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

import be.iminds.ilabt.jfed.rspec.convert.RspecConverter;
import be.iminds.ilabt.jfed.rspec.model.ModelRspecType;
import be.iminds.ilabt.jfed.rspec.model.RspecFactory;
import be.iminds.ilabt.jfed.rspec.model.RspecFactoryFactory;
import be.iminds.ilabt.jfed.rspec.model.javafx_impl.FXModelRspec;
import be.iminds.ilabt.jfed.rspec.rspec_source.RequestRspecSource;
import javafx.scene.control.Alert;
import javafx.scene.control.ButtonBar;
import javafx.scene.control.ButtonType;
import javafx.stage.Window;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Objects;

/**
 * User: twalcari
 * Date: 1/22/2015
 * Time: 17:01
 */
public class IsRequestValidator implements RspecValidator {
    private static final Logger LOG = LoggerFactory.getLogger(IsRequestValidator.class);

    @Override
    public RspecValidationResult validateRSpec(RspecCheckReason reason, RequestRspecSource requestRspecSource, Window dialogOwner) {
        if (Objects.equals(requestRspecSource.getModelRspec(ModelRspecType.FX).getType(), "manifest")) {
            String abortText = "Abort";
            String fixText = "Convert to Request and continue";
            String ignoreText = "Keep as is and continue";

            boolean showIgnore = false;
            switch (reason) {
                case SWITCH_TO_VISUAL_EDITOR: {
                    return null; //no action needed
                }
                case RUN_EXPERIMENT: {
                    abortText = "Abort and continue editing";
                    ignoreText = "Ignore and Run Experiment Anyway";
                    fixText = "Convert to Request and Run Experiment";
                    showIgnore = true;
                    break;
                }
                case CHECK_RSPEC: {
                    abortText = "Keep as is";
                    fixText = "Convert to Request";
                    showIgnore = false;
                    break;
                }
                case OPENED_FILE: {
                    abortText = "Keep as is";
                    fixText = "Convert to Request";
                    showIgnore = false;
                    break;
                }
            }

            ButtonType fixButtonType = new ButtonType(fixText, ButtonBar.ButtonData.YES);
            ButtonType ignoreButtonType = new ButtonType(ignoreText, ButtonBar.ButtonData.CANCEL_CLOSE);
            ButtonType abortButtonType = new ButtonType(abortText, ButtonBar.ButtonData.CANCEL_CLOSE);

            Alert alert = new Alert(Alert.AlertType.ERROR);
            alert.initOwner(dialogOwner);
            alert.setContentText("Problem in RSpec:\n" +
                                    "This is a manifest RSpec, and not a request RSpec.\n\n" +
                                    "Do you want to convert the manifest to a request?"
                    )            ;
            alert.setTitle("Not a Request RSpec");
            if (showIgnore)
                alert.getButtonTypes().setAll(fixButtonType, ignoreButtonType, abortButtonType);
            else
                alert.getButtonTypes().setAll(fixButtonType, abortButtonType);
            ButtonType chosenAction = alert.showAndWait().orElse(null);

            if (chosenAction == fixButtonType) {
                LOG.info("Converting to Request RSpec");
                RspecConverter converter = new RspecConverter();

                RspecFactory rspecFactory = RspecFactoryFactory.getRspecFactoryInstance(ModelRspecType.FX);

                ButtonType boundNodes = new ButtonType("Keep All Bindings", ButtonBar.ButtonData.OTHER);
                ButtonType unboundNodes = new ButtonType("Remove Resource Bindings",  ButtonBar.ButtonData.OTHER);
                ButtonType unboundCMs = new ButtonType("Remove all Bindings",  ButtonBar.ButtonData.OTHER);
                Alert bindingAlert= new Alert(Alert.AlertType.CONFIRMATION);
                bindingAlert.initOwner(dialogOwner) ;
                bindingAlert.setContentText("In a manifest, all nodes are bound to a specific resource.\nIn a request, this is optional.\n" +
                                                    "You can also remove the component manager bindings (thus creating an unbound RSpec).\n" +
                                                    "What do you want to do when converting to a request RSpec?\n"
                                    );
                bindingAlert.setTitle("Convert To Request Options");

                bindingAlert.getButtonTypes().setAll(boundNodes, unboundNodes, unboundCMs);
                ButtonType chosenBinding = bindingAlert.showAndWait().orElse(null);
                boolean keepNodeBindings = chosenBinding == boundNodes;

                FXModelRspec newModel = (FXModelRspec) converter.convertManifestToRequest(requestRspecSource.getModelRspec(ModelRspecType.FX), keepNodeBindings, rspecFactory);
                if (chosenBinding == unboundCMs)
                    newModel = (FXModelRspec) converter.removeComponentManagerBindings(newModel, rspecFactory);

                return new RspecValidationResult(newModel);
            } else if (chosenAction == ignoreButtonType) {
                return new RspecValidationResult(requestRspecSource, false /* == ignore */);

            } else if (chosenAction == abortButtonType || chosenAction == null) {
                return new RspecValidationResult(requestRspecSource, true/* == abort*/);
            }
        }

        return null;
    }
}
