package be.iminds.ilabt.jfed.experimenter_gui.preferences.subsections;

import be.iminds.ilabt.jfed.experimenter_gui.preferences.AbstractPreferencesSubPane;
import be.iminds.ilabt.jfed.fedmon.webapi.service.json.Server;
import be.iminds.ilabt.jfed.fedmon.webapi.service.json.Service;


import be.iminds.ilabt.jfed.lowlevel.ApiInfo;
import be.iminds.ilabt.jfed.lowlevel.GeniUserProvider;
import be.iminds.ilabt.jfed.lowlevel.TestbedInfoSource;
import be.iminds.ilabt.jfed.preferences.JFedGuiPreferences;
import be.iminds.ilabt.jfed.ui.javafx.choosers.ServerChooser;
import be.iminds.ilabt.jfed.ui.javafx.dialogs.JFDialogs;
import be.iminds.ilabt.jfed.util.GeniUrn;
import javafx.beans.InvalidationListener;
import javafx.fxml.FXML;
import javafx.scene.Node;
import javafx.scene.control.Label;
import javafx.scene.control.RadioButton;
import javafx.scene.control.TextField;
import javafx.scene.layout.BorderPane;

import javax.inject.Inject;
import java.net.MalformedURLException;
import java.net.URL;

/**
 * ScsPane
 */
public class ScsPane extends AbstractPreferencesSubPane {
    private final GeniUserProvider geniUserProvider;
    private final TestbedInfoSource testbedInfoSource;
    private final JFedGuiPreferences jFedPreferences;
    @FXML protected Label prefSCSLabel;
    @FXML protected RadioButton autoScsRadioButton;
    @FXML protected RadioButton authScsRadioButton;
    @FXML protected RadioButton urlScsRadioButton;
    @FXML protected ServerChooser scsAuthChooserController;
    @FXML protected Label scsUrlLabel;
    @FXML protected Label scsUrlChooseLabel;
    @FXML protected TextField scsUrlField;

    @FXML
    private BorderPane root;

    @Override
    public Node getRoot() {
        return root;
    }

    @Inject
    ScsPane(GeniUserProvider geniUserProvider, TestbedInfoSource testbedInfoSource, JFedGuiPreferences jFedPreferences) {
        super("SCS", true);
        this.geniUserProvider = geniUserProvider;
        this.testbedInfoSource = testbedInfoSource;
        this.jFedPreferences = jFedPreferences;
    }

    @FXML
    private void initialize() {

        scsAuthChooserController.showEditListButtonProperty().setValue(false);

        scsAuthChooserController.getRoot().managedProperty().bind(scsAuthChooserController.getRoot().visibleProperty());
        scsUrlLabel.managedProperty().bind(scsUrlLabel.visibleProperty());
        scsUrlChooseLabel.managedProperty().bind(scsUrlChooseLabel.visibleProperty());
        scsUrlField.managedProperty().bind(scsUrlField.visibleProperty());

        scsUrlChooseLabel.visibleProperty().bind(scsUrlField.visibleProperty());

        scsAuthChooserController.getRoot().visibleProperty().bind(authScsRadioButton.selectedProperty());
        scsUrlField.visibleProperty().bind(urlScsRadioButton.selectedProperty());
        scsUrlLabel.visibleProperty().bind(autoScsRadioButton.selectedProperty().or(authScsRadioButton.selectedProperty()));

        scsAuthChooserController.setServerFilter(server -> ApiInfo.hasService(server, ApiInfo.ApiName.GENI_SCS, 1));

        InvalidationListener updateUrl = observable -> {
            if (authScsRadioButton.isSelected()) {
                Server newSelectedServer = scsAuthChooserController.getSelectedServer();
                if (newSelectedServer == null) {
                    scsUrlLabel.setText("Error: no SCS selected.");
                    return;
                }
                URL scsUrl = ApiInfo.findUrl(newSelectedServer, ApiInfo.ApiName.GENI_SCS, 1);
                if (scsUrl == null) {
                    scsUrlLabel.setText("Error: selected authority has no SCS URL");
                    return;
                }
                scsUrlLabel.setText("URL: "+scsUrl);

                //for convenience, so that something is added to the field
                if (scsUrlField.getText().trim().isEmpty())
                    scsUrlField.setText(scsUrl+"");
            }
        };

        scsAuthChooserController.selectedAuthorityProperty().addListener(updateUrl);
        authScsRadioButton.selectedProperty().addListener(updateUrl);


        autoScsRadioButton.selectedProperty().addListener((observableValue, aBoolean, newIsSelected) -> {
            if (newIsSelected) {
                Server userAuthServer = this.geniUserProvider.getLoggedInGeniUser().getUserAuthorityServer();
                Integer scsId = userAuthServer.getDefaultScsId();
//                assert scsId != null;
                Service scsService = scsId == null ? null : testbedInfoSource.getServiceById(scsId);
//                assert scsService != null;
                GeniUrn scsUrn = scsService == null ? null : scsService.getUrnAsGeniUrn();
//                Server scsServer = scsService.getServer();
                if (scsService == null)
                    scsUrlLabel.setText("Error: user authority has an invalid SCS: id="+scsId);
                else {
                    URL scsUrl = null;
                    try {
                        scsUrl = new URL(scsService.getUrl());
                    } catch (MalformedURLException e) {
                        throw new RuntimeException("Should never get this error here: TestbedInfoSource should prevent this on init.", e);
                    }
                    if (scsUrl == null)
                        scsUrlLabel.setText("Error: user authority has no SCS URL");
                    else {
                        scsUrlLabel.setText("URL: "+scsUrl);

                        //for convenience, so that something is added to the field
                        if (scsUrlField.getText().trim().isEmpty())
                            scsUrlField.setText(scsUrl+"");
                    }
                }
            }
        });
        urlScsRadioButton.selectedProperty().addListener((observableValue, aBoolean, newIsSelected) -> {
            if (newIsSelected && scsUrlField.getText().trim().isEmpty()) {
                //scsUrlField.setText(scsUrl+"");
                scsUrlField.setText("http://MYSCS:8081/geni/xmlrpc");
            }
        });

        //start with auto selected. Then update from selection
        autoScsRadioButton.setSelected(true);

        URL scsUrl = jFedPreferences.getScsUrl();
        GeniUrn scsUrn = jFedPreferences.getScsUrn();
        if (scsUrn != null) {
            authScsRadioButton.setSelected(true);
            Server selectedAuth = jFedPreferences.getScsAuthority(testbedInfoSource);
            if (selectedAuth != null)
                scsAuthChooserController.select(selectedAuth);
        } else {
            if (scsUrl != null) {
                scsUrlField.setText(scsUrl+"");
                urlScsRadioButton.setSelected(true);
            } else {
                //trigger listener
                autoScsRadioButton.setSelected(false);
                autoScsRadioButton.setSelected(true);
            }
        }
    }
    @Override
    public boolean check() {
        if (urlScsRadioButton.isSelected()) {
            String urlTxt = scsUrlField.getText().trim();
            try {
                new URL(urlTxt);
            } catch (MalformedURLException e) {
                JFDialogs.create()
                        .owner(root)
                        .message("The provided SCS URL is not a valid URL")
                        .showError();
                return false;
            }
        }

        return true;
    }
    @Override
    public boolean save() {
        if (autoScsRadioButton.isSelected())
            jFedPreferences.setScs((URL) null);
        if (authScsRadioButton.isSelected()) {
            Server auth = scsAuthChooserController.getSelectedServer();
            jFedPreferences.setScs(auth);
        }
        if (urlScsRadioButton.isSelected()) {
            String urlTxt = scsUrlField.getText().trim();
            try {
                URL u = new URL(urlTxt);
                jFedPreferences.setScs(u);
            } catch (MalformedURLException e) {
                JFDialogs.create()
                        .owner(root)
                        .message("The provided SCS URL is not a valid URL")
                        .showError();
                return false;
            }
        }


        return true;
    }
}
