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

import be.iminds.ilabt.jfed.lowlevel.GeniUserProvider;
import be.iminds.ilabt.jfed.lowlevel.ssh_key_info.PuTTYFilesKeyInfo;
import be.iminds.ilabt.jfed.lowlevel.ssh_key_info.SshKeyInfoFactory;
import be.iminds.ilabt.jfed.preferences.CorePreferenceKey;
import be.iminds.ilabt.jfed.preferences.GuiPreferenceKey;
import be.iminds.ilabt.jfed.preferences.JFedGuiPreferences;
import be.iminds.ilabt.jfed.ssh_terminal_tool.putty.PageantHelper;
import be.iminds.ilabt.jfed.lowlevel.ssh_key_info.putty.PuTTYPrivateKeyFile;
import be.iminds.ilabt.jfed.ssh_terminal_tool.putty.SshKeyInfoUnlocker;
import be.iminds.ilabt.jfed.ui.javafx.dialogs.JFDialogs;
import be.iminds.ilabt.jfed.util.IOUtils;
import be.iminds.ilabt.jfed.util.KeyUtil;
import javafx.fxml.FXML;
import javafx.scene.Node;
import javafx.scene.control.Label;
import javafx.scene.control.TextArea;
import javafx.scene.layout.BorderPane;

import javax.inject.Inject;
import java.io.File;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;

public class WindowsSshAuthenticationPane extends SshAuthenticationPane {
    //private static final FileChooser.ExtensionFilter PPK_FILE_EXTENSION =
    //        new FileChooser.ExtensionFilter("PuTTY Private Key (*.ppk)", "*.ppk");

    @FXML
    protected Label textKeyLabel;
    @FXML
    protected Label warnMultiKeyLabel;
    @FXML
    protected TextArea textKeyTextArea;
    @FXML
    private BorderPane root;

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

    private final PageantHelper pageantHelper;
    private final SshKeyInfoUnlocker sshKeyInfoUnlocker;

    @Inject
    WindowsSshAuthenticationPane(GeniUserProvider geniUserProvider, JFedGuiPreferences jFedPreferences,
                                 PageantHelper pageantHelper, SshKeyInfoUnlocker sshKeyInfoUnlocker) {
        super(geniUserProvider, jFedPreferences);
        this.pageantHelper = pageantHelper;
        this.sshKeyInfoUnlocker = sshKeyInfoUnlocker;
    }

    @FXML
    protected void initialize() {
        super.initialize();
        textKeyLabel.disableProperty().bind(useCustomKeyPairCheckBox.selectedProperty().not());
        textKeyTextArea.disableProperty().bind(useCustomKeyPairCheckBox.selectedProperty().not());

        warnMultiKeyLabel.managedProperty().bind(useCustomKeyPairCheckBox.selectedProperty().and(useCertificateCheckBox.selectedProperty()));
        warnMultiKeyLabel.visibleProperty().bind(warnMultiKeyLabel.managedProperty());
    }

    @Override
    protected boolean testPrivateKey() {
        boolean validPrivateKey = super.testPrivateKey();
        if (validPrivateKey) {
            textKeyTextArea.setText(getPublicKeyFromFile(new File(fileTextField.getText())));
        } else {
            textKeyTextArea.setText("");
        }
        return validPrivateKey;
    }

    @Override
    protected boolean testPrivateKeyFile(File file) throws IOException {
        return file.exists() && file.isFile() && PuTTYPrivateKeyFile.isPuttyPrivateKey(file);
    }

    protected String getPublicKeyFromFile(File file) {
        String key = null;

        //try to extract public key from this file
        try {
            if (PuTTYPrivateKeyFile.isPuttyPrivateKey(file)) {
                PuTTYPrivateKeyFile ppk = PuTTYPrivateKeyFile.read(file);
                key = ppk.getPublicKeyOpenSshString();
            } else if (KeyUtil.isOpenSshRsaKey(file)) {
                key = IOUtils.fileToString(file).replace("\n", "");
            }
        } catch (IOException ex) {
            JFDialogs.create()
                    .owner(fileTextField)
                    .message("An error occured while processing the key file")
                    .masthead("Error")
                    .title("Error")
                    .showException(ex);

        }
        return key;
    }

    @Override
    public boolean check() {
        return super.check();
    }

    public boolean save() {
        //only continue to save if parent-save is also OK
        if (!super.save())
            return false;

        //Ok, finally, register keys with pageant
        if (jFedPreferences.getBoolean(GuiPreferenceKey.PREF_SSHAGENT_USE)) {
            Set<PuTTYFilesKeyInfo> keys = new HashSet<>();

            assert geniUserProvider.isUserLoggedIn();

            PuTTYFilesKeyInfo sshKeyInfo = jFedPreferences.getCustomSshKeyInfo();
            if (sshKeyInfo == null) {
                final be.iminds.ilabt.jfed.lowlevel.GeniUser geniUser = geniUserProvider.getLoggedInGeniUser();
                sshKeyInfo = SshKeyInfoFactory.createGeniUserSshKeyInfo(geniUser);
            }
            keys.add(sshKeyInfo);

            if (!jFedPreferences.getString(CorePreferenceKey.PREF_SSHPROXY_USE_FOR_SSH).equalsIgnoreCase("NEVER")) {
                final be.iminds.ilabt.jfed.lowlevel.GeniUser geniUser = geniUserProvider.getLoggedInGeniUser();
                keys.add(SshKeyInfoFactory.createGeniUserSshKeyInfo(geniUser));
            }

            pageantHelper.registerKeys(keys, sshKeyInfoUnlocker);
        }

        return true;
    }
}
