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

import be.iminds.ilabt.jfed.experimenter_gui.config.JFedGuiConfig;
import be.iminds.ilabt.jfed.experimenter_gui.editor.actions.EditorActionsFactory;
import be.iminds.ilabt.jfed.experimenter_gui.editor.ribbon_tabs.ControlEditorRibbonTab;
import be.iminds.ilabt.jfed.experimenter_gui.editor.ribbon_tabs.RspecEditorRibbonTab;
import be.iminds.ilabt.jfed.experimenter_gui.editor.ribbon_tabs.TopologyEditorRibbonTab;
import be.iminds.ilabt.jfed.experimenter_gui.editor.views.EditorViewsFactory;
import be.iminds.ilabt.jfed.experimenter_gui.tabs.AskOnCloseRequest;
import be.iminds.ilabt.jfed.experimenter_gui.tabs.RibbonEnabled;
import be.iminds.ilabt.jfed.experimenter_gui.tabs.StatusEnabled;
import be.iminds.ilabt.jfed.experimenter_gui.ui.ribbon.RibbonTab;

import be.iminds.ilabt.jfed.lowlevel.TestbedInfoSource;
import be.iminds.ilabt.jfed.ui.javafx.GlyphUtils;
import be.iminds.ilabt.jfed.ui.javafx.dialogs.JFDialogs;
import javafx.beans.property.StringProperty;
import javafx.scene.control.*;
import org.controlsfx.glyphfont.FontAwesome;
import org.controlsfx.glyphfont.Glyph;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

/**
 * User: twalcari
 * Date: 11/7/13
 * Time: 4:58 PM
 */
public class ExperimentEditorTab extends Tab implements RibbonEnabled, StatusEnabled, AskOnCloseRequest {
    private static final Logger LOG = LoggerFactory.getLogger(ExperimentEditorTab.class);

    private final static List<RibbonTab> ribbonTabs;
    private final ExperimentEditor experimentEditor;

    private static final RspecEditorRibbonTab rspecEditorRibbonTab;
    private static final TopologyEditorRibbonTab topologyEditorRibbonTab;
    private static final ControlEditorRibbonTab controlEditorRibbonTab;

    private final EditableRspec editableRspec;

    static {
        ribbonTabs = new ArrayList<>();

        rspecEditorRibbonTab = new RspecEditorRibbonTab();
        topologyEditorRibbonTab = new TopologyEditorRibbonTab(rspecEditorRibbonTab);
        controlEditorRibbonTab = new ControlEditorRibbonTab(rspecEditorRibbonTab);

        ribbonTabs.add(topologyEditorRibbonTab);
        ribbonTabs.add(rspecEditorRibbonTab);
        ribbonTabs.add(controlEditorRibbonTab);
    }

    ExperimentEditorTab(EditableRspec editableRspec, TestbedInfoSource testbedInfoSource, JFedGuiConfig config, EditorViewsFactory editorViewsFactory,
                        EditorActionsFactory editorActionsFactory, JFedGuiConfig jFedConfiguration) {
        this.editableRspec = editableRspec;

        rspecEditorRibbonTab.setAuthorityList(testbedInfoSource);
        rspecEditorRibbonTab.setJFedGuiConfig(jFedConfiguration);

        textProperty().bind(editableRspec.nameProperty());

        getStyleClass().add("tab-experiment-design");

        //FIXME Temporary fix until https://bitbucket.org/controlsfx/controlsfx/pull-request/452/fix-edit-and-pencil_square_alt-fontawesome/diff is accepted
        setGraphic(new Glyph("FontAwesome", '\uf044')); // GlyphUtils.createGlyph(FontAwesome.Glyph.PENCIL_SQUARE_ALT));

        ContextMenu contextMenu = new ContextMenu();
        MenuItem changeNameMenuItem = new MenuItem("Change name", GlyphUtils.createGlyph(FontAwesome.Glyph.PENCIL));
        changeNameMenuItem.setOnAction(actionEvent -> showEditNameDialog());
        contextMenu.getItems().add(changeNameMenuItem);
        setContextMenu(contextMenu);

        this.experimentEditor =
                new ExperimentEditor(editableRspec, testbedInfoSource, config, editorViewsFactory, editorActionsFactory);

        setContent(experimentEditor);
    }

    private void showEditNameDialog() {
        JFDialogs.create()
                .owner(this.getExperimentEditor())
                .message("Enter a new name:")
                .masthead("Change Experiment Definition name")
                .title("Change Experiment Definition name")
                .showTextInput(editableRspec.getName())
                .filter(x -> !x.isEmpty())
                .ifPresent(editableRspec::setName);
    }

    public ExperimentEditor getExperimentEditor() {
        return experimentEditor;
    }

    @Override
    public List<? extends RibbonTab> getRibbonTabs() {
        return ribbonTabs;
    }

    @Override
    public RibbonTab getInitialTabToActivate() {
        switch (experimentEditor.getCurrentEditorViewType()) {
            case RAW:
                return rspecEditorRibbonTab;
            case CONTROLLER:
                return controlEditorRibbonTab;
            case CANVAS:
            default:
                return topologyEditorRibbonTab;
        }
    }

    @Override
    public StringProperty statusProperty() {
        return experimentEditor.statusProperty();
    }

    @Override
    public boolean onTabCloseRequest() {
        if (experimentEditor.isDirty()) {

            Alert saveAlert = new Alert(Alert.AlertType.CONFIRMATION);
            saveAlert.setTitle("Unsaved changes");
            saveAlert.setHeaderText("Unsaved changes");
            saveAlert.setContentText("Do you want to save changes you made to " +
                    experimentEditor.getEditableRspec().getName() + "?");

            ButtonType saveButtonType = new ButtonType("Save", ButtonBar.ButtonData.YES);
            ButtonType dontSaveButtonType = new ButtonType("Don't save", ButtonBar.ButtonData.NO);
            saveAlert.getButtonTypes().setAll(saveButtonType, dontSaveButtonType, ButtonType.CANCEL);

            Optional<ButtonType> result = saveAlert.showAndWait();

            if (!result.isPresent() || result.get() == ButtonType.CANCEL) {
                return false;
            } else if (result.get() == saveButtonType) {
                experimentEditor.save();
                return true;
            } else return true;// user pressed dontSaveButtonType. The user doesn't want to save it's changes..
        } else return true;
    }
}
