/*
 * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package apple.applescript;

import java.io.*;
import java.nio.file.Files;
import java.util.*;
import java.util.Map.Entry;

import javax.script.*;

/**
 * AppleScriptEngine implements JSR 223 for AppleScript on Mac OS X
 */
public class AppleScriptEngine implements ScriptEngine {
    private static native void initNative();

    private static native long createContextFrom(final Object object);
    private static native Object createObjectFrom(final long context);
    private static native void disposeContext(final long context);

    private static native long evalScript(final String script, long contextptr);
    private static native long evalScriptFromURL(final String filename, long contextptr);

    static {
        System.loadLibrary("AppleScriptEngine");
        initNative();
        TRACE("<static-init>");
    }

    static void checkSecurity() {
        final SecurityManager securityManager = System.getSecurityManager();
        if (securityManager != null) securityManager.checkExec("/usr/bin/osascript");
    }

    static void TRACE(final String str) {
//        System.out.println(AppleScriptEngine.class.getName() + "." + str);
    }

    /**
     * Accessor for the ScriptEngine's long name variable
     * @return the long name of the ScriptEngine
     */
    protected static String getEngine() {
        TRACE("getEngine()");
        return AppleScriptEngineFactory.ENGINE_NAME;
    }

    /**
     * Accessor for the ScriptEngine's version
     * @return the version of the ScriptEngine
     */
    protected static String getEngineVersion() {
        TRACE("getEngineVersion()");
        return AppleScriptEngineFactory.ENGINE_VERSION;
    }

    /**
     * Accessor for the ScriptEngine's short name
     * @return the short name of the ScriptEngine
     */
    protected static String getName() {
        TRACE("getName()");
        return AppleScriptEngineFactory.ENGINE_SHORT_NAME;
    }

    /**
     * Accessor for the ScriptEngine's supported language name
     * @return the language the ScriptEngine supports
     */
    protected static String getLanguage() {
        TRACE("getLanguage()");
        return AppleScriptEngineFactory.LANGUAGE;
    }

    /**
     * The no argument constructor sets up the object with default members,
     * a factory for the engine and a fresh context.
     * @see com.apple.applescript.AppleScriptEngine#init()
     */
    public AppleScriptEngine() {
        TRACE("<ctor>()");
        // set our parent factory to be a new factory
        factory = AppleScriptEngineFactory.getFactory();

        // set up our noarg bindings
        setContext(new SimpleScriptContext());
        put(ARGV, "");

        init();
    }

    /**
     * All AppleScriptEngines share the same ScriptEngineFactory
     */
    private final ScriptEngineFactory factory;

    /**
     * The local context for the AppleScriptEngine
     */
    private ScriptContext context;

    /**
     * The constructor taking a factory as an argument sets the parent factory for
     * this engine to be the passed factory, and sets up the engine with a fresh context
     * @param factory
     * @see com.apple.applescript.AppleScriptEngine#init()
     */
    public AppleScriptEngine(final ScriptEngineFactory factory) {
        // inherit the factory passed to us
        this.factory = factory;

        // set up our noarg bindings
        setContext(new SimpleScriptContext());
        put(ARGV, "");

        init();
    }

    /**
     * The initializer populates the local context with some useful predefined variables:
     * <ul><li><code>javax_script_language_version</code> - the version of AppleScript that the AppleScriptEngine supports.</li>
     * <li><code>javax_script_language</code> - "AppleScript" -- the language supported by the AppleScriptEngine.</li>
     * <li><code>javax_script_engine</code> - "AppleScriptEngine" -- the name of the ScriptEngine.</li>
     * <li><code>javax_script_engine_version</code> - the version of the AppleScriptEngine</li>
     * <li><code>javax_script_argv</code> - "" -- AppleScript does not take arguments from the command line</li>
     * <li><code>javax_script_filename</code> - "" -- the currently executing filename</li>
     * <li><code>javax_script_name</code> - "AppleScriptEngine" -- the short name of the AppleScriptEngine</li>
     * <li><code>THREADING</code> - null -- the AppleScriptEngine does not support concurrency, you will have to implement thread-safeness yourself.</li></ul>
     */
    private void init() {
        TRACE("init()");
        // set up our context
/* TODO -- name of current executable?  bad java documentation at:
 * https://docs.oracle.com/javase/6/docs/api/javax/script/ScriptEngine.html#FILENAME */
        put(ScriptEngine.FILENAME, "");
        put(ScriptEngine.ENGINE, getEngine());
        put(ScriptEngine.ENGINE_VERSION, getEngineVersion());
        put(ScriptEngine.NAME, getName());
        put(ScriptEngine.LANGUAGE, getLanguage());
        put(ScriptEngine.LANGUAGE_VERSION, getLanguageVersion());

        // TODO -- for now, err on the side of caution and say that we are NOT thread-safe
        put("THREADING", null);
    }

    /**
     * Uses the AppleScriptEngine to get the local AppleScript version
     * @return the version of AppleScript running on the system
     */
    protected String getLanguageVersion() {
        TRACE("AppleScriptEngine.getLanguageVersion()");
        try {
            final Object result = eval("get the version of AppleScript");
            if (result instanceof String) return (String)result;
        } catch (final ScriptException e) { e.printStackTrace(); }
        return "unknown";
    }

    /**
     * Implementation required by ScriptEngine parent<br />
     * Returns the factory parent of this AppleScriptEngine
     */
    public ScriptEngineFactory getFactory() {
        return factory;
    }

    /**
     * Implementation required by ScriptEngine parent<br />
     * Return the engine's context
     * @return this ScriptEngine's context
     */
    public ScriptContext getContext() {
        return context;
    }

    /**
     * Implementation required by ScriptEngine parent<br />
     * Set a new context for the engine
     * @param context the new context to install in the engine
     */
    public void setContext(final ScriptContext context) {
        this.context = context;
    }

    /**
     * Implementation required by ScriptEngine parent<br />
     * Create and return a new set of simple bindings.
     * @return a new and empty set of bindings
     */
    public Bindings createBindings() {
        return new SimpleBindings();
    }

    /**
     * Implementation required by ScriptEngine parent<br />
     * Return the engines bindings for the context indicated by the argument.
     * @param scope contextual scope to return.
     * @return the bindings in the engine for the scope indicated by the parameter
     */
    public Bindings getBindings(final int scope) {
        return context.getBindings(scope);
    }

    /**
     * Implementation required by ScriptEngine parent<br />
     * Sets the bindings for the indicated scope
     * @param bindings a set of bindings to assign to the engine
     * @param scope the scope that the passed bindings should be assigned to
     */
    public void setBindings(final Bindings bindings, final int scope) {
        context.setBindings(bindings, scope);
    }

    /**
     * Implementation required by ScriptEngine parent<br />
     * Insert a key and value into the engine's bindings (scope: engine)
     * @param key the key of the pair
     * @param value the value of the pair
     */
    public void put(final String key, final Object value) {
        getBindings(ScriptContext.ENGINE_SCOPE).put(key, value);
    }

    /**
     * Implementation required by ScriptEngine parent<br />
     * Get a value from the engine's bindings using a key (scope: engine)
     * @param key the key of the pair
     * @return the value of the pair
     */
    public Object get(final String key) {
        return getBindings(ScriptContext.ENGINE_SCOPE).get(key);
    }

    /**
     * Implementation required by ScriptEngine parent<br />
     * Passes the Reader argument, as well as the engine's context to a lower evaluation function.<br />
     * Prefers FileReader or BufferedReader wrapping FileReader as argument.
     * @param reader a Reader to AppleScript source or compiled AppleScript
     * @return an Object corresponding to the return value of the script
     * @see com.apple.applescript.AppleScriptEngine#eval(Reader, ScriptContext)
     */
    public Object eval(final Reader reader) throws ScriptException {
        return eval(reader, getContext());
    }

    /**
     * Implementation required by ScriptEngine parent<br />
     * Uses the passed bindings as the context for executing the passed script.
     * @param reader a stream to AppleScript source or compiled AppleScript
     * @param bindings a Bindings object representing the contexts to execute inside
     * @return the return value of the script
     * @see com.apple.applescript.AppleScriptEngine#eval(Reader, ScriptContext)
     */
    public Object eval(final Reader reader, final Bindings bindings) throws ScriptException {
        final Bindings tmp = getContext().getBindings(ScriptContext.ENGINE_SCOPE);
        getContext().setBindings(bindings, ScriptContext.ENGINE_SCOPE);
        final Object retval = eval(reader);
        getContext().setBindings(tmp, ScriptContext.ENGINE_SCOPE);
        return retval;
    }

    /**
     * Implementation required by ScriptEngine parent<br />
     * This function can execute either AppleScript source or compiled AppleScript and functions by writing the
     * contents of the Reader to a temporary file and then executing it with the engine's context.
     * @param reader
     * @param scriptContext
     * @return an Object corresponding to the return value of the script
     */
    public Object eval(final Reader reader, final ScriptContext context) throws ScriptException {
        checkSecurity();

        // write our passed reader to a temporary file
        File tmpfile;
        FileWriter tmpwrite;
        try {
            tmpfile = Files.createTempFile("AppleScriptEngine.", ".scpt").toFile();
            tmpwrite = new FileWriter(tmpfile);

            // read in our input and write directly to tmpfile
            /* TODO -- this may or may not be avoidable for certain Readers,
             * if a filename can be grabbed, it would be faster to get that and
             * use the underlying file than writing a temp file.
             */
            int data;
            while ((data = reader.read()) != -1) {
                tmpwrite.write(data);
            }
            tmpwrite.close();

            // set up our context business
            final long contextptr = scriptContextToNSDictionary(context);
            try {
                final long retCtx = evalScriptFromURL("file://" + tmpfile.getCanonicalPath(), contextptr);
                Object retVal = (retCtx == 0) ? null : createObjectFrom(retCtx);
                disposeContext(retCtx);
                return retVal;
            } finally {
                disposeContext(contextptr);
                tmpfile.delete();
            }
        } catch (final IOException e) {
            throw new ScriptException(e);
        }
    }

    /**
     * Implementation required by ScriptEngine parent<br />
     * Evaluate an AppleScript script passed as a source string. Using the engine's built in context.
     * @param script the string to execute.
     * @return an Object representing the return value of the script
     * @see com.apple.applescript.AppleScriptEngine#eval(String, ScriptContext)
     */
    public Object eval(final String script) throws ScriptException {
        return eval(script, getContext());
    }

    /**
     * Implementation required by ScriptEngine parent<br />
     * Evaluate an AppleScript script passed as a source string with a custom ScriptContext.
     * @param script the AppleScript source to compile and execute.
     * @param scriptContext the context to execute the script under
     * @see com.apple.applescript.AppleScriptEngine#eval(String, ScriptContext)
     */
    public Object eval(final String script, final Bindings bindings) throws ScriptException {
        final Bindings tmp = getContext().getBindings(ScriptContext.ENGINE_SCOPE);
        getContext().setBindings(bindings, ScriptContext.ENGINE_SCOPE);

        final Object retval = eval(script);
        getContext().setBindings(tmp, ScriptContext.ENGINE_SCOPE);

        return retval;
    }

    /**
     * Implementation required by ScriptEngine parent
     * @param script
     * @param scriptContext
     */
    public Object eval(final String script, final ScriptContext context) throws ScriptException {
        checkSecurity();
        final long ctxPtr = scriptContextToNSDictionary(context);
        try {
            final long retCtx = evalScript(script, ctxPtr);
            Object retVal = (retCtx == 0) ? null : createObjectFrom(retCtx);
            disposeContext(retCtx);
            return retVal;
        } finally {
            disposeContext(ctxPtr);
        }
    }

    /**
     * Converts a ScriptContext into an NSDictionary
     * @param context ScriptContext for the engine
     * @return a pointer to an NSDictionary
     */
    private long scriptContextToNSDictionary(final ScriptContext context) throws ScriptException {
        final Map<String, Object> contextAsMap = new HashMap<String, Object>();
        for (final Entry<String, Object> e : context.getBindings(ScriptContext.ENGINE_SCOPE).entrySet()) {
            contextAsMap.put(e.getKey().replaceAll("\\.", "_"), e.getValue());
        }
        return createContextFrom(contextAsMap);
    }
}
