/**
 * The Java(TM) Compiler is invoked in the method compile() essentially as
 * shown in the docu for the javax.tools.JavaCompiler interface(
 * https://docs.oracle.com/javase/7/docs/api/javax/tools/JavaCompiler.html).
 */ 
package eg.javatools;

import javax.tools.Diagnostic;
import javax.tools.DiagnosticCollector;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.ToolProvider;
import javax.tools.JavaCompiler.CompilationTask;
import javax.tools.StandardJavaFileManager;

import java.io.File;
import java.io.IOException;

import java.util.List;
import java.util.Arrays;
import java.util.ArrayList;

//--Eadgyth--//
import eg.Preferences;
import eg.utils.Dialogs;
import eg.console.ConsolePanel;

/**
 * Compiles java files in a given working directory using the
 * JavaCompiler API.
 */
public class Compile {

   private final static Preferences PREFS = new Preferences();
   private final static String F_SEP = File.separator;

   private static String jdkPath = null;
   
   private final ConsolePanel consPnl;
   
   private boolean success = false;
   private ArrayList<String> errorInfo;
   
   /**
    * @param consPnl  the reference to {@link ConsolePanel} in whose
    * text area messages are displayed
    */
   public Compile(ConsolePanel consPnl) {
      this.consPnl = consPnl;
   }
   
   /**
    * @return  true if all java files compiled without
    * errors; false otherwise
    */
   public boolean success() {
      return success;
   }
   
   /**
    * @return  the first of all listed error messages that contain
    * the info about the line number an the source file
    */
   public String getMessage() {   
      return errorInfo.get(0);
   }

   /**
    * Invokes the javac compiler
    *
    * @param projectPath  the root directory of the project
    * @param classDir  the target directory of the class files
    * @param sourceDir  the directory that contains java files
    */
   public void compile(String projectPath, String classDir, String sourceDir) {
      success = false;
      errorInfo = new ArrayList<>();
      if (jdkPath == null) {
         setJdkPath();
         if (jdkPath == null) {
            errorInfo.add(
                  "The filepath of the JDK is not defined");
            consPnl.appendText(
                  "<<ERROR:\nThe file path of the JDK is not defined"
                  + " in'settings.properties'.>>");
            return;
         }
      }
      String targetDir = targetDir(projectPath, classDir);
      String[] compileOptions = new String[] {"-d", targetDir} ;
      Iterable<String> compilationOptions = Arrays.asList(compileOptions);      
      JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
      DiagnosticCollector<JavaFileObject> diagnostics
            = new DiagnosticCollector<>();
      StandardJavaFileManager fileManager
            = compiler.getStandardFileManager(null, null, null);
      Iterable<? extends JavaFileObject> units;
      List<File> classes = new SearchFiles().filteredFiles(projectPath
            + F_SEP + sourceDir, ".java");
      File[] fileArr = classes.toArray(new File[classes.size()]);
      units = fileManager.getJavaFileObjects(fileArr);
      CompilationTask task = compiler.getTask(null, fileManager, diagnostics,
              compilationOptions, null, units);
      success = task.call();       
      output(diagnostics);
      try {
         fileManager.close();
      } catch (IOException e) {
         System.out.println(e.getMessage());
      }
   }
   
   private void output(DiagnosticCollector<JavaFileObject> diagnostics) {
      if (success) {
         consPnl.appendText("<<Compilation successful>>");
      }
      else {
         for (Diagnostic<?> diagnostic : diagnostics.getDiagnostics()) {
            consPnl.appendText(diagnostic.getKind().toString() + ":\n");
            consPnl.appendText(diagnostic.getCode() + ": ");
            consPnl.appendText(diagnostic.getMessage( null ) + "\n");
            consPnl.appendText("at line: " + diagnostic.getLineNumber() + "\n");
            consPnl.appendText("at column: " + diagnostic.getColumnNumber() + "\n");
            if (diagnostic.getSource() != null) { // can be null!
               consPnl.appendText(diagnostic.getSource().toString() + "\n");
               String file = new File(diagnostic.getSource().toString()).getName();
               file = file.substring(0, file.length() - 1);
               errorInfo.add("First listed error is found in " + file + ", line " 
                     + diagnostic.getLineNumber());
            }
            String devider = "_";
            for (int i = 0; i <= 90; i++) {
               consPnl.appendText(devider);
            }
            consPnl.appendText("\n");
         }
      }
   }

   /**
    * @return  the directory where class files/packages are saved
    */
   private String targetDir(String projectPath, String classDir) {
      String targetDir;
      if (classDir.length() > 0) {
         File target = new File(projectPath + F_SEP + classDir);
         target.mkdirs();
         targetDir = projectPath + F_SEP + classDir;
      }
      else {
         targetDir = projectPath;
      }
      return targetDir;
   }

   /**
    * Sets the path to the Java JDK and asks for a new path if no valid path is
    * found in Settings.properties
    */
   private void setJdkPath() {
      PREFS.readSettings();
      jdkPath = PREFS.getProperty("LocationOfJDK");
      if (!new File(jdkPath).exists()) {
         String notFound = "The JDK was not found."
               + " Enter or correct the filepath of the JDK.";
         jdkPath = Dialogs.textFieldInput(notFound, "Location of JDK", jdkPath);
         if (jdkPath != null) { // if ok clicked
            PREFS.storeSettings(jdkPath);
            setJdkPath();
         }
      }
      else {
         System.setProperty("java.home", jdkPath);
         System.out.println("Set Location of JDK: " + jdkPath);
      }
   }
}

@@ -968,50 +968,8 @@
 tor;
-%0A%0A   private static String jdkPath = null;
 %0A   
@@ -1993,110 +1993,66 @@
     
-success = false;%0A      errorInfo = new ArrayList%3C%3E();%0A      if (jdkPath == null) %7B%0A         setJdkPath
+JavaCompiler compiler = ToolProvider.getSystemJavaCompiler
 ();%0A
@@ -2057,30 +2057,28 @@
 ;%0A      
-   
 if (
-jdkPath
+compiler
  == null
@@ -2094,279 +2094,149 @@
     
-   errorInfo.add(%0A                  %22The filepath of the JDK is not defined%22);%0A            consPnl.appendText(%0A                  %22%3C%3CERROR:%5CnThe file path
+Dialogs.errorMessage(%22The programm may not be run in the JRE
  of 
-the
+a
  JDK
- is not defined%22
+.%22);
 %0A      
+%7D%0A
       
-      + %22 in'settings.properties'.%3E%3E%22);%0A            return;%0A         %7D%0A      %7D
+success = false;%0A      errorInfo = new ArrayList%3C%3E();
 %0A   
@@ -2441,76 +2441,8 @@
    %0A
-      JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();%0A
     
@@ -4947,762 +4947,7 @@
    %7D
-%0A%0A   /**%0A    * Sets the path to the Java JDK and asks for a new path if no valid path is%0A    * found in Settings.properties%0A    */%0A   private void setJdkPath() %7B%0A      PREFS.readSettings();%0A      jdkPath = PREFS.getProperty(%22LocationOfJDK%22);%0A      if (!new File(jdkPath).exists()) %7B%0A         String notFound = %22The JDK was not found.%22%0A               + %22 Enter or correct the filepath of the JDK.%22;%0A         jdkPath = Dialogs.textFieldInput(notFound, %22Location of JDK%22, jdkPath);%0A         if (jdkPath != null) %7B // if ok clicked%0A            PREFS.storeSettings(jdkPath);%0A            setJdkPath();%0A         %7D%0A      %7D%0A      else %7B%0A         System.setProperty(%22java.home%22, jdkPath);%0A         System.out.println(%22Set Location of JDK: %22 + jdkPath);%0A      %7D%0A   %7D
 %0A%7D%0A

remove setting the java_home