package be.iminds.ilabt.jfed.experimenter_gui.preferences;

import be.iminds.ilabt.jfed.preferences.JFedPreferencesApplier;
import be.iminds.ilabt.jfed.util.OSDetector;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.scene.control.*;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.inject.Inject;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * MainPreferencesPane
 */
public class MainPreferencesPane {
    private final static Logger LOG = LoggerFactory.getLogger(MainPreferencesPane.class);

    @FXML
    private StackPane subSectionStackPane;
    @FXML
    private ListView<Label> subSectionListView;

    @FXML
    protected Button saveButton;
    @FXML
    protected Button cancelButton;
    @FXML
    protected Button resetButton;

    @FXML
    protected CheckBox advancedCheckBox;

    private final List<PreferencesSubPane> preferencesSubPanes = new ArrayList<>();

    private final Map<Label, ScrollPane> preferencesSubPanesContainersByLabel = new HashMap<>();
    private final ObservableList<Label> allSubPanes = FXCollections.observableArrayList();
    private final ObservableList<Label> basicSubPanes = FXCollections.observableArrayList();

    private final SubSectionLibrary subSectionLibrary;
    private final JFedPreferencesApplier jFedPreferencesApplier;

    @Inject
    MainPreferencesPane(SubSectionLibrary subSectionLibrary, JFedPreferencesApplier jFedPreferencesApplier) {
        this.subSectionLibrary = subSectionLibrary;

        this.jFedPreferencesApplier = jFedPreferencesApplier;
    }

    private ScrollPane wrapInScrollPane(PreferencesSubPane node) {
        assert node != null;
        ScrollPane container = new ScrollPane(node.getRoot());
        container.setFitToHeight(true);
        container.setFitToWidth(true);
        return container;
    }

    @FXML
    private void initialize() {
        List<PreferencesSubPane> subPanes = subSectionLibrary.filterByOs(OSDetector.findOS()).get();

        LOG.debug("Got the following subpanes: {}", subPanes);

        for (PreferencesSubPane subPane : subPanes) {
            LOG.debug("Initializing subPane {}", subPane != null ? subPane.getClass().getName() : "NULL !!!" );
            ScrollPane subPaneContainer = wrapInScrollPane(subPane);


            subSectionStackPane.getChildren().add(subPaneContainer);

            allSubPanes.add(subPane.getListLabel());
            if (!subPane.isAdvanced())
                basicSubPanes.add(subPane.getListLabel());

            preferencesSubPanesContainersByLabel.put(subPane.getListLabel(), subPaneContainer);
            preferencesSubPanes.add(subPane);

            subPaneContainer.managedProperty().bind(subPaneContainer.visibleProperty());
            subPaneContainer.setVisible(false);
        }

        subSectionListView.setItems(basicSubPanes);
        advancedCheckBox.setSelected(true);

        subSectionListView.getSelectionModel().setSelectionMode(SelectionMode.SINGLE);
        subSectionListView.getSelectionModel().selectedItemProperty().addListener((observableValue, oldSelection, newSelection) -> {
            if (oldSelection != null) {
                if (preferencesSubPanesContainersByLabel.containsKey(oldSelection))
                    preferencesSubPanesContainersByLabel.get(oldSelection).setVisible(false);
                else
                    LOG.warn("preferencesSubPanesByLabel did not contain oldSelection label " + oldSelection + " with text=" + oldSelection.getText());
            }
            if (newSelection != null) {
                if (preferencesSubPanesContainersByLabel.containsKey(newSelection))
                    preferencesSubPanesContainersByLabel.get(newSelection).setVisible(true);
                else
                    LOG.warn("preferencesSubPanesByLabel did not contain newSelection label " + newSelection + " with text=" + newSelection.getText());
            }
        });
        subSectionListView.getSelectionModel().selectFirst();

        advancedCheckBox.selectedProperty().addListener((observableValue, oldValue, newValue) -> setShowAdvanced(newValue));
        setShowAdvanced(advancedCheckBox.isSelected());
    }

    public void setShowAdvanced(boolean showAdvanced) {
        Label selected = subSectionListView.getSelectionModel().getSelectedItem();

        ObservableList<Label> newList;
        if (showAdvanced)
            newList = allSubPanes;
        else
            newList = basicSubPanes;

        subSectionListView.setItems(newList);
        if (selected != null && newList.contains(selected)) {
            subSectionListView.getSelectionModel().select(selected);
        } else
            subSectionListView.getSelectionModel().selectFirst();
    }

    @FXML
    protected void onSaveButtonAction() {
        for (PreferencesSubPane subPane : preferencesSubPanes) {
            boolean ok = subPane.check();
            if (!ok) {
                subSectionListView.getSelectionModel().select(subPane.getListLabel());
                return;
            }
        }

        preferencesSubPanes.forEach(PreferencesSubPane::save);

        jFedPreferencesApplier.applyPreferences();
        onCancelButtonAction();
    }

    @FXML
    protected void onCancelButtonAction() {
        Stage stage = (Stage) cancelButton.getScene().getWindow();
        stage.close();
    }
}
