package ij.plugin;
import ij.*;
import ij.plugin.frame.Editor;
import javax.script.*;

/** Implements the macro editor's Macros/Evaluate JavaScript command 
    on systems running Java 1.6 or later. The JavaScript plugin at
    <http://rsb.info.nih.gov/ij/plugins/download/misc/JavaScript.java>
    is used to evaluate JavaScript on systems running versions
    of Java earlier than 1.6. */
public class JavaScriptEvaluator implements PlugIn, Runnable  {
    private Thread thread;
    private String script;
    private Object result;

    // run script in separate thread
    public void run(String script) {
        if (script.equals("")) return;
        if (!IJ.isJava16()) {
            IJ.error("Java 1.6 or later required");
            return;
        }
        this.script = script;
        thread = new Thread(this, "JavaScript"); 
        thread.setPriority(Math.max(thread.getPriority()-2, Thread.MIN_PRIORITY));
        thread.start();
    }

    // run script in current thread
    public String run(String script, String arg) {
        this.script = script;
        run();
        return null;
    }

    public void run() {
        result = null;
        Thread.currentThread().setContextClassLoader(IJ.getClassLoader());
        try {
            ScriptEngineManager scriptEngineManager = new ScriptEngineManager();
            ScriptEngine engine = scriptEngineManager.getEngineByName("ECMAScript");
            if (engine == null) {
                IJ.error("Could not find JavaScript engine");
                return;
            }
            if (!IJ.isJava18()) {
                engine.eval("function load(path) {\n"
                    + "  importClass(Packages.sun.org.mozilla.javascript.internal.Context);\n"
                    + "  importClass(Packages.java.io.FileReader);\n"
                    + "  var cx = Context.getCurrentContext();\n"
                    + "  cx.evaluateReader(this, new FileReader(path), path, 1, null);\n"
                    + "}");
            }
            result = engine.eval(script);
        } catch(Throwable e) {
            String msg = e.getMessage();
            if (msg==null)
                msg = "";
            if (msg.startsWith("sun.org.mozilla.javascript.internal.EcmaError: "))
                msg = msg.substring(47, msg.length());
            if (msg.startsWith("sun.org.mozilla.javascript.internal.EvaluatorException"))
                msg = "Error"+msg.substring(54, msg.length());
            if (msg.length()>0 && !msg.contains("Macro canceled"))
                IJ.log(msg);
        }
    }
    
    public String toString() {
        return result!=null?""+result:"";
    }

}