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

import be.iminds.ilabt.jfed.experimenter_gui.util.ui.TextFieldWithStatus;
import be.iminds.ilabt.jfed.rspec.model.SliverType;
import be.iminds.ilabt.jfed.rspec.model.SliverTypeBuilder;
import be.iminds.ilabt.jfed.rspec.model.javafx_impl.FXRspecNode;
import be.iminds.ilabt.jfed.ui.javafx.FXMLUtil;
import javafx.fxml.FXML;
import javafx.scene.control.CheckBox;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Objects;

/**
 * User: twalcari
 * Date: 9/10/2014
 * Time: 09:44
 */
public class XenTab extends AdaptivePropertiesTab<FXRspecNode> {
    private static final Logger LOG = LoggerFactory.getLogger(XenTab.class);

    private final AdaptivePropertiesDialog adaptivePropertiesDialog;

    @FXML private CheckBox coresCheckBox;
    @FXML private CheckBox ramCheckBox;
    @FXML private CheckBox diskCheckBox;
    @FXML private TextFieldWithStatus coresField;
    @FXML private TextFieldWithStatus ramField;
    @FXML private TextFieldWithStatus diskField;

    public XenTab(AdaptivePropertiesDialog adaptivePropertiesDialog) {
        super("Xen Options");
        this.adaptivePropertiesDialog = adaptivePropertiesDialog;

        setContent(FXMLUtil.createFromFXML(this));

        coresField.disableProperty().bind(coresCheckBox.selectedProperty().not());
        ramField.disableProperty().bind(ramCheckBox.selectedProperty().not());
        diskField.disableProperty().bind(diskCheckBox.selectedProperty().not());

        coresCheckBox.selectedProperty().addListener((observableValue, aBoolean, aBoolean2) -> {
            if (coresCheckBox.isSelected() && coresField.getText().trim().isEmpty())
                coresField.setText("1");
        });
        ramCheckBox.selectedProperty().addListener((observableValue, aBoolean, aBoolean2) -> {
            if (ramCheckBox.isSelected() && ramField.getText().trim().isEmpty())
                ramField.setText("512");
        });
        diskCheckBox.selectedProperty().addListener((observableValue, aBoolean, aBoolean2) -> {
            if (diskCheckBox.isSelected() && diskField.getText().trim().isEmpty())
                diskField.setText("8");
        });
    }

    @Override
    public void load(FXRspecNode rspecNode) {
        SliverType sliverType = rspecNode.getSliverType();
        Integer cores = sliverType == null ? null : sliverType.getXenCores();
        Integer ram = sliverType == null ? null : sliverType.getXenRam();
        Integer disk = sliverType == null ? null : sliverType.getXenDisk();

        coresCheckBox.setSelected(cores != null);
        ramCheckBox.setSelected(ram != null);
        diskCheckBox.setSelected(disk != null);

        coresField.setText(cores == null ? "" : (cores+""));
        ramField.setText(ram == null ? "" : (ram+""));
        diskField.setText(disk == null ? "" : (disk+""));
    }

    @Override
    public void save(FXRspecNode rspecNode) {
        try {
            Integer cores = coresCheckBox.isSelected() ? Integer.parseInt(coresField.getText()) : null;
            Integer ram = ramCheckBox.isSelected() ? Integer.parseInt(ramField.getText()) : null;
            Integer disk = diskCheckBox.isSelected() ? Integer.parseInt(diskField.getText()) : null;

            SliverType sliverType = rspecNode.getSliverType();
            if (sliverType != null) {
                SliverType newSliverType = new SliverTypeBuilder(sliverType).xenCores(cores).xenDisk(disk).xenRam(ram).build();
                rspecNode.setSliverType(newSliverType);
            } else
                LOG.warn("XenTab.save() could not set sliver type: original sliver type is null");
        } catch (NumberFormatException e) {
            LOG.warn("XenTab.save() User integer input is invalid: Will not change sliver type", e);
        }
    }

    @Override
    public void onTabShown() {

    }

    @Override
    public boolean shouldBeVisible(FXRspecNode rspecNode) {
        return Objects.equals("emulab-xen", adaptivePropertiesDialog.getCurrentSliverTypeName());
    }

    @Override
    public String validateConfiguration() {
        String errors = "";
        try {
            Integer cores = coresCheckBox.isSelected() ? Integer.parseInt(coresField.getText()) : null;
            coresField.setStatus(TextFieldWithStatus.Status.OK);
        } catch (NumberFormatException e) {
            coresField.setStatus(TextFieldWithStatus.Status.ERROR);
            errors += "Invalid integer in cores field";
        }
        try {
            Integer ram = ramCheckBox.isSelected() ? Integer.parseInt(ramField.getText()) : null;
            ramField.setStatus(TextFieldWithStatus.Status.OK);
        } catch (NumberFormatException e) {
            ramField.setStatus(TextFieldWithStatus.Status.ERROR);
            if (!errors.isEmpty()) errors += "\n";
            errors += "Invalid integer in RAM field";
        }
        try {
            Integer disk = diskCheckBox.isSelected() ? Integer.parseInt(diskField.getText()) : null;
            diskField.setStatus(TextFieldWithStatus.Status.OK);
        } catch (NumberFormatException e) {
            diskField.setStatus(TextFieldWithStatus.Status.ERROR);
            if (!errors.isEmpty()) errors += "\n";
            errors +=  "Invalid integer in disk field";
        }
        if (errors.isEmpty())
            return null;
        else
            return errors;
    }


    public void onHelpLinkClicked() {
        if(java.awt.Desktop.isDesktopSupported())
        {
            try {
                java.awt.Desktop.getDesktop().browse(new URI("http://doc.ilabt.iminds.be/ilabt-documentation/urnsrspecs.html#xen-vm-options"));
            } catch (IOException | URISyntaxException e) {
                LOG.warn("Exception starting browser", e);
            }
        }
    }
}
