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

import be.iminds.ilabt.jfed.experiment.ExperimentState;
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.preferences.GuiPreferenceKey;
import be.iminds.ilabt.jfed.preferences.JFedPreferences;
import be.iminds.ilabt.jfed.ui.javafx.GlyphUtils;
import be.iminds.ilabt.jfed.util.GeniUrn;
import javafx.application.Platform;
import javafx.beans.value.ObservableStringValue;
import javafx.collections.ObservableMap;
import javafx.scene.control.*;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import org.controlsfx.glyphfont.FontAwesome;
import org.controlsfx.glyphfont.GlyphFont;
import org.controlsfx.glyphfont.GlyphFontRegistry;

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

/**
 * User: twalcari
 * Date: 11/19/13
 * Time: 5:10 PM
 */
public class ExperimentViewControllerTab extends Tab implements StatusEnabled, RibbonEnabled, AskOnCloseRequest {

    private static final GlyphFont fontAwesome = GlyphFontRegistry.font("FontAwesome");
    private final ObservableMap<GeniUrn, ExperimentViewController> experimentViewControllers;

    private final ExperimentViewController experimentViewController;
    private final SliceRibbonTabs sliceRibbonTabs;
    private final JFedPreferences jFedPreferences ;


    //instance initializer
    {
        setGraphic(fontAwesome.create(FontAwesome.Glyph.PLAY_CIRCLE));

    }

    public ExperimentViewControllerTab(final ExperimentViewController experimentViewController,
                                       ObservableMap<GeniUrn, ExperimentViewController> experimentViewControllers,
                                       SliceRibbonTabs sliceRibbonTabs) {
        this.experimentViewController = experimentViewController;
        this.experimentViewControllers = experimentViewControllers;
        this.sliceRibbonTabs = sliceRibbonTabs;

        assert experimentViewController != null;
        this.jFedPreferences = experimentViewController.getjFedPreferences();

        setContent(experimentViewController);
        setText(experimentViewController.getExperiment().getName());

        TabStyle.updateTabStyle(this, experimentViewController.getExperiment().getExperimentState());
        experimentViewController.getExperiment().experimentStateProperty().addListener(observable -> Platform.runLater(() -> TabStyle.updateTabStyle(this, experimentViewController.getExperiment().getExperimentState())));
    }

    public ExperimentViewController getExperimentViewController() {
        return experimentViewController;
    }

    @Override
    public ObservableStringValue statusProperty() {
        return experimentViewController.statusProperty();
    }

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

    @Override
    public RibbonTab getInitialTabToActivate() {
        if (experimentViewController.isControllerVisible())
            return sliceRibbonTabs.getControlViewerRibbonTab();
        else if (experimentViewController.isRawRspecVisible())
            return sliceRibbonTabs.getRspecViewerRibbonTab();
        else
            return sliceRibbonTabs.getTopologyViewerRibbonTab();
    }

    @Override
    public boolean onTabCloseRequest() {
        if (getExperimentViewController().getExperiment().getExperimentState().isActiveState()) {
            if (jFedPreferences.getBoolean(GuiPreferenceKey.PREF_SHOW_CLOSE_TAB_WARNING_DIALOG, true)) {
                VBox pane = new VBox();
                pane.setSpacing(5);

                Label textLabel = new Label(String.format("There are currently resources in use by '%s'. " + "\n"+
                                                        "Are you sure you want to close this tab?"+ "\n\n"+
                                                        "If you close it, you will still be able to access the resources later by using jFed's \"Recover\" function. " ,
                                                getExperimentViewController().getExperiment().getName()));
                textLabel.setWrapText(true);
                pane.getChildren().add(textLabel);
                final CheckBox checkBox = new CheckBox("Do not show this dialog again");
                pane.getChildren().add(checkBox);

                DialogPane dialogPane = new DialogPane();
                dialogPane.setHeaderText("Resources in use");
                dialogPane.setGraphic(GlyphUtils.createDialogGlyph(FontAwesome.Glyph.WARNING, Color.ORANGE));
                dialogPane.setContent(pane);
                dialogPane.getButtonTypes().setAll(ButtonType.YES, ButtonType.NO);

                Dialog<ButtonType> dialog = new Dialog<>();
                dialog.setTitle("Resources in use");
                dialog.setDialogPane(dialogPane);

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

                if (result.isPresent() && result.get() != ButtonType.YES) {
                    return false;
                } else {
                    jFedPreferences.setBoolean(GuiPreferenceKey.PREF_SHOW_CLOSE_TAB_WARNING_DIALOG,
                            !checkBox.isSelected());

                    experimentViewController.getTimelineView().getController().unregister();
                    experimentViewControllers.remove(experimentViewController.getExperiment().getSlice().getUrn());
                    return true;
                }
            } else {
                experimentViewController.getTimelineView().getController().unregister();
                experimentViewControllers.remove(experimentViewController.getExperiment().getSlice().getUrn());
                return true;
            }
        } else
            return true;
    }



    public enum TabStyle {

        FUTURE_RESERVATION("tab-experiment-future-reservation"),
        RUNNING("tab-experiment-execution"),
        EXPIRED("tab-experiment-execution-expired"),
        FAILED("tab-experiment-execution-terminated");


        private final String styleClass;

        TabStyle(String styleClass) {
            this.styleClass = styleClass;
        }


        public static void updateTabStyle(Tab tab, ExperimentState newState) {
            for (TabStyle tabStyle : TabStyle.values()) {
                tab.getStyleClass().remove(tabStyle.styleClass);
            }

            TabStyle newTabStyle;
            switch (newState) {
                case FUTURE_RESERVATION:
                    newTabStyle = TabStyle.FUTURE_RESERVATION;
                    break;
                case FAILING:
                case FAILED:
                    newTabStyle = TabStyle.FAILED;
                    break;
                case EXPIRED:
                case EMPTY:
                    newTabStyle = TabStyle.EXPIRED;
                    break;
                default:
                    newTabStyle = TabStyle.RUNNING;
                    break;
            }

            tab.getStyleClass().add(newTabStyle.styleClass);
        }
    }
}
