package be.iminds.ilabt.jfed;

import be.iminds.ilabt.jfed.ui.javafx.dialogs.JFDialogs;
import javafx.application.Platform;
import javafx.scene.control.ButtonType;
import javafx.stage.Stage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Objects;
import java.util.Optional;

/**
 * User: twalcari
 * Date: 6/25/2015
 * Time: 13:48
 */
public class UncaughtGuiExceptionLogger implements Thread.UncaughtExceptionHandler {
    private static final Logger LOG = LoggerFactory.getLogger(UncaughtGuiExceptionLogger.class);

    private final Stage stage;

    private UncaughtGuiExceptionLogger(Stage stage) {
        this.stage = stage;
    }

    private static UncaughtGuiExceptionLogger instance;

    /* singleton, this way, it can optionally later be used by other parts of jFed to retrieve exception info. */
    public static UncaughtGuiExceptionLogger getInstance(Stage stage) {
        if (instance == null) {
            instance = new UncaughtGuiExceptionLogger(stage);
        }
        return instance;
    }

    @Override
    public void uncaughtException(Thread t, Throwable e) {
        LOG.error("UNCAUGHT ERROR IN THREAD {}", t.getName(), e);

        Platform.runLater(() -> {if (e instanceof OutOfMemoryError) {
            if (stage != null) {
                try {
                    Optional<ButtonType> reply =
                            JFDialogs.create()
                                    .owner(stage)
                                    .message("jFed has run out of memory. This will cause bugs and instabilities.\n" +
                                            "It is advised to close jFed now and restart it.\n\n" +
                                            "You can choose to continue. You might still be able to save your work.\n\n" +
                                            "Continue running jFed?")
                                    .masthead("Out of Memory!")
                                    .buttonTypes(ButtonType.YES, ButtonType.NO,ButtonType.CANCEL)
                                    .showWarning();

                    if (reply.isPresent() && Objects.equals(reply.get(), ButtonType.YES)) {
                        LOG.warn("User chose to continue after out of memory.");
                    } else {
                        LOG.warn("User chose to exit after out of memory.");
                        System.exit(-1);
                    }
                } catch (Throwable throwable) {
                    System.err.println("jFed encountered an exception trying to handle OutOfMemoryError dialog. Will exit.");
                    LOG.error("jFed encountered an exception trying to handle OutOfMemoryError dialog. Will exit.", throwable);
                    System.exit(-1);
                }
            } else {
                System.err.println("jFed ran out of memory and will exit.");
                LOG.warn("jFed ran out of memory and will exit.", e);
                System.exit(-1);
            }
        } else {
//            if (e instanceof Error) {
            //any uncaught exception is bad.
            if (stage != null) {
                try {
                    JFDialogs.create()
                            .owner(stage)
                            .message("jFed encountered a serious error. This will cause likely bugs and instabilities.\n\n" +
                                    "Please copy this exception and send it to the jFed developers.\n\n" +
                                    "It might be a good idea to close jFed.")
                            .masthead("Internal Error.")
                            .showException(e);

                    LOG.warn("Exception was shown to user.");
                } catch (Throwable throwable) {
                    System.err.println("jFed encountered an exception trying to handle Error dialog.");
                    LOG.error("jFed encountered an exception trying to handle Error dialog.", throwable);
                }
            } else {
                System.err.println("jFed encountered Error. Will try to continue.");
                e.printStackTrace();
                LOG.warn("jFed encountered Error. Will try to continue.", e);
            }
//            }
        }});
    }
}
