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

import be.iminds.ilabt.jfed.experiment.ExperimentController;
import be.iminds.ilabt.jfed.experimenter_gui.util.ui.UIUtils;
import be.iminds.ilabt.jfed.fedmon.webapi.service.json.Server;
import be.iminds.ilabt.jfed.lowlevel.TestbedInfoSource;
import be.iminds.ilabt.jfed.lowlevel.authority.AuthorityFinder;
import be.iminds.ilabt.jfed.rspec.model.javafx_impl.FXRspecNode;
import be.iminds.ilabt.jfed.ui.javafx.FXMLUtil;
import be.iminds.ilabt.jfed.ui.javafx.GlyphUtils;
import be.iminds.ilabt.jfed.util.ExecuteOnNotNull;
import javafx.application.Platform;
import javafx.fxml.FXML;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.ButtonType;
import javafx.scene.control.CheckBox;
import javafx.scene.control.Dialog;
import javafx.scene.control.TextField;
import javafx.scene.layout.GridPane;
import javafx.scene.paint.Color;
import javafx.stage.Window;
import org.controlsfx.glyphfont.FontAwesome;
import org.controlsfx.validation.Severity;
import org.controlsfx.validation.ValidationSupport;
import org.controlsfx.validation.Validator;
import org.controlsfx.validation.decoration.GraphicValidationDecoration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.regex.Pattern;

/**
 * User: twalcari
 * Date: 2/2/2015
 * Time: 15:05
 */
public class CreateDiskImageAction extends ExperimentAction {
    private static final Logger LOG = LoggerFactory.getLogger(CreateDiskImageAction.class);

    private static final Pattern DISK_IMAGE_PATTERN = Pattern.compile("[A-Za-z0-9_-]{1,30}");

    private final FXRspecNode node;
    private final TestbedInfoSource testbedInfoSource;
    private final AuthorityFinder authorityFinder;
    private static final boolean GLOBAL = true;


    CreateDiskImageAction(Window parentWindow, ExperimentController experimentController, FXRspecNode node,
                          TestbedInfoSource testbedInfoSource,
                          AuthorityFinder authorityFinder) {
        super(parentWindow, experimentController);
        this.node = node;
        this.testbedInfoSource = testbedInfoSource;
        this.authorityFinder = authorityFinder;
    }

    @Override
    public void run() {
        assert (Platform.isFxApplicationThread());

        new CreateDiskImageDialog().showDialog();

    }

    private class CreateDiskImageDialog extends GridPane {
        private final Dialog<ButtonType> dialog;

        @FXML
        private TextField textField;
        @FXML
        private CheckBox prepareImageCheckBox;


        CreateDiskImageDialog() {
            FXMLUtil.injectFXML(this);
            dialog = new Dialog<>();
            dialog.initOwner(parentWindow);
            dialog.setTitle("Create a Disk Image of " + node.getClientId());
            dialog.setHeaderText("Create a Disk Image of " + node.getClientId());
            dialog.setGraphic(GlyphUtils.createDialogGlyph(FontAwesome.Glyph.UPLOAD, Color.GREEN));

            dialog.getDialogPane().setContent(UIUtils.wrapWithDecorationPane(this));
            dialog.getDialogPane().getButtonTypes().setAll(ButtonType.OK, ButtonType.CANCEL);

            dialog.resultProperty().addListener(observable -> {
                if (dialog.getResult() == ButtonType.OK)
                    createDiskImage();
            });

            ValidationSupport validationSupport = new ValidationSupport();
            validationSupport.registerValidator(textField,
                    Validator.createRegexValidator("Please provide a valid disk image name!", DISK_IMAGE_PATTERN, Severity.ERROR));
            validationSupport.setValidationDecorator(new GraphicValidationDecoration());

            Node okButton = dialog.getDialogPane().lookupButton(ButtonType.OK);
            okButton.disableProperty().bind(validationSupport.invalidProperty());

            new ExecuteOnNotNull<Scene>(this.sceneProperty()) {
                @Override
                public void run() {
                    Platform.runLater(textField::requestFocus);
                }
            };

        }

        private void createDiskImage() {

            Server auth =
                    authorityFinder.findByUrn(node.getComponentManagerId(), AuthorityFinder.Purpose.CREATE_SLIVER); //same as createsliver
            if (auth == null) {
                LOG.error("Could not fetch authority info for node {} with componentManagerId {}",
                        node.getClientId(), node.getComponentManagerId());
                return;
            }

            experimentController.createDiskImage(node, getDiskImageName(), GLOBAL, isPrepareImage());
        }

        public String getDiskImageName() {
            return textField.getText();
        }

        public boolean isPrepareImage() {
            return prepareImageCheckBox.isSelected();
        }


        public void showDialog() {
            dialog.show();
        }

    }


}
