package be.iminds.ilabt.jfed.experimenter_gui.bugreport_viewer;

import be.iminds.ilabt.jfed.log.cache.ApiCallDetailsCache;
import be.iminds.ilabt.jfed.log.cache.DiskApiCallDetailsCache;
import be.iminds.ilabt.jfed.ui.javafx.dialogs.JFDialogs;
import be.iminds.ilabt.jfed.ui.javafx.util.ExtraInfoCallBackGUIs;
import be.iminds.ilabt.jfed.util.GuiceContext;
import be.iminds.ilabt.jfed.util.JFedUtils;
import com.google.inject.Module;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.stage.Stage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.inject.Inject;
import javax.inject.Singleton;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * BugReportViewerStandalone
 */
public class BugReportViewerStandalone extends Application {
    public final static String BUGREPORT_VIEWER_URL = "bugreport-url";
    private static final Logger LOG = LoggerFactory.getLogger(BugReportViewerStandalone.class);

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

    @Inject
    private FXMLLoader loader;
    private final GuiceContext context = new GuiceContext(this, () -> {
        List<Module> modules = new ArrayList<>();
        modules.add(binder -> binder.bind(ApiCallDetailsCache.class).to(DiskApiCallDetailsCache.class).in(Singleton.class));
        return modules;
    });

    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage stage) throws Exception {
        context.init();
        try {
            //check for filesystem access
            if (JFedUtils.getUserDataDirectory() == null) {

                JFDialogs.create()
                        .owner(stage)
                        .message("Please verify your security settings and try again.\n\n" +
                                "If you are trying to run jFed through Safari on OS X, you need to change your Safari security settings.\n" +
                                "(cfr. http://doc.fed4fire.eu/firstexperiment.html#start-up-jfed)")
                        .masthead("jFed was unable to access the filesystem.")
                        .title("Fatal Error").showError();

                exit();
                return;
            }

            ExtraInfoCallBackGUIs.prepareExtraInfoCallback(stage);

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

            try {
                URL location = BugReportViewerPanel.class.getResource(BugReportViewerPanel.BUG_REPORT_VIEWER_FXML);
                assert location != null;

                loader.setLocation(location);
                stage.setTitle("jFed Bug Report Viewer");
                stage.setScene(new Scene(loader.load()));

                processParameters(loader.getController());

                stage.show();
            } catch (Exception e) {
                throw new RuntimeException("Something went wrong showing the Bug Report Viewer: " + e.getMessage(), e);
            }
        } catch (Exception | AssertionError ex) {
            LOG.error("Fatal error in jFed Bug Report Viewer Main Thread: " + ex.getMessage(), ex);
            JFDialogs.create()
                    .owner(stage)
                    .message("jFed Bug Report Viewer will terminate.")
                    .masthead("A fatal error occurred!")
                    .title("Fatal Error")
                    .showException(ex);

            throw ex;
        }
    }

    public void processParameters(BugReportViewerPanel bugReportViewer) {
        //check if we got a bug report URL via the parameters
        Map<String, String> parametersMap = getParameters().getNamed();

        if (parametersMap.containsKey(BUGREPORT_VIEWER_URL)) {
            String url = parametersMap.get(BUGREPORT_VIEWER_URL);
            try {
                bugReportViewer.setStartReport(url);
            } catch (IOException e) {
                LOG.error("IOException trying to use URL \"" + url + "\" from jnlp parameters", e);
            }
        }

    }

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

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

}
