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

import be.iminds.ilabt.jfed.BaseGuiModule;
import be.iminds.ilabt.jfed.UncaughtGuiExceptionLogger;
import be.iminds.ilabt.jfed.fedmon.webapi.service.json.Testbed;
import be.iminds.ilabt.jfed.highlevel.LowLevelModule;
import be.iminds.ilabt.jfed.highlevel.UserLoginModelModule;
import be.iminds.ilabt.jfed.lowlevel.GeniUser;
import be.iminds.ilabt.jfed.lowlevel.GeniUserProvider;
import be.iminds.ilabt.jfed.lowlevel.TestbedInfoSource;
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.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 ScannerStandalone extends Application implements GeniUserProvider {
    private static final Logger LOG = LoggerFactory.getLogger(ScannerStandalone.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 LowLevelModule());
        modules.add(new UserLoginModelModule(false/*loginRequiresAlluserInfo*/));
        modules.add(new BaseGuiModule());
        modules.add(binder -> binder.bind(GeniUserProvider.class).toInstance(ScannerStandalone.this));
        return modules;
    });
    @Inject
    private Provider<AdvancedUserLoginDialog> advancedUserLoginDialogProvider;
    @Inject
    private ScanServerDialogFactory scanServerDialogFactory;
    @Inject
    private ScanResultPanelFactory scanResultPanelFactory;
    @Inject
    private TestbedInfoSource testbedInfoSource;

    private GeniUser loggedInGeniUser = null;

    public static void main(String[] args) {
        for (String arg : args) {
            if (arg.equalsIgnoreCase("debug") || arg.equalsIgnoreCase("--debug") || arg.equalsIgnoreCase("-debug"))
                debugEnabled = true;
        }
        Application.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);

        if (!isUserLoggedIn())
            exit();

        //noinspection StatementWithEmptyBody
        while (showScanner()) { /*nothing in loop*/ }

        exit();
    }

    /**
     * returns true if scan again has been chosen
     */
    public boolean showScanner() {
        ScanServerDialogFactory.ScanServerDialogResult scanServerDialogResult =
                scanServerDialogFactory.showScanAuthorityDialog(false/*dialog*/);

        if(scanServerDialogResult == null)
            return false;

        if (scanServerDialogResult.getResult() == null)
            return scanServerDialogResult.isScanAgain();

        Testbed testbed = scanServerDialogResult.getResult();

        LOG.debug("Showing scanner for auth " + (testbed == null ? null
                : testbed.getDefaultComponentManagerAsGeniUrn()));
        boolean scanAgain = scanResultPanelFactory.showScanResultPanel(testbed, false/*dialog*/);
        return scanAgain;
    }

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

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

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

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