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

import be.iminds.ilabt.jfed.BaseGuiModule;
import be.iminds.ilabt.jfed.UncaughtGuiExceptionLogger;
import be.iminds.ilabt.jfed.highlevel.HighLevelModule;
import be.iminds.ilabt.jfed.highlevel.LowLevelModule;
import be.iminds.ilabt.jfed.highlevel.SfaOnlyExperimentModule;
import be.iminds.ilabt.jfed.highlevel.UserLoginModelModule;
import be.iminds.ilabt.jfed.highlevel.controller.TaskThread;
import be.iminds.ilabt.jfed.lowlevel.GeniUser;
import be.iminds.ilabt.jfed.lowlevel.GeniUserProvider;
import be.iminds.ilabt.jfed.ssh_terminal_tool.unix.SshAgentHelper;
import be.iminds.ilabt.jfed.ui.javafx.userlogin.AdvancedUserLoginDialog;
import be.iminds.ilabt.jfed.ui.javafx.util.ExtraInfoCallBackGUIs;
import be.iminds.ilabt.jfed.util.GuiceContext;
import com.google.inject.AbstractModule;
import com.google.inject.Module;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.stage.Stage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.inject.Inject;
import javax.inject.Provider;
import java.util.ArrayList;
import java.util.List;

public class JFedProbeStandalone extends Application implements GeniUserProvider {
    private static final Logger LOG = LoggerFactory.getLogger(JFedProbeStandalone.class);
    /**
     * The main() method is ignored in correctly deployed JavaFX application.
     * main() serves only as fallback in case the application can not be
     * launched through deployment artifacts, e.g., in IDEs with limited FX
     * support. NetBeans ignores main().
     *
     * @param args the command line arguments
     */
    public static boolean debugEnabled = false;

    /* solution for MAC OS HeadlessException bug. See https://ibcn-jira.intec.ugent.be/browse/FEDIBBTDEV-239 */
    static {
        System.setProperty("java.awt.headless", "false");
    }

    private final GuiceContext context = new GuiceContext(this, () -> {
        List<Module> modules = new ArrayList<>();
        modules.add(new AbstractModule() {
            @Override
            protected void configure() {
                bind(GeniUserProvider.class).toInstance(JFedProbeStandalone.this);
            }
        });
        modules.add(new HighLevelModule());
        modules.add(new SfaOnlyExperimentModule());
        modules.add(new LowLevelModule());
        modules.add(new UserLoginModelModule(false/*requireAllUserInfo*/));
        modules.add(new BaseGuiModule());
        return modules;
    });
    @Inject
    private Provider<AdvancedUserLoginDialog> advancedUserLoginDialogProvider;
    @Inject
    private ProbeFactory probeFactory;
    @Inject
    private TaskThread tt;
    private GeniUser loggedInGeniUser;

    public static void main(String[] args) {
        for (String arg : args) {
            if (arg.equalsIgnoreCase("debug") || arg.equalsIgnoreCase("--debug") || arg.equalsIgnoreCase("-debug"))
                debugEnabled = true;
        }
        launch(args);
    }

    @Override
    public void start(final Stage stage) throws Exception {
        Thread.setDefaultUncaughtExceptionHandler(UncaughtGuiExceptionLogger.getInstance(stage));
        context.init();

        ExtraInfoCallBackGUIs.prepareExtraInfoCallback(stage);

        stage.setOnCloseRequest(event -> exit());

        loggedInGeniUser = advancedUserLoginDialogProvider.get().showUserLogin(stage);


        probeFactory.showProbe(stage);

    }

    public void exit() {
        LOG.info("Close was requested. Trying to terminate");
        tt.requestStop();

        //stop any running ssh-agent
        SshAgentHelper.stopSshAgent();

        Platform.exit();
        System.exit(0);
    }

    @Override
    public GeniUser getLoggedInGeniUser() {
        return loggedInGeniUser;
    }

    @Override
    public boolean isUserLoggedIn() {
        return loggedInGeniUser != null;
    }
}
