package me.coley.recaf.util;

import me.coley.recaf.Recaf;

import javax.swing.*;

import static me.coley.recaf.util.Classpath.getSystemClass;

/**
 * Check if Recaf can be run on the current JVM.
 * 
 * <ul>
 * <li>Prevent execution on modularized JVM's until support is added</li>
 * <li>Verify compatible JavaFX</li>
 * </ul>
 * 
 * @author Matt
 */
public class Dependencies {

	public static boolean check() {
		double version = getVersion();
		if(version < 1.8) {
			// Java 7-
			err("Outdated Java", "Please update java to the latest of Java 8 before using Recaf.");
			return false;
		} else if(version == 1.8) {
			// Java 8
			if(checkJFX()) {
				// Using up-to-date java 8 (including associated JavaFx version)
				return true;
			} else {
				err("Outdated JavaFX", "Please update Java 8 to the latest release.");
				return false;
			}
		} else if(version > 1.8 && version < 11) {
			// Java 9/10
			//
			// Unsupported since Java 11 is the first Jigsaw LTS.
			err("Unsupported Java Version", "Java versions 9 & 10 are not supported. Please " +
					"upgrade to Java 11 to run Recaf.");
			return false;
		} else {
			// Java 11+
			//
			// Will have to ensure usage of updated ControlsFx & JavaFx
			if(!checkJFX()) {
				// Run external script to update the Recaf jar with the proper dependencies
				System.out.println("Detected JDK 11+ without OpenJFX dependencies\n" +
						"Dependencies will be downloaded and Recaf will restart...");
				Updater.updateViaJdk11Patch(Recaf.args);
				return false;
			}
			// All good to go
			return true;
		}
	}

	private static boolean checkJFX() {
		// Checking these classes because JavaFX used to be linked to the actual Java release.
		// Some early versions of 1.8 are 'missing' these classes. So verify we have them.
		if (!exists("javafx.scene.control.MenuBar") || !exists("javafx.scene.control.Menu")) {
			return false;
		}
		try {
			getSystemClass("javafx.scene.control.MenuBar").getConstructor(getSystemClass("[Ljavafx.scene.control.Menu;"));
		} catch (Exception e) {
			return false;
		}
		return true;
	}

	public static double getVersion() {
		String version = System.getProperty("java.version");
		int pos = version.indexOf('.');
		if (pos == -1)
			return Double.parseDouble(version);
		pos = version.indexOf('.', pos + 1);
		return Double.parseDouble(version.substring(0, pos));
	}

	private static void err(String title, String msg) {
		System.err.println(msg);
		JOptionPane.showMessageDialog(null, msg, title, JOptionPane.ERROR_MESSAGE);
	}

	private static boolean exists(String className) {
		return Classpath.getSystemClassIfExists(className).isPresent();
	}
}

@@ -68,78 +68,55 @@
 java
-x.swing.*;%0A%0Aimport static me.coley.recaf.util.Classpath.getSystemClass
+.lang.reflect.Constructor;%0Aimport javax.swing.*
 ;%0A%0A/
@@ -422,16 +422,17 @@
 ();%0A%09%09if
+ 
 (version
@@ -566,32 +566,33 @@
 lse;%0A%09%09%7D else if
+ 
 (version == 1.8)
@@ -612,16 +612,17 @@
  8%0A%09%09%09if
+ 
 (checkJF
@@ -835,16 +835,17 @@
  else if
+ 
 (version
@@ -1195,16 +1195,17 @@
 Fx%0A%09%09%09if
+ 
 (!checkJ
@@ -1765,18 +1765,35 @@
 .%0A%09%09
-if (!exist
+Class%3C?%3E menuBar = findClas
 s(%22j
@@ -1825,18 +1825,36 @@
 ar%22)
- %7C%7C !exist
+;%0A%09%09Class%3C?%3E menu = findClas
 s(%22j
@@ -1883,198 +1883,298 @@
 nu%22)
-) %7B%0A%09%09%09return false;%0A%09%09%7D%0A%09%09try %7B%0A%09%09%09getSystemClass(%22
+;%0A%09%09if (menuBar == null %7C%7C menu == null) %7B%0A%09%09%09return false;%0A%09%09%7D%0A%0A%09%09// Find %3Cinit%3E(%5BL
 javafx
-.
+/
 scene
-.
+/
 control
-.
+/
 Menu
-Bar%22).getConstructor(getSystemClass(%22%5BLjavafx.scene.c
+;)V%0A%09%09for (Constructor%3C?%3E constructor : menu.getC
 on
+s
 tr
-ol.Menu;%22));%0A%09%09%7D catch (Exception e
+uctors()) %7B%0A%09%09%09if (constructor.getParameterCount() == 1 && constructor.getParameterTypes()%5B0%5D == menu
 ) %7B%0A%09%09%09
+%09
 return 
-fals
+tru
 e;%0A
+%09%09%09%7D%0A
 %09%09%7D%0A
@@ -2178,27 +2178,28 @@
 %09%7D%0A%09%09return 
-tru
+fals
 e;%0A%09%7D%0A%0A%09publ
@@ -2656,21 +2656,25 @@
 tic 
-boolean exist
+Class%3C?%3E findClas
 s(St
@@ -2691,16 +2691,25 @@
 Name) %7B%0A
+%09%09try %7B%0A%09
 %09%09return
@@ -2718,59 +2718,131 @@
 lass
-path.getSystemClassIfExists(className).isPresent();
+.forName(className, false, Dependencies.class.getClassLoader());%0A%09%09%7D catch (ClassNotFoundException e) %7B%0A%09%09%09return null;%0A%09%09%7D
 %0A%09%7D%0A

Fix #156