// Path: src/main/java/com/superzanti/serversync/util/Logger.java
// public class Logger {
//     public static LoggerInstance instance = null;
//     private static final Object mutex = new Object();
//     private static Handler uiHandler;
// 
//     // Probably a heinous implementation of debounce but whatever
//     private static final long dbTimeMS = 2000L;
//     private static final ScheduledExecutorService dbRunner = Executors.newSingleThreadScheduledExecutor();
//     private static ScheduledFuture<?> waitingFlush;
// 
//     public static String getContext() {
//         return ServerSync.MODE == null ? "undefined" : ServerSync.MODE.toString();
//     }
// 
//     public static LoggerInstance getInstance() {
//         LoggerInstance result = instance;
//         if (result == null) {
//             //synchronized block to remove overhead
//             synchronized (mutex) {
//                 result = instance;
//                 if (result == null) {
//                     // if instance is null, initialize
//                     instance = result = new LoggerInstance(getContext());
//                 }
//             }
//         }
//         return result;
//     }
// 
//     public static void instantiate(String context) {
//         instance = new LoggerInstance(context);
//     }
// 
//     public static synchronized void setSystemOutput(boolean output) {
//         // enable/disable System.out logging
//         getInstance().javaLogger.setUseParentHandlers(output);
//     }
// 
//     public static synchronized void log(String s) {
//         getInstance().log(s);
//     }
// 
//     public static synchronized void error(String s) {
//         getInstance().error(s);
//     }
// 
//     public static synchronized void debug(String s) {
//         getInstance().debug(s);
//     }
// 
//     public static synchronized void debug(Exception e) {
//         getInstance().debug(Arrays.toString(e.getStackTrace()));
//     }
// 
//     public static synchronized void outputError(Object object) {
//         getInstance().debug("Failed to write object (" + object + ") to output stream");
//     }
// 
//     public static synchronized void attachUIHandler(Handler handler) {
//         if (uiHandler != null) {
//             uiHandler.close();
//             getInstance().javaLogger.removeHandler(uiHandler);
//         }
//         uiHandler = handler;
//         getInstance().javaLogger.addHandler(uiHandler);
//     }
// 
//     public static synchronized void flush() {
//         if (uiHandler != null) {
//             if (waitingFlush == null || waitingFlush.isDone()) {
//                 waitingFlush = dbRunner.schedule(() -> {
//                     uiHandler.flush();
//                 }, dbTimeMS, TimeUnit.MILLISECONDS);
//             }
//         }
//     }
// }


import com.superzanti.serversync.util.Logger;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.geometry.Insets;
import javafx.scene.control.TextArea;
import javafx.scene.layout.BorderPane;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.util.logging.SimpleFormatter;
package com.superzanti.serversync.GUIJavaFX;



// GUI for showing the logs
public class PaneLogs extends BorderPane {

    private final TextArea textArea = new TextArea();

    public PaneLogs() {
        textArea.setEditable(false);
        setMargin(textArea, new Insets(10, 10, 10, 10));
        this.setCenter(textArea);
        final StringProperty records = new SimpleStringProperty();
        getText().textProperty().bind(records);

        Handler handler = new Handler() {
            final SimpleFormatter fmt = new SimpleFormatter();
            final StringBuilder r = new StringBuilder();


            @Override
            public void publish(LogRecord record) {
                if (record.getLevel().equals(Level.INFO)) {
                    r.append(fmt.format(record));
// Path: src/main/java/com/superzanti/serversync/util/Logger.java
// public class Logger {
//     public static LoggerInstance instance = null;
//     private static final Object mutex = new Object();
//     private static Handler uiHandler;
// 
//     // Probably a heinous implementation of debounce but whatever
//     private static final long dbTimeMS = 2000L;
//     private static final ScheduledExecutorService dbRunner = Executors.newSingleThreadScheduledExecutor();
//     private static ScheduledFuture<?> waitingFlush;
// 
//     public static String getContext() {
//         return ServerSync.MODE == null ? "undefined" : ServerSync.MODE.toString();
//     }
// 
//     public static LoggerInstance getInstance() {
//         LoggerInstance result = instance;
//         if (result == null) {
//             //synchronized block to remove overhead
//             synchronized (mutex) {
//                 result = instance;
//                 if (result == null) {
//                     // if instance is null, initialize
//                     instance = result = new LoggerInstance(getContext());
//                 }
//             }
//         }
//         return result;
//     }
// 
//     public static void instantiate(String context) {
//         instance = new LoggerInstance(context);
//     }
// 
//     public static synchronized void setSystemOutput(boolean output) {
//         // enable/disable System.out logging
//         getInstance().javaLogger.setUseParentHandlers(output);
//     }
// 
//     public static synchronized void log(String s) {
//         getInstance().log(s);
//     }
// 
//     public static synchronized void error(String s) {
//         getInstance().error(s);
//     }
// 
//     public static synchronized void debug(String s) {
//         getInstance().debug(s);
//     }
// 
//     public static synchronized void debug(Exception e) {
//         getInstance().debug(Arrays.toString(e.getStackTrace()));
//     }
// 
//     public static synchronized void outputError(Object object) {
//         getInstance().debug("Failed to write object (" + object + ") to output stream");
//     }
// 
//     public static synchronized void attachUIHandler(Handler handler) {
//         if (uiHandler != null) {
//             uiHandler.close();
//             getInstance().javaLogger.removeHandler(uiHandler);
//         }
//         uiHandler = handler;
//         getInstance().javaLogger.addHandler(uiHandler);
//     }
// 
//     public static synchronized void flush() {
//         if (uiHandler != null) {
//             if (waitingFlush == null || waitingFlush.isDone()) {
//                 waitingFlush = dbRunner.schedule(() -> {
//                     uiHandler.flush();
//                 }, dbTimeMS, TimeUnit.MILLISECONDS);
//             }
//         }
//     }
// }


// Path: src/main/java/com/superzanti/serversync/GUIJavaFX/PaneLogs.java
import com.superzanti.serversync.util.Logger;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.geometry.Insets;
import javafx.scene.control.TextArea;
import javafx.scene.layout.BorderPane;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.util.logging.SimpleFormatter;

package com.superzanti.serversync.GUIJavaFX;



// GUI for showing the logs
public class PaneLogs extends BorderPane {

    private final TextArea textArea = new TextArea();

    public PaneLogs() {
        textArea.setEditable(false);
        setMargin(textArea, new Insets(10, 10, 10, 10));
        this.setCenter(textArea);
        final StringProperty records = new SimpleStringProperty();
        getText().textProperty().bind(records);

        Handler handler = new Handler() {
            final SimpleFormatter fmt = new SimpleFormatter();
            final StringBuilder r = new StringBuilder();


            @Override
            public void publish(LogRecord record) {
                if (record.getLevel().equals(Level.INFO)) {
                    r.append(fmt.format(record));
                    Logger.flush();