// Path: src/main/java/com/superzanti/serversync/RefStrings.java
// public class RefStrings {
//     public static final String MODID = "com.superzanti.serversync";
//     public static final String NAME = "ServerSync";
//     public static final String VERSION = "v4.2.0";
// 
//     public static final String ERROR_TOKEN = "<E>";
//     public static final String DELETE_TOKEN = "<D>";
//     public static final String UPDATE_TOKEN = "<U>";
//     public static final String CLEANUP_TOKEN = "<C>";
//     public static final String IGNORE_TOKEN = "<I>";
// }
// 
// 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.eclipsesource.json.Json;
import com.eclipsesource.json.JsonObject;
import com.superzanti.serversync.RefStrings;
import com.superzanti.serversync.util.Logger;
import javafx.application.Platform;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.control.Hyperlink;
import javafx.scene.control.Label;
import javafx.scene.layout.GridPane;
import java.awt.Desktop;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.*;
                } catch (URISyntaxException | IOException e) {
                    e.printStackTrace();
                }
            }

        });

        this.setAlignment(Pos.CENTER);
        this.setHgap(10);
        this.setVgap(10);
        this.setPadding(new Insets(10, 10, 10, 10));

        this.add(labelCurVersion,0,0);
        this.add(labelCurVersion2,1,0);
        this.add(labelVersion,0,1);
        this.add(labelVersion2,1,1);
        this.add(labelUrl,0,2);
        this.add(hyperUpdatedUrl,1,2);

        Platform.runLater(this::getLastReleases);
    }

    public void getLastReleases() {
        //String url = "https://github.com/superzanti/ServerSync/releases/latest";

        // Create a neat value object to hold the URL
        try {
            URL url = new URL("https://github.com/superzanti/ServerSync/releases/latest");

            // Open a connection(?) on the URL(??) and cast the response(???)
// Path: src/main/java/com/superzanti/serversync/RefStrings.java
// public class RefStrings {
//     public static final String MODID = "com.superzanti.serversync";
//     public static final String NAME = "ServerSync";
//     public static final String VERSION = "v4.2.0";
// 
//     public static final String ERROR_TOKEN = "<E>";
//     public static final String DELETE_TOKEN = "<D>";
//     public static final String UPDATE_TOKEN = "<U>";
//     public static final String CLEANUP_TOKEN = "<C>";
//     public static final String IGNORE_TOKEN = "<I>";
// }
// 
// 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/PaneUpdate.java
import com.eclipsesource.json.Json;
import com.eclipsesource.json.JsonObject;
import com.superzanti.serversync.RefStrings;
import com.superzanti.serversync.util.Logger;
import javafx.application.Platform;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.control.Hyperlink;
import javafx.scene.control.Label;
import javafx.scene.layout.GridPane;
import java.awt.Desktop;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.*;

                } catch (URISyntaxException | IOException e) {
                    e.printStackTrace();
                }
            }

        });

        this.setAlignment(Pos.CENTER);
        this.setHgap(10);
        this.setVgap(10);
        this.setPadding(new Insets(10, 10, 10, 10));

        this.add(labelCurVersion,0,0);
        this.add(labelCurVersion2,1,0);
        this.add(labelVersion,0,1);
        this.add(labelVersion2,1,1);
        this.add(labelUrl,0,2);
        this.add(hyperUpdatedUrl,1,2);

        Platform.runLater(this::getLastReleases);
    }

    public void getLastReleases() {
        //String url = "https://github.com/superzanti/ServerSync/releases/latest";

        // Create a neat value object to hold the URL
        try {
            URL url = new URL("https://github.com/superzanti/ServerSync/releases/latest");

            // Open a connection(?) on the URL(??) and cast the response(???)
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();