package be.iminds.ilabt.jfed.ui.javafx.userlogin;

import be.iminds.ilabt.jfed.fedmon.webapi.service.json.Server;
import be.iminds.ilabt.jfed.lowlevel.GeniUser;
import be.iminds.ilabt.jfed.lowlevel.authority.AuthorityFinder;
import be.iminds.ilabt.jfed.lowlevel.user.*;
import be.iminds.ilabt.jfed.lowlevel.userloginmodel.InvalidLoginException;
import be.iminds.ilabt.jfed.lowlevel.ssh_key_info.putty.PpkHelper;
import be.iminds.ilabt.jfed.ui.javafx.choosers.ServerChooser;
import be.iminds.ilabt.jfed.ui.javafx.dialogs.JFDialogs;
import be.iminds.ilabt.jfed.ui.javafx.x509_certificate_gui.X509CertificatePanel;
import be.iminds.ilabt.jfed.util.GeniUrn;
import be.iminds.ilabt.jfed.util.JFedCommonDialogs;
import javafx.beans.binding.BooleanBinding;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.fxml.FXML;
import javafx.scene.Parent;
import javafx.scene.control.*;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.FileChooser;
import javafx.stage.Stage;
import org.slf4j.LoggerFactory;

import javax.annotation.Nonnull;
import javax.inject.Inject;
import javax.inject.Named;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.security.cert.CertificateExpiredException;
import java.security.cert.CertificateNotYetValidException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;

/**
 * UserLoginController
 */
public class AdvancedUserLoginController {
    private static final org.slf4j.Logger LOG = LoggerFactory.getLogger(AdvancedUserLoginController.class);

    private final UserLoginInfoManager userLoginInfoManager;
    private final UserLoginInfoFactory userLoginInfoFactory;
    private final AuthorityFinder authorityFinder;
    private final ObjectProperty<UserLoginInfo> userLoginInfo = new SimpleObjectProperty<>();

    private final boolean requireAllUserInfo;
    @FXML
    private Parent defaultLoginPanel;
    @FXML
    private RadioButton pemKeyCertInputFromFileRadioButton;
    @FXML
    private RadioButton pemKeyCertInputFromURLRadioButton;
    @FXML
    private RadioButton pemKeyCertInputFromStringRadioButton;
    @FXML
    private Button pemKeyCertInputFromFileLoadButton;
    @FXML
    private Button pemKeyCertInputFromURLLoadButton;
    @FXML
    private HBox defaultLoginPanelPasswordBox;
    @FXML
    private Button defaultLoginPanelPasswordButton;
    @FXML
    private TextArea pemKeyCertContentTextArea;
    @FXML
    private TextField defaultLoginPanelPassword;
    @FXML
    private TextField pemKeyCertInputFromFileField;
    @FXML
    private HBox pemKeyCertInputFromFileBox;
    @FXML
    private TextField pemKeyCertInputFromURLField;
    @FXML
    private HBox pemKeyCertInputFromURLBox;
    @FXML
    private Label defaultLoginPanelSliceAuthName;
    @FXML
    private Label defaultLoginPanelSliceAuthUrn;
    @FXML
    private Label defaultLoginPanelUsername;
    @FXML
    private Label defaultLoginPanelUserUrn;
    @FXML
    private Button loginButton;
    @FXML
    private Button logoutButton;
    @FXML
    private VBox errorLogBox;
    @FXML
    private TextArea errorLog;
    @FXML
    private Label missingInfoWarningLabel;
    @FXML
    private Label missingInfoErrorLabel;
    @FXML
    private Parent derivedCertificateDetails;
    @FXML
    private Parent manualCertificateDetails;
    @FXML
    private ServerChooser defaultLoginPanelSliceAuthNameChooserController;
    @FXML
    private TextField defaultLoginPanelUserUrnField;
    @FXML
    private RadioButton loginTypeKeyCertAutoRadioButton;
    @FXML
    private RadioButton loginTypeKeyCertManualRadioButton;
    @FXML
    private Button certificateDetailsButton;
    /**
     * Copy settings from userLoginInfoManager to GUI
     */
    private boolean blockModelToGUI_eventhelper = false;
    private boolean blockTextAreaUpdate_eventhelper = false;

    private GeniUser result = null;

    @Inject
    public AdvancedUserLoginController(UserLoginInfoManager userLoginInfoManager,
                                       UserLoginInfoFactory userLoginInfoFactory,
                                       AuthorityFinder authorityFinder,
                                       @Named("loginRequiresAlluserInfo") Boolean loginRequiresAlluserInfo) {
        this.userLoginInfoManager = userLoginInfoManager;
        this.userLoginInfoFactory = userLoginInfoFactory;
        this.authorityFinder = authorityFinder;
        this.requireAllUserInfo = loginRequiresAlluserInfo;
    }

    @FXML
    public void initialize() {
        derivedCertificateDetails.visibleProperty().bind(loginTypeKeyCertAutoRadioButton.selectedProperty());
        manualCertificateDetails.visibleProperty().bind(loginTypeKeyCertManualRadioButton.selectedProperty());

        pemKeyCertInputFromFileBox.visibleProperty().bind(pemKeyCertInputFromFileRadioButton.selectedProperty());
        pemKeyCertContentTextArea.editableProperty().bind(pemKeyCertInputFromStringRadioButton.selectedProperty());
        pemKeyCertInputFromURLBox.visibleProperty().bind(pemKeyCertInputFromURLRadioButton.selectedProperty());


        userLoginInfo.addListener(observable -> modelToGUI());

        defaultLoginPanelPasswordBox.managedProperty().bind(defaultLoginPanelPasswordBox.visibleProperty());
        loginButton.managedProperty().bind(loginButton.visibleProperty());

        pemKeyCertInputFromFileBox.managedProperty().bind(pemKeyCertInputFromFileBox.visibleProperty());
        pemKeyCertInputFromURLBox.managedProperty().bind(pemKeyCertInputFromURLBox.visibleProperty());

        errorLogBox.managedProperty().bind(errorLogBox.visibleProperty());
        errorLog.managedProperty().bind(errorLog.visibleProperty());
        errorLogBox.visibleProperty().bind(errorLog.textProperty().isNotEmpty());

        derivedCertificateDetails.managedProperty().bind(derivedCertificateDetails.visibleProperty());
        manualCertificateDetails.managedProperty().bind(manualCertificateDetails.visibleProperty());
        missingInfoWarningLabel.managedProperty().bind(missingInfoWarningLabel.visibleProperty());
        missingInfoErrorLabel.managedProperty().bind(missingInfoErrorLabel.visibleProperty());
        defaultLoginPanel.managedProperty().bind(defaultLoginPanel.visibleProperty());

        errorLog.setMaxHeight(Control.USE_PREF_SIZE);

        pemKeyCertContentTextArea.textProperty().addListener((observable) -> onPemEdit());

        defaultLoginPanelSliceAuthNameChooserController.selectedAuthorityProperty().addListener((observableValue, oldAuthInfo, newAuthInfo) -> {
            if (!GeniUrn.valid(defaultLoginPanelUserUrnField.getText())) {
                GeniUrn authUrn = GeniUrn.parse(newAuthInfo.getDefaultComponentManagerUrn());
                if (authUrn != null) {
                    GeniUrn templateUrn =
                            GeniUrn.createGeniUrnFromEncodedParts(authUrn.getEncodedTopLevelAuthority(), "user", "<username>");
                    defaultLoginPanelUserUrnField.setText(templateUrn.toString());
                }
            }
        });

        defaultLoginPanelUserUrnField.textProperty().addListener((observableValue, oldUrn, newUrn) -> {
            if (blockModelToGUI_eventhelper) return;

            GeniUrn newUserUrn = GeniUrn.parse(newUrn);

            if (newUserUrn != null) {
                Server newUserAuthority =
                        this.authorityFinder.findByUrn(newUserUrn, AuthorityFinder.Purpose.FIND_USERAUTH);

                if (newUserAuthority != null) {
                    defaultLoginPanelSliceAuthNameChooserController.select(newUserAuthority);
                }
            }
        });

        certificateDetailsButton.disableProperty().bind(new BooleanBinding() {
            {
                bind(userLoginInfo);
            }

            @Override
            protected boolean computeValue() {
                //noinspection ConstantConditions
                return userLoginInfo.get() == null
                        || userLoginInfo.get().getCertificateChain() == null
                        || userLoginInfo.get().getCertificateChain().isEmpty();
            }
        });


        //now load the previously saved UserLoginInfo
        loadConfig();
    }

    private static void setValidationStyle(Parent p, ValidationStyle validationStyle) {
        String styleName;
        switch (validationStyle) {
            case ERROR: {
                styleName = "validation_error";
                break;
            }
            case WARNING: {
                styleName = "validation_warning";
                break;
            }
            case OK: {
                styleName = null;
                break;
            }
            case EXPLICIT_OK: {
                styleName = "validation_explicit_ok";
                break;
            }
            default:
                throw new RuntimeException("Unsupported ValidationStyle");
        }

        List<String> otherStyles = new ArrayList<>();
        otherStyles.add("validation_error");
        otherStyles.add("validation_warning");
        otherStyles.add("validation_explicit_ok");

        if (styleName != null)
            otherStyles.remove(styleName);

        p.getStyleClass().removeAll(otherStyles);
        if (styleName != null)
            if (!p.getStyleClass().contains(styleName))
                p.getStyleClass().add(styleName);
    }

    private static boolean isMinimalLoginInfoAvailable(UserLoginInfo userLoginInfo) {
        if (userLoginInfo == null) return false;
        if (userLoginInfo.getCertificateContent() == null) return false;
        if (userLoginInfo.getCertificateChain() == null) return false;
        if (userLoginInfo.getCertificateChain().isEmpty()) return false;
        return true;
    }

    @FXML
    private void selectLoginType() {
        if (blockModelToGUI_eventhelper) return;

        final UserLoginInfo prevLoginInfo = userLoginInfo.get();
        UserLoginInfo newLoginInfo = null;


        if (loginTypeKeyCertAutoRadioButton.isSelected()) {
            if (prevLoginInfo instanceof ManualUserLoginInfo) {
                //convert old info into ManualUserInfo
                newLoginInfo = userLoginInfoFactory.createManualUserLoginInfo(prevLoginInfo.getCertificateContent());
            } else if (prevLoginInfo instanceof KeyCertFileUserLoginInfo) {
                try {
                    newLoginInfo =
                            userLoginInfoFactory.createKeyCertFileUserLoginInfo(
                                    ((KeyCertFileUserLoginInfo) prevLoginInfo).getFile());
                } catch (IOException e) {
                    LOG.error("Could not convert File UserLoginInfo", e);
                }
            } else if (prevLoginInfo instanceof KeyCertUrlUserLoginInfo) {
                try {
                    newLoginInfo =
                            userLoginInfoFactory.createKeyCertUrlUserLoginInfo(
                                    ((KeyCertUrlUserLoginInfo) prevLoginInfo).getUrl());
                } catch (IOException e) {
                    LOG.error("Could not convert URL UserLoginInfo", e);
                }
            } else {
                newLoginInfo = userLoginInfoFactory.createManualUserLoginInfo((String) null);
            }

        } else if (loginTypeKeyCertManualRadioButton.isSelected()) {
            if (prevLoginInfo instanceof ManualUserLoginInfo) {
                //convert old info into ManualUserInfo
                newLoginInfo = userLoginInfoFactory.createManualUserLoginInfo(
                        prevLoginInfo.getCertificateContent(),
                        prevLoginInfo.getUserUrn(), prevLoginInfo.getUserAuthorityServer());
            } else if (prevLoginInfo instanceof KeyCertFileUserLoginInfo) {
                try {
                    newLoginInfo =
                            userLoginInfoFactory.createKeyCertFileUserLoginInfo(
                                    ((KeyCertFileUserLoginInfo) prevLoginInfo).getFile(),
                                    prevLoginInfo.getUserUrn(), prevLoginInfo.getUserAuthorityServer());
                } catch (IOException e) {
                    LOG.error("Could not convert File UserLoginInfo", e);
                }
            } else if (prevLoginInfo instanceof KeyCertUrlUserLoginInfo) {
                try {
                    newLoginInfo =
                            userLoginInfoFactory.createKeyCertUrlUserLoginInfo(
                                    ((KeyCertUrlUserLoginInfo) prevLoginInfo).getUrl(),
                                    prevLoginInfo.getUserUrn(),
                                    prevLoginInfo.getUserAuthorityServer());
                } catch (IOException e) {
                    LOG.error("Could not convert URL UserLoginInfo", e);
                }
            } else {
                newLoginInfo = userLoginInfoFactory.createManualUserLoginInfo(null,
                        GeniUrn.parse(defaultLoginPanelUserUrnField.getText()),
                        defaultLoginPanelSliceAuthNameChooserController.getSelectedServer());
            }
        }

        this.userLoginInfo.set(newLoginInfo);
        modelToGUI();
    }

    private void clearError() {
        errorLog.setText("");
    }

    protected void guiToModel() {
        if (loginTypeKeyCertAutoRadioButton.isSelected()) {
            if (pemKeyCertInputFromFileRadioButton.isSelected()) {
                File keyCertFile = new File(pemKeyCertInputFromFileField.getText());

                try {
                    userLoginInfo.set(userLoginInfoFactory.createKeyCertFileUserLoginInfo(keyCertFile));
                } catch (IOException e) {
                    LOG.error("Could not read keyCertFile", e);
                }
            } else {
                userLoginInfo.set(userLoginInfoFactory.createManualUserLoginInfo(pemKeyCertContentTextArea.getText()));
            }
        } else {

            GeniUrn userUrn = GeniUrn.parse(defaultLoginPanelUserUrnField.getText());
            Server userAuthority = defaultLoginPanelSliceAuthNameChooserController.getSelectedServer();

            if (pemKeyCertInputFromFileRadioButton.isSelected()) {
                File keyCertFile = new File(pemKeyCertInputFromFileField.getText());

                try {
                    userLoginInfo.set(userLoginInfoFactory.createKeyCertFileUserLoginInfo(keyCertFile, userUrn, userAuthority));
                } catch (IOException e) {
                    LOG.error("Could not read KeyCertFile", e);
                }
            } else {
                userLoginInfo.set(userLoginInfoFactory.createManualUserLoginInfo(pemKeyCertContentTextArea.getText(), userUrn, userAuthority));
            }
        }

    }

    protected void modelToGUI() {
        if (blockModelToGUI_eventhelper) return;
        blockModelToGUI_eventhelper = true; //don't let it trigger modelToGUI() again, as we're doing it already

        modelToGUI_input();
        modelToGUI_derived();
        blockModelToGUI_eventhelper = false;
    }

    protected void modelToGUI_input() {
        final UserLoginInfo userLoginInfo = this.userLoginInfo.get();

        //handle the null case
        if (userLoginInfo == null) {
            loginTypeKeyCertAutoRadioButton.setSelected(true);
            pemKeyCertInputFromFileRadioButton.setSelected(true);
            pemKeyCertInputFromFileField.setText("");
            pemKeyCertInputFromURLField.setText("");
            pemKeyCertContentTextArea.setText("");
            return;
        }

        //Set user login type
        if (userLoginInfo.isUserAndAuthorityProvidedSeperately()) {
            loginTypeKeyCertManualRadioButton.setSelected(true);
        } else {
            loginTypeKeyCertAutoRadioButton.setSelected(true);
        }


        //set certificate entry method
        if (userLoginInfo instanceof KeyCertFileUserLoginInfo) {
            pemKeyCertInputFromFileRadioButton.setSelected(true);
            KeyCertFileUserLoginInfo keyCertFileUserLoginInfo = (KeyCertFileUserLoginInfo) userLoginInfo;

            if (keyCertFileUserLoginInfo.getFile() != null)
                pemKeyCertInputFromFileField.setText(keyCertFileUserLoginInfo.getFile().getAbsolutePath());
            else
                pemKeyCertInputFromFileField.setText("");
        } else if (userLoginInfo instanceof KeyCertUrlUserLoginInfo) {
            pemKeyCertInputFromURLRadioButton.setSelected(true);
            KeyCertUrlUserLoginInfo keyCertUrlUserLoginInfo = (KeyCertUrlUserLoginInfo) userLoginInfo;

            if (keyCertUrlUserLoginInfo.getUrl() != null)
                pemKeyCertInputFromURLField.setText(keyCertUrlUserLoginInfo.getUrl().toExternalForm());
            else
                pemKeyCertInputFromURLField.setText("");
        } else if (userLoginInfo instanceof ManualUserLoginInfo) {
            pemKeyCertInputFromStringRadioButton.setSelected(true);
            pemKeyCertInputFromFileField.setText("");
            pemKeyCertInputFromURLField.setText("");
        }


        //show current login info
        if (!blockTextAreaUpdate_eventhelper)
            pemKeyCertContentTextArea.setText(userLoginInfo.getCertificateContent());

        if (userLoginInfo.getUserUrn() != null)
            defaultLoginPanelUserUrnField.setText(userLoginInfo.getUserUrn().toString());
        if (userLoginInfo.getUserAuthorityServer() != null)
            defaultLoginPanelSliceAuthNameChooserController.select(userLoginInfo.getUserAuthorityServer());

        //set error
        if (userLoginInfo.getError() != null)
            showError(userLoginInfo.getError());
        else
            clearError();

    }

    protected void modelToGUI_derived() {
        UserLoginInfo userLoginInfo = this.userLoginInfo.get();

        if (userLoginInfo != null) {
            if (userLoginInfo.getUserUrn() != null) {
                defaultLoginPanelUserUrn.setText(userLoginInfo.getUserUrn().toString());
                defaultLoginPanelUsername.setText(userLoginInfo.getUserUrn().getEncodedResourceName());
            } else {
                defaultLoginPanelUserUrn.setText("-");
                defaultLoginPanelUsername.setText("-");
            }

            if (userLoginInfo.getUserAuthorityServer() != null) {
                defaultLoginPanelSliceAuthUrn.setText(userLoginInfo.getUserAuthorityServer().getDefaultComponentManagerUrn());
                defaultLoginPanelSliceAuthName.setText(userLoginInfo.getUserAuthorityServer().getName());
            } else {
                defaultLoginPanelSliceAuthUrn.setText("-");
                defaultLoginPanelSliceAuthName.setText("-");
            }


            defaultLoginPanelPasswordBox.setVisible(userLoginInfo.isValid() && !userLoginInfo.isUnlocked());
        }

        boolean missingInfo = userLoginInfo == null
                || userLoginInfo.getUserAuthorityServer() == null || userLoginInfo.getUserUrn() == null;
        if (requireAllUserInfo) {
            missingInfoWarningLabel.setVisible(false);
            missingInfoErrorLabel.setVisible(isMinimalLoginInfoAvailable(userLoginInfo) && missingInfo);
        } else {
            missingInfoWarningLabel.setVisible(isMinimalLoginInfoAvailable(userLoginInfo) && missingInfo);
            missingInfoErrorLabel.setVisible(false);
        }
        LOG.debug("missingInfo=" + missingInfo + " requireAllUserInfo=" + requireAllUserInfo);

        updateLoginButtonEnabled();
    }

    @FXML
    public void selectInputMethod() {
        LOG.trace("selectInputMethod blockModelToGUI_eventhelper={} userLoginInfo.class={}",
                blockModelToGUI_eventhelper,
                userLoginInfo.get() != null ? userLoginInfo.get().getClass().getName() : "null");
        if (blockModelToGUI_eventhelper) return;

        UserLoginInfo prevUserLoginInfo = this.userLoginInfo.get();

        if (pemKeyCertInputFromStringRadioButton.isSelected()) {
            if (prevUserLoginInfo != null) {
                userLoginInfo.set(userLoginInfoFactory.createManualUserLoginInfo(prevUserLoginInfo));
            }
        } else if (pemKeyCertInputFromFileRadioButton.isSelected()) {
            final File certificateFile = new File(pemKeyCertInputFromFileField.getText());
            if (certificateFile.exists())
                loadCertificateFile(certificateFile);
            else {
                try {
                    userLoginInfo.set(userLoginInfoFactory.createKeyCertFileUserLoginInfo(null));
                } catch (IOException ignored) {
                }
            }
        } else if (pemKeyCertInputFromURLRadioButton.isSelected()) {
            if (!pemKeyCertInputFromURLField.getText().isEmpty())
                loadCertificateURL();
            else {
                try {
                    userLoginInfo.set(userLoginInfoFactory.createKeyCertUrlUserLoginInfo(null));
                } catch (IOException ignored) {
                }
            }
        }
    }

    private void showError(Exception e) {
        showError(e.getMessage());
    }

    public void onPemEdit() {
        if (blockModelToGUI_eventhelper) return;

        blockTextAreaUpdate_eventhelper = true;
        guiToModel();
        blockTextAreaUpdate_eventhelper = false;
    }

    @FXML
    public void showCertificateDetailsWindow() {
        String keyCertContent = userLoginInfo.get().getCertificateContent();
        if (keyCertContent != null) {
            X509CertificatePanel.showX509Certificate(keyCertContent);
        }
    }

    @FXML
    public void unlockAndLogin() {
        try {
            final char[] password =
                    userLoginInfo.get().isUnlocked() ? null : defaultLoginPanelPassword.getText().toCharArray();
            GeniUser loggedInUser = userLoginInfo.get().login(password);

            if (password != null)
                PpkHelper.makePpkIfNeeded(loggedInUser, new String(password));

            processLoggedInUser(loggedInUser);
        } catch (InvalidLoginException e) {
            UserLoginInfo userLoginInfo = this.userLoginInfo.get();
            LOG.debug("userLoginInfoManager.unlockAndLogin() not successful unlocked={}\n" +
                            "\tgetClass().getName()={}\n" +
                            "\tisMinimalLoginInfoAvailable()={}\n" +
                            "\tm.getUserAuthority() == null={}\n" +
                            "\tm.getUserUrn() == null={}\n" +
                            "\trequireAllUserInfo={}",
                    userLoginInfo.isUnlocked(),
                    userLoginInfo.getClass().getName(),
                    isMinimalLoginInfoAvailable(userLoginInfo),
                    (userLoginInfo.getUserAuthorityServer() == null),
                    (userLoginInfo.getUserUrn() == null),
                    requireAllUserInfo, e);
        }
    }

    private boolean loginWithoutPasswordAllowed() {
        UserLoginInfo userLoginInfo = this.userLoginInfo.get();

        if (userLoginInfo == null) return false;

        LOG.debug("loginWithoutPasswordAllowed() ->  isMinimalLoginInfoAvailable={} (getUserUrn() == null) = {} (getUserAuthorityServer() == null) = {} requireAllUserInfo={}"
                , isMinimalLoginInfoAvailable(userLoginInfo), userLoginInfo.getUserUrn() == null, userLoginInfo.getUserAuthorityServer() == null, requireAllUserInfo);


        //is the bare minimum supplied?
        if (!isMinimalLoginInfoAvailable(userLoginInfo)) return false;

        if (requireAllUserInfo) {
            if (userLoginInfo.getUserUrn() == null) return false;
            if (userLoginInfo.getUserAuthorityServer() == null) return false;
        }

        return userLoginInfo.isUnlocked() || defaultLoginPanelPassword.getText() != null;
    }

    public void updateLoginButtonEnabled() {
        loginButton.setDisable(!loginWithoutPasswordAllowed());
    }

    private void showError(String error) {
        if (error != null) {
            errorLog.setText(error);
        } else {
            clearError();
        }
    }

    private void processLoggedInUser(GeniUser loggedInUser) {
        LOG.debug("Advanced User Login window 'login'");

        UserLoginInfo newUserLoginInfo = userLoginInfo.get();

        UserLoginInfo prevUserLoginInfo = null;

        try {
            prevUserLoginInfo = userLoginInfoManager.load();
        } catch (InvalidLoginException e) {
            LOG.debug("Could not load saved user login info. Ignoring", e);
        }

        if (!Objects.equals(newUserLoginInfo, prevUserLoginInfo)) {
            JFDialogs.create()
                    .message("Save login details now? (password is never saved)")
                    .buttonTypes(ButtonType.YES, ButtonType.NO)
                    .showWarning()
                    .filter(response -> response == ButtonType.YES)
                    .ifPresent(response -> userLoginInfoManager.save(newUserLoginInfo));
        }

        //Check for certificate validity
        boolean success = true;
        String problem;
        try {
            for (X509Certificate cert : loggedInUser.getClientCertificateChain()) {
                cert.checkValidity();
            }
            problem = null;
        } catch (CertificateExpiredException e) {
            problem = "certificate has expired.";
        } catch (CertificateNotYetValidException e) {
            problem = "certificate is not yet valid";
        }
        if (problem != null) {
            Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
            alert.setTitle("Certificate problem");
            alert.setHeaderText("Warning: " + problem);
            alert.setContentText("There is a problem with your certificate, which will likely cause all calls to fail.\n" +
                    "Since this is an advanced login dialog, you can continue if you really wish.\n" +
                    "The problem is: " + problem + "\n" +
                    "\n" +
                    "Do you really want to continue login?");
            alert.getButtonTypes().setAll(ButtonType.YES, ButtonType.NO, ButtonType.CANCEL);

            Optional<ButtonType> reply = alert.showAndWait();
            if (!reply.isPresent() || reply.get() != ButtonType.YES) {
                success = false;
            }
        }

        if (success) {
            result = loggedInUser;
            close();
        }

        LOG.debug("Advanced User Login window 'login' handled: success={}", success);
    }

    @FXML
    public void nologin() {
        LOG.debug("Advanced User Login window 'skip login' button pressed: skipping login");

        result = null;
        close();
    }

    private void close() {
        ((Stage) loginButton.getScene().getWindow()).close();
    }


    @FXML
    public void saveConfig() {
        //Note: password is never saved
        userLoginInfoManager.save(userLoginInfo.get());
    }

    @FXML
    public void loadConfig() {
        try {
            userLoginInfo.set(userLoginInfoManager.load());
        } catch (InvalidLoginException e) {
            LOG.error("Loading previous UserLoginInfo failed", e);
            userLoginInfo.set(null);
        }
    }

    @FXML
    public void resetConfig() {
        userLoginInfo.set(userLoginInfoManager.reset());
        new Alert(Alert.AlertType.INFORMATION, "User Login settings were reset to defaults").showAndWait();
    }

    @FXML
    private void browseForCertificateFile() {
        FileChooser fileChooser = new FileChooser();
        File file = fileChooser.showOpenDialog(null);

        if (file != null)
            pemKeyCertInputFromFileField.setText(file.getAbsolutePath());
    }

    private void loadCertificateFile(@Nonnull File file) {

        try {
            if (loginTypeKeyCertAutoRadioButton.isSelected()) {
                userLoginInfo.set(userLoginInfoFactory.createKeyCertFileUserLoginInfo(file));
            } else {
                GeniUrn userUrn = GeniUrn.parse(defaultLoginPanelUserUrnField.getText());

                userLoginInfo.set(userLoginInfoFactory.createKeyCertFileUserLoginInfo(file, userUrn,
                        defaultLoginPanelSliceAuthNameChooserController.getSelectedServer()));
            }
        } catch (IOException e) {
            showError(e);
        }

    }


    @FXML
    private void loadCertificateURL() {
        try {
            URL url = new URL(pemKeyCertInputFromURLField.getText());

            if (loginTypeKeyCertAutoRadioButton.isSelected()) {
                userLoginInfo.set(userLoginInfoFactory.createKeyCertUrlUserLoginInfo(url));
            } else {
                GeniUrn userUrn = GeniUrn.parse(defaultLoginPanelUserUrnField.getText());

                userLoginInfo.set(userLoginInfoFactory.createKeyCertUrlUserLoginInfo(url, userUrn,
                        defaultLoginPanelSliceAuthNameChooserController.getSelectedServer()));
            }

        } catch (IOException e) {
            showError(e);
        }
    }


    @FXML
    private void showAbout() {
        //TODO either remove about button or add about panel
//        AboutBoxController.showAbout();
    }


    @FXML
    private void clearJfedDir() {
        JFedCommonDialogs.requestEraseJFedConfiguration(loginButton.getScene().getWindow());
    }

    public GeniUser getResult() {
        return result;
    }

    public UserLoginInfo getUserLoginInfo() {
        return userLoginInfo.get();
    }

    private enum ValidationStyle {ERROR, WARNING, OK, EXPLICIT_OK}
}
