package be.iminds.ilabt.jfed.ssh_terminal_tool;

import be.iminds.ilabt.jfed.lowlevel.GeniUser;
import be.iminds.ilabt.jfed.lowlevel.GeniUserProvider;
import be.iminds.ilabt.jfed.lowlevel.connection.JFedConnection;
import be.iminds.ilabt.jfed.lowlevel.ssh_key_info.PuTTYFilesKeyInfo;
import be.iminds.ilabt.jfed.lowlevel.ssh_key_info.SshFilesKeyInfo;
import be.iminds.ilabt.jfed.lowlevel.ssh_key_info.SshKeyInfoFactory;
import be.iminds.ilabt.jfed.preferences.GuiPreferenceKey;
import be.iminds.ilabt.jfed.preferences.JFedGuiPreferences;
import be.iminds.ilabt.jfed.preferences.ProxyPreferencesManager;
import be.iminds.ilabt.jfed.ssh_terminal_tool.putty.PuttyHelper;
import be.iminds.ilabt.jfed.ssh_terminal_tool.unix.OpenSshKnownHostsFile;
import be.iminds.ilabt.jfed.ssh_terminal_tool.unix.SshAgentHelper;
import be.iminds.ilabt.jfed.ui.javafx.GlyphUtils;
import be.iminds.ilabt.jfed.util.OSDetector;
import be.iminds.ilabt.jfed.util.tmp_file_helpers.TmpContentFile;
import be.iminds.ilabt.jfed.util.tmp_file_helpers.TmpFile;
import javafx.scene.control.*;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import org.controlsfx.glyphfont.FontAwesome;
import org.slf4j.LoggerFactory;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.inject.Inject;
import javax.inject.Singleton;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.regex.Pattern;

@Singleton
public class ExternalSshTerminal {
    private static final org.slf4j.Logger LOG = LoggerFactory.getLogger(ExternalSshTerminal.class);

    private final GeniUserProvider geniUserProvider;
    private final JFedGuiPreferences jFedPreferences;
    private final ProxyPreferencesManager proxyPreferencesManager;
    private final PuttyHelper puttyHelper;
    private final OpenSshKnownHostsFile openSshKnownHostsFile;

    @Inject
    public ExternalSshTerminal(GeniUserProvider geniUserProvider,
                               ProxyPreferencesManager proxyPreferencesManager,
                               JFedGuiPreferences jFedPreferences,
                               PuttyHelper puttyHelper,
                               OpenSshKnownHostsFile openSshKnownHostsFile) {
        this.geniUserProvider = geniUserProvider;
        this.proxyPreferencesManager = proxyPreferencesManager;
        this.jFedPreferences = jFedPreferences;
        this.puttyHelper = puttyHelper;
        this.openSshKnownHostsFile = openSshKnownHostsFile;

        //not the best way, but currently the easiest way to activate more detailed logging only for ExternalSshTerminal
        boolean terminalDebug = jFedPreferences.getBoolean(GuiPreferenceKey.PREF_TERMINAL_DEBUG, true);
        //TODO: re-enable this, by actually configuring the logging differently
    }

    public boolean isConfigured() {
        LOG.debug("ExternalSshTerminal.isConfigured");
        if (OSDetector.os == OSDetector.OS.WIN) {
            File puttyDir = jFedPreferences.getFile(GuiPreferenceKey.PREF_PUTTY_DIRECTORY);
            LOG.debug("ExternalSshTerminal.isConfigured WIN puttyDir=" + puttyDir);
            if (puttyDir == null) return false;
            boolean valid = JFedGuiPreferences.isValidPuttyDir(puttyDir);
            LOG.debug("ExternalSshTerminal.isConfigured WIN puttyDir=" + puttyDir + " valid=" + valid);
            return valid;
        }

        if (OSDetector.os == OSDetector.OS.UNIX) {
            return jFedPreferences.getString(GuiPreferenceKey.PREF_COMMAND_UNIX_TERMINAL) != null;
        }

        if (OSDetector.os == OSDetector.OS.MAC) {
            return jFedPreferences.getString(GuiPreferenceKey.PREF_COMMAND_UNIX_TERMINAL) != null;
        }

        return true;
    }


    public void launch(@Nonnull String targetServerUserName, @Nonnull String hostName, int port,
                       @Nullable JFedConnection.ProxyInfo customProxyInfo) {
        assert geniUserProvider.isUserLoggedIn();

        final GeniUser geniUser = geniUserProvider.getLoggedInGeniUser();

        List<PuTTYFilesKeyInfo> sshKeyInfos = new ArrayList<>();
        PuTTYFilesKeyInfo customSshKeyInfo = jFedPreferences.getCustomSshKeyInfo();
        if (customSshKeyInfo != null) {
            LOG.info("ExternalSshTerminal: The preferences are overriding the SSH key used (" + customSshKeyInfo.getClass().getName() + ").");
            sshKeyInfos.add(customSshKeyInfo);
        }
        if (jFedPreferences.getBoolean(GuiPreferenceKey.PREF_SSH_USE_LOGIN_KEY) || sshKeyInfos.isEmpty()) {
            LOG.info("ExternalSshTerminal: The user's SSH key will be used.");
            final GeniUser geniUser1 = geniUser;
            sshKeyInfos.add(SshKeyInfoFactory.createGeniUserSshKeyInfo(geniUser1));
        }

        //This will set the proxyInfo to what is needed, based on if proxy exists, preferences and connectivity data.
        JFedConnection.ProxyInfo proxyInfo =
                proxyPreferencesManager.getSshProxySettings(geniUser.getUserAuthorityServer().getTestbed().getProxies(), geniUser);

        if(customProxyInfo != null){
            if(proxyInfo != null){
                LOG.warn("Proxy is active, however, it will be overridden by a custom testbed proxy '{}'!", customProxyInfo);


                //show warning to user that we cannot do double proxy support

                //show a (mutable) notification to users that they have two proxies enabled
                if (jFedPreferences.getBoolean(GuiPreferenceKey.PREF_SHOW_DOUBLE_PROXY_WARNING_DIALOG, true)) {
                    LOG.debug("Showing slivers initialization dialog");

                    VBox pane = new VBox();
                    pane.setPrefWidth(360);
                    pane.setSpacing(5);

                    Label textLabel = new Label(
                            "The testbed defined a proxy that has to be used to connect to the node. " +
                                    "You also have the jFed-proxy enabled for SSH-connections.\n\n" +
                                    "Your SSH-terminal-application only supports one proxy at a time. " +
                                    "We will therefore try to connect by only using the proxy defined by the testbed.\n\n" +
                                    "If you are experiencing connectivity problems because of this, please contact support.");
                    textLabel.setWrapText(true);
                    pane.getChildren().add(textLabel);
                    final CheckBox checkBox = new CheckBox("Do not show this dialog again");
                    pane.getChildren().add(checkBox);

                    DialogPane dialogPane = new DialogPane();
                    dialogPane.setHeaderText("2 Proxies detected");
                    dialogPane.setGraphic(GlyphUtils.createDialogGlyph(FontAwesome.Glyph.TERMINAL, Color.BLACK));
                    dialogPane.setContent(pane);
                    dialogPane.getButtonTypes().setAll(ButtonType.OK);


                    Dialog<ButtonType> dialog = new Dialog<>();
                    dialog.setTitle("Warning: 2 Proxies detected");
                    dialog.setDialogPane(dialogPane);

                    dialog.showAndWait();

                    jFedPreferences.setBoolean(GuiPreferenceKey.PREF_SHOW_DOUBLE_PROXY_WARNING_DIALOG,
                            !checkBox.isSelected());
                } else {
                    LOG.debug("Skipping slivers initializing dialog because user muted it before");
                }


            }

            //TODO: warn user?

            proxyInfo = customProxyInfo;
        }

        if (proxyInfo == null)
            LOG.info("ExternalSshTerminal: No proxy will be used.");
        else
            LOG.info("ExternalSshTerminal: Proxy will be used: " + proxyInfo);

        if (OSDetector.os == OSDetector.OS.WIN) {
            launchPutty(targetServerUserName, hostName, port, sshKeyInfos, proxyInfo);
            return;
        }

        if (OSDetector.os == OSDetector.OS.UNIX) {
            launchUnixOrMacTerminal(false/*isMac*/, targetServerUserName, hostName, port, sshKeyInfos, proxyInfo, jFedPreferences.getBoolean(GuiPreferenceKey.PREF_SSHAGENT_USE));
            return;
        }

        if (OSDetector.os == OSDetector.OS.MAC) {
            launchUnixOrMacTerminal(true/*isMac*/, targetServerUserName, hostName, port, sshKeyInfos, proxyInfo, jFedPreferences.getBoolean(GuiPreferenceKey.PREF_SSHAGENT_USE));
            return;
        }

        throw new RuntimeException("No terminal known for OS \"" + OSDetector.os + "\"");
    }

    public void launchPutty(final String userName, final String hostName, final int port, final List<? extends PuTTYFilesKeyInfo> sshKeyInfos,
                            final JFedConnection.ProxyInfo proxyInfo) {
        PuttyHelper.PuttyRunParameters parameters = new PuttyHelper.PuttyRunParameters();
        parameters.setTarget(hostName, port, sshKeyInfos, userName);
        parameters.setProxy(proxyInfo);
        parameters.setEnableX11Forward(jFedPreferences.getBoolean(GuiPreferenceKey.PREF_PUTTY_X11_FORWARD, true));
        parameters.setEnableAgentForward(jFedPreferences.getBoolean(GuiPreferenceKey.PREF_PUTTY_AGENT_FORWARD, true));
        puttyHelper.runPutty(parameters);
    }


    public void launchUnixOrMacTerminal(boolean isMac, final String userName, final String hostName, final int port,
                                        final List<? extends SshFilesKeyInfo> sshKeyInfos, JFedConnection.ProxyInfo proxyInfo, boolean useSshAgent) {
        if (isMac && jFedPreferences.getString(GuiPreferenceKey.PREF_COMMAND_UNIX_TERMINAL) == null) {
            String com = "tell application \"Terminal\" to do script \"%\"";

            LOG.info("Falling back to auto-detected terminal command: " + com);
            jFedPreferences.setString(GuiPreferenceKey.PREF_COMMAND_UNIX_TERMINAL, com);
        }

        //for SSH proxy to work, we need to store the private key unencrypted.
        final List<TmpFile> tmpFiles = new ArrayList<>();

        String sshCommand;

        if (useSshAgent) {
            for (SshFilesKeyInfo sshKeyInfo : sshKeyInfos) {
                try {
                    SshAgentHelper.registerKey(sshKeyInfo);
                } catch (Exception e) {
                    LOG.warn("ssh-add failed: sshKeyInfo.hasUnencryptedPrivateKey=" + sshKeyInfo.hasUnencryptedPrivateKey(), e);
                }
            }
        }

        if (proxyInfo == null) {
            sshCommand = jFedPreferences.getString(GuiPreferenceKey.PREF_COMMAND_SSH);
        } else {
            assert proxyInfo instanceof JFedConnection.SshProxyInfo;

            JFedConnection.SshProxyInfo sshProxyInfo = (JFedConnection.SshProxyInfo) proxyInfo;

            //store proxyOpenSshKey
            if (sshProxyInfo.getHostKey() != null)
                openSshKnownHostsFile.addKnownHost(sshProxyInfo.getHostname(), sshProxyInfo.getHostKey());

            sshCommand = jFedPreferences.getString(GuiPreferenceKey.PREF_COMMAND_SSH_PROXY);

            sshCommand = sshCommand.replace("$P", sshProxyInfo.getPort() + "");
            sshCommand = sshCommand.replace("$H", sshProxyInfo.getHostname());
            sshCommand = sshCommand.replace("$U", sshProxyInfo.getUsername());

            if (sshProxyInfo.getSshKeyInfo() != null) {
                assert sshProxyInfo.getSshKeyInfo() instanceof SshFilesKeyInfo :
                        "sshProxyInfo.getSshKeyInfo() -> "+sshProxyInfo.getSshKeyInfo().getClass().getName();
                SshFilesKeyInfo sshFilesKeyInfo = (SshFilesKeyInfo)sshProxyInfo.getSshKeyInfo();
                if (useSshAgent) {
                    TmpFile tmpFile = sshFilesKeyInfo.getPrivateKeyFile();
                    tmpFiles.add(tmpFile);
                    sshCommand =
                            sshCommand.replace("$I", tmpFile.getFilename()); //if using ssh-agent, just use encrypted file

                    SshAgentHelper.registerKey(sshFilesKeyInfo);
                } else {
                    TmpFile tmpFile = sshFilesKeyInfo.getUnencryptedPrivateKeyFile();
                    tmpFiles.add(tmpFile);
                    sshCommand =
                            sshCommand.replace("$I", tmpFile.getFilename());
                }
            }
        }
        sshCommand = sshCommand.replace("$p", port + "");
        sshCommand = sshCommand.replace("$h", hostName);
        sshCommand = sshCommand.replace("$u", userName);

        //OpenSSH option "-i <key>" can be specified multiple times, so we will do that.
        String iReplacement = null;
        boolean isDefaultIOption = sshCommand.contains("-i $i");
        boolean isQuotedDefaultIOption = sshCommand.contains("-i '$i'");
        boolean isDoubleQuotedDefaultIOption = sshCommand.contains("-i \"$i\"");
        if (!(isDefaultIOption || isQuotedDefaultIOption || isDoubleQuotedDefaultIOption)) {
            LOG.warn("isDefaultIOption=false for sshCommand=\""+sshCommand+"\"");
        }
        for (SshFilesKeyInfo sshKeyInfo : sshKeyInfos) {
            LOG.debug("launchTerminal sshKeyInfo class: " + sshKeyInfo.getClass().getName()+" isDefaultIOption="+isDefaultIOption+" iReplacement=\""+iReplacement+"\"");

            TmpFile privKeyFile = sshKeyInfo.getPrivateKeyFile();
            tmpFiles.add(privKeyFile);
            if (privKeyFile != null) {
                if (iReplacement == null) {
                    iReplacement = privKeyFile.getFilename();
                } else {
                    if (isDefaultIOption || isQuotedDefaultIOption || isDoubleQuotedDefaultIOption) {
                        if (isDefaultIOption)
                            iReplacement = iReplacement+" -i "+privKeyFile.getFilename();
                        if (isQuotedDefaultIOption)
                            iReplacement = iReplacement+"' -i '"+privKeyFile.getFilename();
                        if (isDoubleQuotedDefaultIOption)
                            iReplacement = iReplacement+"\" -i \""+privKeyFile.getFilename();
                    } else {
                        LOG.warn("sshCommand used is not using default openSSH -i option -> Will only use first private key to login!");
                    }
                }
                //WAS:  sshCommand = sshCommand.replace("$i", privKeyFile.getFilename());
            } else
                throw new RuntimeException("No private key file specified, cannot use SSH login. sshKeyInfo class: " + sshKeyInfo.getClass().getName());
        }
        if (iReplacement != null) {
            LOG.debug("Using final iReplacement=\""+iReplacement+"\"");
            sshCommand = sshCommand.replace("$i", iReplacement);
        } else {
            throw new RuntimeException("Could not replace $i in sshCommand");
        }

        StringBuilder internalCommand = new StringBuilder();
        internalCommand.append(sshCommand);

        //set -v shows commands executed
        //set +v stops showing commands executed
        // (+x and -x hide and show expanded commands)
        TmpContentFile tmpCommandFile;
        if (useSshAgent)
            tmpCommandFile =
                    new TmpContentFile("openSsh", "sh", "#!/bin/bash \n\nset -v\n" + SshAgentHelper.getSshAgentEnvironment() + "\n" + internalCommand.toString() + "\n/bin/bash");
        else
            tmpCommandFile =
                    new TmpContentFile("openSsh", "sh", "#!/bin/bash \n\nset -v\n" + internalCommand.toString() + "\n/bin/bash");
        tmpFiles.add(tmpCommandFile);
        String tmpCommandFilename = tmpCommandFile.getFilename();
        //        String quotedTmpCommandFilename = "'"+tmpCommandFileHelper.getFilename()+"'";

        final String callScriptCommand = "bash " + tmpCommandFilename;

        String command = jFedPreferences.getString(GuiPreferenceKey.PREF_COMMAND_UNIX_TERMINAL);

        final List<String> commandList = new ArrayList<>();
        if (isMac) {
            //commandList not used
            if (command.contains("%")) {
                command = command.replaceFirst("%", callScriptCommand);
            } else
                LOG.error("command does not contain required % \"" + command + "\"");
        } else {
            //unix
            if (!command.contains("%")) {
                //We do not know the exact command, so we will assume it is '-e' which is what xterm and konsole use
                //mustQuote is a hack to make gnome-terminal work (it needs quotes around the command)
                boolean mustQuote = false; //false for xterm and konsole, true for gnome-terminal
                if (internalCommand.toString().contains("gnome-terminal"))
                    mustQuote = true;

                if (mustQuote)
                    command += " -e '%'";
                else
                    command += " -e %";
            }

            if (command.contains("'%'") || command.contains("\"%\"")) {
                command = command.replaceFirst(Pattern.quote("'%'"), "%").replaceFirst(Pattern.quote("\"%\""), "%");

                String[] finalCommandSplit = command.split(" ");
                for (String aFinalCommandSplit : finalCommandSplit)
                    if (Objects.equals(aFinalCommandSplit, "%"))
                        commandList.add(callScriptCommand);
                    else
                        commandList.add(aFinalCommandSplit);
            } else {
                command = command.replaceFirst(Pattern.quote("%"), callScriptCommand);
                String[] finalCommandSplit = command.split(" ");
                Collections.addAll(commandList, finalCommandSplit);
            }
        }
        final String finalCommand = command;

        LOG.debug("launchTerminal: useSshAgent=" + useSshAgent + " proxyInfo=" + proxyInfo);
        LOG.info("launchTerminal: commands={}", tmpCommandFile.getContent());
        if (isMac) {
            LOG.debug("launchTerminal: callScriptCommand: " + callScriptCommand);
        } else {
            LOG.debug("Executing command to launch terminal: {}", command);
            LOG.debug("   internalCommand: {}", internalCommand.toString());

            LOG.info("launchTerminal: commandList={}", commandList);

            //example commands:
            //   "xterm"
            //   "konsole"
            //   "gnome-terminal"      // mustQuote = true
            //   "x-terminal-emulator" //alternative for konsole or gnome-terminal
        }


        Runnable processOutputMonitor = () -> {
            try {

                if (isMac) {
                    LOG.info("ExternalTerminal Thread: Running external terminal with command: " + finalCommand);
                    //cfr https://developer.apple.com/library/mac/documentation/Java/Conceptual/Java14Development/07-NativePlatformIntegration/NativePlatformIntegration.html
                    ScriptEngineManager mgr = new ScriptEngineManager();
                    ScriptEngine engine = mgr.getEngineByName("AppleScript");
                    if (engine != null) {
                        try {
                            Object result = engine.eval(finalCommand);

                            LOG.trace("ExternalTerminal Thread: Got output: " + result);
                        } catch (ScriptException e) {
                            LOG.error("ExternalTerminal Thread: Executing external ssh-terminal failed.", e);
                            throw new RuntimeException(e);
                        }
                    } else {
                        LOG.info("ExternalTerminal Thread: Got null when requesting AppleScript-engine, trying fallback to osascript");

                        ProcessBuilder pb = new ProcessBuilder("osascript", "-e", finalCommand);
                        try {
                            Process p = pb.start();

                            BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()));
                            BufferedReader input2 = new BufferedReader(new InputStreamReader(p.getErrorStream()));
                            String line;
                            while ((line = input.readLine()) != null) {
                                LOG.trace("ExternalTerminal Thread: External Terminal stdout: " + line);
                            }
                            while ((line = input2.readLine()) != null) {
                                LOG.trace("ExternalTerminal Thread: External Terminal stderr: " + line);
                            }
                            input.close();
                            input2.close();

                        } catch (IOException ex) {
                            LOG.error("ExternalTerminal Thread: Got exception while running ExternalTerminal-app", ex);
                            throw new RuntimeException(ex);
                        }

                    }
                } else {
                    //unix
                    LOG.debug("ExternalTerminal Thread: Starting terminal using command (list): " + commandList);

                    ProcessBuilder pb = new ProcessBuilder(commandList);
                    pb.redirectErrorStream();

                    Process p = pb.start();
                    //                    Process p = Runtime.getRuntime().exec(finalCommand);
                    BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()));

                    String line;
                    while ((line = input.readLine()) != null) {
                        LOG.debug("ExternalTerminal Thread: External Terminal stdout+stderr: " + line);
                    }
                    //note: input might close before terminal stops.
                    input.close();
                    try {
                        p.waitFor();
                    } catch (InterruptedException e) {
                        LOG.warn("ExternalTerminal Thread: processOutputMonitor thread interrupted while waiting for terminal to stop", e);
                    }
                    LOG.info("ExternalTerminal Thread: Terminal command exited with exit value: " + p.exitValue());
                }
            } catch (Exception e) {
                LOG.error("Unhandled Exception in ExternalTerminal Thread.", e);
            } catch (AssertionError e) {
                LOG.error("Unhandled AssertionError in ExternalTerminal Thread.", e);
            }

            try {
                if (!jFedPreferences.getBoolean(GuiPreferenceKey.PREF_TERMINAL_KEEP_TMP_FILES, true)) {
                    LOG.debug("ExternalTerminal Thread: Terminal has been shown. Will now wait 30s. (and then delete temp files)");
                    //some terminal commands exit immediately and start terminal in background
                    try {
                        Thread.sleep(30 * 1000);
                    } catch (InterruptedException e) {
                        //ignore
                    }

                    LOG.info("ExternalTerminal Thread: Terminal has been shown and waited 30s and will now delete temp files");
                    for (TmpFile tmpFile : tmpFiles)
                        tmpFile.delete();
                }
            } catch (AssertionError e) {
                LOG.error("Unhandled AssertionError in ExternalTerminal Thread.", e);
            } catch (Exception e) {
                LOG.error("Unhandled Exception in ExternalTerminal Thread.", e);
            }
        };
        try {
            for (TmpFile tmpFile : tmpFiles) {
                tmpFile.store();
            }

            Thread t = new Thread(processOutputMonitor);
            t.setName("ExternalTerminal");
            t.setDaemon(true); //=> this application may exit before terminal stops
            t.start();
        } catch (AssertionError e) {
            LOG.error("AssertionError starting ExternalTerminal Thread", e);
            if (!jFedPreferences.getBoolean(GuiPreferenceKey.PREF_TERMINAL_KEEP_TMP_FILES, true)) {
                LOG.warn("  because of exception starting ExternalTerminal Thread -> will delete temp files");
                for (TmpFile tmpFile : tmpFiles)
                    tmpFile.delete();
            }
        } catch (Exception e) {
            LOG.error("Exception starting ExternalTerminal Thread", e);
            if (!jFedPreferences.getBoolean(GuiPreferenceKey.PREF_TERMINAL_KEEP_TMP_FILES, true)) {
                LOG.warn("  because of exception starting ExternalTerminal Thread -> will delete temp files");
                for (TmpFile tmpFile : tmpFiles)
                    tmpFile.delete();
            }
        } catch (Error e) {
            //ok to catch, because thrown at end
            //noinspection finally
            try {
                LOG.error("Error starting ExternalTerminal Thread", e);
                if (!jFedPreferences.getBoolean(GuiPreferenceKey.PREF_TERMINAL_KEEP_TMP_FILES, true)) {
                    LOG.warn("  because of exception starting ExternalTerminal Thread -> will delete temp files");
                    for (TmpFile tmpFile : tmpFiles)
                        tmpFile.delete();
                }
            } finally {
                throw e;
            }
        }

        if (isMac)
            try {
                //show a (mutable) notification to mac-users that the terminal opens in the background
                if (jFedPreferences.getBoolean(GuiPreferenceKey.PREF_SHOW_MAC_TERMINAL_WARNING, true)) {
                    VBox pane = new VBox();
                    pane.setPrefWidth(750);
                    pane.setSpacing(5);

                    Label textLabel = new Label(String.format("An SSH-terminal to %s@%s:%d was launched.\n" +
                                    "It may however be on the background. Please switch applications to access your terminal.",
                            userName, hostName, port));
                    textLabel.setPrefHeight(75);

                    textLabel.setWrapText(true);
                    pane.getChildren().add(textLabel);
                    final CheckBox checkBox = new CheckBox("Do not show this warning again");
                    pane.getChildren().add(checkBox);


                    DialogPane dialogPane = new DialogPane();
                    // bvermeul, FEDIBBTDEV-1049
                    dialogPane.setContent(pane);
                    dialogPane.getButtonTypes().setAll(ButtonType.OK);


                    Dialog<ButtonType> dialog = new Dialog<>();
                    dialog.setTitle("Terminal was launched");
                    dialog.setDialogPane(dialogPane);

                    dialog.showAndWait();

                    //dialogPane.setContent(pane);


                    //Alert alert = new Alert(Alert.AlertType.INFORMATION);
                    //alert.setTitle("Terminal was launched");
                    //alert.setDialogPane(dialogPane);
                    //alert.show();

                    jFedPreferences.setBoolean(GuiPreferenceKey.PREF_SHOW_MAC_TERMINAL_WARNING,
                            !checkBox.isSelected());
                }
            } catch (Exception e) {
                LOG.error("Exception while showing MAC terminal dialog. (will be ignored)", e);
            } catch (AssertionError e) {
                LOG.error("AssertionError while showing MAC terminal dialog. (will be ignored)", e);
            }
    }

}

