/*
 * Copyright (c) 2010, 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 jdk.nashorn.api.scripting;

import static jdk.nashorn.internal.runtime.Source.sourceFor;

import java.io.IOException;
import java.io.Reader;
import java.lang.invoke.MethodHandles;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.Permissions;
import java.security.PrivilegedAction;
import java.security.ProtectionDomain;
import java.text.MessageFormat;
import java.util.Locale;
import java.util.Objects;
import java.util.ResourceBundle;
import javax.script.AbstractScriptEngine;
import javax.script.Bindings;
import javax.script.Compilable;
import javax.script.CompiledScript;
import javax.script.Invocable;
import javax.script.ScriptContext;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineFactory;
import javax.script.ScriptException;
import javax.script.SimpleBindings;
import jdk.nashorn.internal.objects.Global;
import jdk.nashorn.internal.runtime.Context;
import jdk.nashorn.internal.runtime.ErrorManager;
import jdk.nashorn.internal.runtime.ScriptFunction;
import jdk.nashorn.internal.runtime.ScriptObject;
import jdk.nashorn.internal.runtime.ScriptRuntime;
import jdk.nashorn.internal.runtime.Source;
import jdk.nashorn.internal.runtime.linker.JavaAdapterFactory;
import jdk.nashorn.internal.runtime.options.Options;

/**
 * JSR-223 compliant script engine for Nashorn. Instances are not created directly, but rather returned through
 * {@link NashornScriptEngineFactory#getScriptEngine()}. Note that this engine implements the {@link Compilable} and
 * {@link Invocable} interfaces, allowing for efficient precompilation and repeated execution of scripts.
 * @see NashornScriptEngineFactory
 *
 * @since 1.8u40
 */
@jdk.Exported
public final class NashornScriptEngine extends AbstractScriptEngine implements Compilable, Invocable {
    /**
     * Key used to associate Nashorn global object mirror with arbitrary Bindings instance.
     */
    public static final String NASHORN_GLOBAL = "nashorn.global";

    // commonly used access control context objects
    private static AccessControlContext createPermAccCtxt(final String permName) {
        final Permissions perms = new Permissions();
        perms.add(new RuntimePermission(permName));
        return new AccessControlContext(new ProtectionDomain[] { new ProtectionDomain(null, perms) });
    }

    private static final AccessControlContext CREATE_CONTEXT_ACC_CTXT = createPermAccCtxt(Context.NASHORN_CREATE_CONTEXT);
    private static final AccessControlContext CREATE_GLOBAL_ACC_CTXT  = createPermAccCtxt(Context.NASHORN_CREATE_GLOBAL);

    // the factory that created this engine
    private final ScriptEngineFactory factory;
    // underlying nashorn Context - 1:1 with engine instance
    private final Context             nashornContext;
    // do we want to share single Nashorn global instance across ENGINE_SCOPEs?
    private final boolean             _global_per_engine;
    // This is the initial default Nashorn global object.
    // This is used as "shared" global if above option is true.
    private final Global              global;

    // Nashorn script engine error message management
    private static final String MESSAGES_RESOURCE = "jdk.nashorn.api.scripting.resources.Messages";

    private static final ResourceBundle MESSAGES_BUNDLE;
    static {
        MESSAGES_BUNDLE = ResourceBundle.getBundle(MESSAGES_RESOURCE, Locale.getDefault());
    }

    // helper to get Nashorn script engine error message
    private static String getMessage(final String msgId, final String... args) {
        try {
            return new MessageFormat(MESSAGES_BUNDLE.getString(msgId)).format(args);
        } catch (final java.util.MissingResourceException e) {
            throw new RuntimeException("no message resource found for message id: "+ msgId);
        }
    }

    NashornScriptEngine(final NashornScriptEngineFactory factory, final String[] args, final ClassLoader appLoader, final ClassFilter classFilter) {
        assert args != null : "null argument array";
        this.factory = factory;
        final Options options = new Options("nashorn");
        options.process(args);

        // throw ParseException on first error from script
        final ErrorManager errMgr = new Context.ThrowErrorManager();
        // create new Nashorn Context
        this.nashornContext = AccessController.doPrivileged(new PrivilegedAction<Context>() {
            @Override
            public Context run() {
                try {
                    return new Context(options, errMgr, appLoader, classFilter);
                } catch (final RuntimeException e) {
                    if (Context.DEBUG) {
                        e.printStackTrace();
                    }
                    throw e;
                }
            }
        }, CREATE_CONTEXT_ACC_CTXT);

        // cache this option that is used often
        this._global_per_engine = nashornContext.getEnv()._global_per_engine;

        // create new global object
        this.global = createNashornGlobal();
        // set the default ENGINE_SCOPE object for the default context
        context.setBindings(new ScriptObjectMirror(global, global), ScriptContext.ENGINE_SCOPE);
    }

    @Override
    public Object eval(final Reader reader, final ScriptContext ctxt) throws ScriptException {
        return evalImpl(makeSource(reader, ctxt), ctxt);
    }

    @Override
    public Object eval(final String script, final ScriptContext ctxt) throws ScriptException {
        return evalImpl(makeSource(script, ctxt), ctxt);
    }

    @Override
    public ScriptEngineFactory getFactory() {
        return factory;
    }

    @Override
    public Bindings createBindings() {
        if (_global_per_engine) {
            // just create normal SimpleBindings.
            // We use same 'global' for all Bindings.
            return new SimpleBindings();
        }
        return createGlobalMirror();
    }

    // Compilable methods

    @Override
    public CompiledScript compile(final Reader reader) throws ScriptException {
        return asCompiledScript(makeSource(reader, context));
    }

    @Override
    public CompiledScript compile(final String str) throws ScriptException {
        return asCompiledScript(makeSource(str, context));
    }

    // Invocable methods

    @Override
    public Object invokeFunction(final String name, final Object... args)
            throws ScriptException, NoSuchMethodException {
        return invokeImpl(null, name, args);
    }

    @Override
    public Object invokeMethod(final Object thiz, final String name, final Object... args)
            throws ScriptException, NoSuchMethodException {
        if (thiz == null) {
            throw new IllegalArgumentException(getMessage("thiz.cannot.be.null"));
        }
        return invokeImpl(thiz, name, args);
    }

    @Override
    public <T> T getInterface(final Class<T> clazz) {
        return getInterfaceInner(null, clazz);
    }

    @Override
    public <T> T getInterface(final Object thiz, final Class<T> clazz) {
        if (thiz == null) {
            throw new IllegalArgumentException(getMessage("thiz.cannot.be.null"));
        }
        return getInterfaceInner(thiz, clazz);
    }

    // Implementation only below this point

    private static Source makeSource(final Reader reader, final ScriptContext ctxt) throws ScriptException {
        try {
            return sourceFor(getScriptName(ctxt), reader);
        } catch (final IOException e) {
            throw new ScriptException(e);
        }
    }

    private static Source makeSource(final String src, final ScriptContext ctxt) {
        return sourceFor(getScriptName(ctxt), src);
    }

    private static String getScriptName(final ScriptContext ctxt) {
        final Object val = ctxt.getAttribute(ScriptEngine.FILENAME);
        return (val != null) ? val.toString() : "<eval>";
    }

    private <T> T getInterfaceInner(final Object thiz, final Class<T> clazz) {
        assert !(thiz instanceof ScriptObject) : "raw ScriptObject not expected here";

        if (clazz == null || !clazz.isInterface()) {
            throw new IllegalArgumentException(getMessage("interface.class.expected"));
        }

        // perform security access check as early as possible
        final SecurityManager sm = System.getSecurityManager();
        if (sm != null) {
            if (! Modifier.isPublic(clazz.getModifiers())) {
                throw new SecurityException(getMessage("implementing.non.public.interface", clazz.getName()));
            }
            Context.checkPackageAccess(clazz);
        }

        ScriptObject realSelf = null;
        Global realGlobal = null;
        if(thiz == null) {
            // making interface out of global functions
            realSelf = realGlobal = getNashornGlobalFrom(context);
        } else if (thiz instanceof ScriptObjectMirror) {
            final ScriptObjectMirror mirror = (ScriptObjectMirror)thiz;
            realSelf = mirror.getScriptObject();
            realGlobal = mirror.getHomeGlobal();
            if (! isOfContext(realGlobal, nashornContext)) {
                throw new IllegalArgumentException(getMessage("script.object.from.another.engine"));
            }
        }

        if (realSelf == null) {
            throw new IllegalArgumentException(getMessage("interface.on.non.script.object"));
        }

        try {
            final Global oldGlobal = Context.getGlobal();
            final boolean globalChanged = (oldGlobal != realGlobal);
            try {
                if (globalChanged) {
                    Context.setGlobal(realGlobal);
                }

                if (! isInterfaceImplemented(clazz, realSelf)) {
                    return null;
                }
                return clazz.cast(JavaAdapterFactory.getConstructor(realSelf.getClass(), clazz,
                        MethodHandles.publicLookup()).invoke(realSelf));
            } finally {
                if (globalChanged) {
                    Context.setGlobal(oldGlobal);
                }
            }
        } catch(final RuntimeException|Error e) {
            throw e;
        } catch(final Throwable t) {
            throw new RuntimeException(t);
        }
    }

    // Retrieve nashorn Global object for a given ScriptContext object
    private Global getNashornGlobalFrom(final ScriptContext ctxt) {
        if (_global_per_engine) {
            // shared single global object for all ENGINE_SCOPE Bindings
            return global;
        }

        final Bindings bindings = ctxt.getBindings(ScriptContext.ENGINE_SCOPE);
        // is this Nashorn's own Bindings implementation?
        if (bindings instanceof ScriptObjectMirror) {
            final Global glob = globalFromMirror((ScriptObjectMirror)bindings);
            if (glob != null) {
                return glob;
            }
        }

        // Arbitrary user Bindings implementation. Look for NASHORN_GLOBAL in it!
        final Object scope = bindings.get(NASHORN_GLOBAL);
        if (scope instanceof ScriptObjectMirror) {
            final Global glob = globalFromMirror((ScriptObjectMirror)scope);
            if (glob != null) {
                return glob;
            }
        }

        // We didn't find associated nashorn global mirror in the Bindings given!
        // Create new global instance mirror and associate with the Bindings.
        final ScriptObjectMirror mirror = createGlobalMirror();
        bindings.put(NASHORN_GLOBAL, mirror);
        // Since we created this global explicitly for the non-default script context we set the
        // current script context in global permanently so that invokes work as expected. See JDK-8150219
        mirror.getHomeGlobal().setInitScriptContext(ctxt);
        return mirror.getHomeGlobal();
    }

    // Retrieve nashorn Global object from a given ScriptObjectMirror
    private Global globalFromMirror(final ScriptObjectMirror mirror) {
        final ScriptObject sobj = mirror.getScriptObject();
        if (sobj instanceof Global && isOfContext((Global)sobj, nashornContext)) {
            return (Global)sobj;
        }

        return null;
    }

    // Create a new ScriptObjectMirror wrapping a newly created Nashorn Global object
    private ScriptObjectMirror createGlobalMirror() {
        final Global newGlobal = createNashornGlobal();
        return new ScriptObjectMirror(newGlobal, newGlobal);
    }

    // Create a new Nashorn Global object
    private Global createNashornGlobal() {
        final Global newGlobal = AccessController.doPrivileged(new PrivilegedAction<Global>() {
            @Override
            public Global run() {
                try {
                    return nashornContext.newGlobal();
                } catch (final RuntimeException e) {
                    if (Context.DEBUG) {
                        e.printStackTrace();
                    }
                    throw e;
                }
            }
        }, CREATE_GLOBAL_ACC_CTXT);

        nashornContext.initGlobal(newGlobal, this);

        return newGlobal;
    }

    private Object invokeImpl(final Object selfObject, final String name, final Object... args) throws ScriptException, NoSuchMethodException {
        Objects.requireNonNull(name);
        assert !(selfObject instanceof ScriptObject) : "raw ScriptObject not expected here";

        Global invokeGlobal = null;
        ScriptObjectMirror selfMirror = null;
        if (selfObject instanceof ScriptObjectMirror) {
            selfMirror = (ScriptObjectMirror)selfObject;
            if (! isOfContext(selfMirror.getHomeGlobal(), nashornContext)) {
                throw new IllegalArgumentException(getMessage("script.object.from.another.engine"));
            }
            invokeGlobal = selfMirror.getHomeGlobal();
        } else if (selfObject == null) {
            // selfObject is null => global function call
            final Global ctxtGlobal = getNashornGlobalFrom(context);
            invokeGlobal = ctxtGlobal;
            selfMirror = (ScriptObjectMirror)ScriptObjectMirror.wrap(ctxtGlobal, ctxtGlobal);
        }

        if (selfMirror != null) {
            try {
                return ScriptObjectMirror.translateUndefined(selfMirror.callMember(name, args));
            } catch (final Exception e) {
                final Throwable cause = e.getCause();
                if (cause instanceof NoSuchMethodException) {
                    throw (NoSuchMethodException)cause;
                }
                throwAsScriptException(e, invokeGlobal);
                throw new AssertionError("should not reach here");
            }
        }

        // Non-script object passed as selfObject
        throw new IllegalArgumentException(getMessage("interface.on.non.script.object"));
    }

    private Object evalImpl(final Source src, final ScriptContext ctxt) throws ScriptException {
        return evalImpl(compileImpl(src, ctxt), ctxt);
    }

    private Object evalImpl(final ScriptFunction script, final ScriptContext ctxt) throws ScriptException {
        return evalImpl(script, ctxt, getNashornGlobalFrom(ctxt));
    }

    private Object evalImpl(final Context.MultiGlobalCompiledScript mgcs, final ScriptContext ctxt, final Global ctxtGlobal) throws ScriptException {
        final Global oldGlobal = Context.getGlobal();
        final boolean globalChanged = (oldGlobal != ctxtGlobal);
        try {
            if (globalChanged) {
                Context.setGlobal(ctxtGlobal);
            }

            final ScriptFunction script = mgcs.getFunction(ctxtGlobal);
            final ScriptContext oldCtxt = ctxtGlobal.getScriptContext();
            ctxtGlobal.setScriptContext(ctxt);
            try {
                return ScriptObjectMirror.translateUndefined(ScriptObjectMirror.wrap(ScriptRuntime.apply(script, ctxtGlobal), ctxtGlobal));
            } finally {
                ctxtGlobal.setScriptContext(oldCtxt);
            }
        } catch (final Exception e) {
            throwAsScriptException(e, ctxtGlobal);
            throw new AssertionError("should not reach here");
        } finally {
            if (globalChanged) {
                Context.setGlobal(oldGlobal);
            }
        }
    }

    private Object evalImpl(final ScriptFunction script, final ScriptContext ctxt, final Global ctxtGlobal) throws ScriptException {
        if (script == null) {
            return null;
        }
        final Global oldGlobal = Context.getGlobal();
        final boolean globalChanged = (oldGlobal != ctxtGlobal);
        try {
            if (globalChanged) {
                Context.setGlobal(ctxtGlobal);
            }

            final ScriptContext oldCtxt = ctxtGlobal.getScriptContext();
            ctxtGlobal.setScriptContext(ctxt);
            try {
                return ScriptObjectMirror.translateUndefined(ScriptObjectMirror.wrap(ScriptRuntime.apply(script, ctxtGlobal), ctxtGlobal));
            } finally {
                ctxtGlobal.setScriptContext(oldCtxt);
            }
        } catch (final Exception e) {
            throwAsScriptException(e, ctxtGlobal);
            throw new AssertionError("should not reach here");
        } finally {
            if (globalChanged) {
                Context.setGlobal(oldGlobal);
            }
        }
    }

    private static void throwAsScriptException(final Exception e, final Global global) throws ScriptException {
        if (e instanceof ScriptException) {
            throw (ScriptException)e;
        } else if (e instanceof NashornException) {
            final NashornException ne = (NashornException)e;
            final ScriptException se = new ScriptException(
                ne.getMessage(), ne.getFileName(),
                ne.getLineNumber(), ne.getColumnNumber());
            ne.initEcmaError(global);
            se.initCause(e);
            throw se;
        } else if (e instanceof RuntimeException) {
            throw (RuntimeException)e;
        } else {
            // wrap any other exception as ScriptException
            throw new ScriptException(e);
        }
    }

    private CompiledScript asCompiledScript(final Source source) throws ScriptException {
        final Context.MultiGlobalCompiledScript mgcs;
        final ScriptFunction func;
        final Global oldGlobal = Context.getGlobal();
        final Global newGlobal = getNashornGlobalFrom(context);
        final boolean globalChanged = (oldGlobal != newGlobal);
        try {
            if (globalChanged) {
                Context.setGlobal(newGlobal);
            }

            mgcs = nashornContext.compileScript(source);
            func = mgcs.getFunction(newGlobal);
        } catch (final Exception e) {
            throwAsScriptException(e, newGlobal);
            throw new AssertionError("should not reach here");
        } finally {
            if (globalChanged) {
                Context.setGlobal(oldGlobal);
            }
        }

        return new CompiledScript() {
            @Override
            public Object eval(final ScriptContext ctxt) throws ScriptException {
                final Global globalObject = getNashornGlobalFrom(ctxt);
                // Are we running the script in the same global in which it was compiled?
                if (func.getScope() == globalObject) {
                    return evalImpl(func, ctxt, globalObject);
                }

                // different global
                return evalImpl(mgcs, ctxt, globalObject);
            }
            @Override
            public ScriptEngine getEngine() {
                return NashornScriptEngine.this;
            }
        };
    }

    private ScriptFunction compileImpl(final Source source, final ScriptContext ctxt) throws ScriptException {
        return compileImpl(source, getNashornGlobalFrom(ctxt));
    }

    private ScriptFunction compileImpl(final Source source, final Global newGlobal) throws ScriptException {
        final Global oldGlobal = Context.getGlobal();
        final boolean globalChanged = (oldGlobal != newGlobal);
        try {
            if (globalChanged) {
                Context.setGlobal(newGlobal);
            }

            return nashornContext.compileScript(source, newGlobal);
        } catch (final Exception e) {
            throwAsScriptException(e, newGlobal);
            throw new AssertionError("should not reach here");
        } finally {
            if (globalChanged) {
                Context.setGlobal(oldGlobal);
            }
        }
    }

    private static boolean isInterfaceImplemented(final Class<?> iface, final ScriptObject sobj) {
        for (final Method method : iface.getMethods()) {
            // ignore methods of java.lang.Object class
            if (method.getDeclaringClass() == Object.class) {
                continue;
            }

            // skip check for default methods - non-abstract, interface methods
            if (! Modifier.isAbstract(method.getModifiers())) {
                continue;
            }

            final Object obj = sobj.get(method.getName());
            if (! (obj instanceof ScriptFunction)) {
                return false;
            }
        }
        return true;
    }

    private static boolean isOfContext(final Global global, final Context context) {
        return global.isOfContext(context);
    }
}
