/*
 *  Licensed to the Apache Software Foundation (ASF) under one
 *  or more contributor license agreements.  See the NOTICE file
 *  distributed with this work for additional information
 *  regarding copyright ownership.  The ASF licenses this file
 *  to you under the Apache License, Version 2.0 (the
 *  "License"); you may not use this file except in compliance
 *  with the License.  You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing,
 *  software distributed under the License is distributed on an
 *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 *  KIND, either express or implied.  See the License for the
 *  specific language governing permissions and limitations
 *  under the License.
 */
package groovy.lang;

import groovy.security.GroovyCodeSourcePermission;
import groovy.ui.GroovyMain;
import org.apache.groovy.plugin.GroovyRunner;
import org.apache.groovy.plugin.GroovyRunnerRegistry;
import org.codehaus.groovy.control.CompilationFailedException;
import org.codehaus.groovy.control.CompilerConfiguration;
import org.codehaus.groovy.runtime.InvokerHelper;
import org.codehaus.groovy.runtime.InvokerInvocationException;

import java.io.File;
import java.io.IOException;
import java.io.Reader;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.net.URI;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

import static org.codehaus.groovy.runtime.InvokerHelper.MAIN_METHOD_NAME;

/**
 * Represents a groovy shell capable of running arbitrary groovy scripts
 */
public class GroovyShell extends GroovyObjectSupport {

    public static final String DEFAULT_CODE_BASE = "/groovy/shell";
    private static final String[] EMPTY_STRING_ARRAY = new String[0];

    private final Binding context;
    private final AtomicInteger counter = new AtomicInteger(0);
    private final CompilerConfiguration config;
    private GroovyClassLoader loader;

    public static void main(String[] args) {
        GroovyMain.main(args);
    }

    public GroovyShell() {
        this(null, new Binding());
    }

    public GroovyShell(Binding binding) {
        this(null, binding);
    }

    public GroovyShell(ClassLoader parent, CompilerConfiguration config) {
        this(parent, new Binding(), config);
    }

    public GroovyShell(CompilerConfiguration config) {
        this(new Binding(), config);
    }

    public GroovyShell(Binding binding, CompilerConfiguration config) {
        this(null, binding, config);
    }

    public GroovyShell(ClassLoader parent, Binding binding) {
        this(parent, binding, CompilerConfiguration.DEFAULT);
    }

    public GroovyShell(ClassLoader parent) {
        this(parent, new Binding(), CompilerConfiguration.DEFAULT);
    }

    public GroovyShell(ClassLoader parent, Binding binding, final CompilerConfiguration config) {
        if (binding == null) {
            throw new IllegalArgumentException("Binding must not be null.");
        }
        if (config == null) {
            throw new IllegalArgumentException("Compiler configuration must not be null.");
        }
        final ClassLoader parentLoader = (parent!=null)?parent:GroovyShell.class.getClassLoader();

        if (parentLoader instanceof GroovyClassLoader
            && ((GroovyClassLoader) parentLoader).hasCompatibleConfiguration(config)) {
          this.loader = (GroovyClassLoader) parentLoader;
        } else {
          this.loader = AccessController.doPrivileged((PrivilegedAction<GroovyClassLoader>) () -> new GroovyClassLoader(parentLoader,config));
        }
        this.context = binding;
        this.config = config;
    }

    public void resetLoadedClasses() {
        loader.clearCache();
    }

    /**
     * Creates a child shell using a new ClassLoader which uses the parent shell's
     * class loader as its parent
     *
     * @param shell is the parent shell used for the variable bindings and the parent class loader
     */
    public GroovyShell(GroovyShell shell) {
        this(shell.loader, shell.context);
    }

    public Binding getContext() {
        return context;
    }

    public GroovyClassLoader getClassLoader() {
        return loader;
    }

    public Object getProperty(String property) {
        Object answer = getVariable(property);
        if (answer == null) {
            answer = super.getProperty(property);
        }
        return answer;
    }

    public void setProperty(String property, Object newValue) {
        setVariable(property, newValue);
        try {
            super.setProperty(property, newValue);
        } catch (GroovyRuntimeException e) {
            // ignore, was probably a dynamic property
        }
    }

    //
    // FIXME: Use List<String> here, current version is not safe
    //

    /**
     * A helper method which runs the given script file with the given command line arguments
     *
     * @param scriptFile the file of the script to run
     * @param list       the command line arguments to pass in
     */
    public Object run(File scriptFile, List list) throws CompilationFailedException, IOException {
        return run(scriptFile, (String[]) list.toArray(EMPTY_STRING_ARRAY));
    }

    /**
     * A helper method which runs the given cl script with the given command line arguments
     *
     * @param scriptText is the text content of the script
     * @param fileName   is the logical file name of the script (which is used to create the class name of the script)
     * @param list       the command line arguments to pass in
     */
    public Object run(String scriptText, String fileName, List list) throws CompilationFailedException {
        return run(scriptText, fileName, (String[]) list.toArray(EMPTY_STRING_ARRAY));
    }

    /**
     * Runs the given script file name with the given command line arguments
     *
     * @param scriptFile the file name of the script to run
     * @param args       the command line arguments to pass in
     */
    public Object run(final File scriptFile, String[] args) throws CompilationFailedException, IOException {
        String scriptName = scriptFile.getName();
        int p = scriptName.lastIndexOf(".");
        if (p++ >= 0) {
            if (scriptName.substring(p).equals("java")) {
                throw new CompilationFailedException(0, null);
            }
        }

        // Get the current context classloader and save it on the stack
        final Thread thread = Thread.currentThread();
        //ClassLoader currentClassLoader = thread.getContextClassLoader();

        class DoSetContext implements PrivilegedAction {
            ClassLoader classLoader;

            public DoSetContext(ClassLoader loader) {
                classLoader = loader;
            }

            public Object run() {
                thread.setContextClassLoader(classLoader);
                return null;
            }
        }

        AccessController.doPrivileged(new DoSetContext(loader));

        // Parse the script, generate the class, and invoke the main method.  This is a little looser than
        // if you are compiling the script because the JVM isn't executing the main method.
        Class scriptClass;
        try {
            scriptClass = AccessController.doPrivileged((PrivilegedExceptionAction<Class>) () -> loader.parseClass(scriptFile));
        } catch (PrivilegedActionException pae) {
            Exception e = pae.getException();
            if (e instanceof CompilationFailedException) {
                throw (CompilationFailedException) e;
            } else if (e instanceof IOException) {
                throw (IOException) e;
            } else {
                throw (RuntimeException) pae.getException();
            }
        }

        return runScriptOrMainOrTestOrRunnable(scriptClass, args);

        // Set the context classloader back to what it was.
        //AccessController.doPrivileged(new DoSetContext(currentClassLoader));
    }

    /**
     * if (theClass is a Script) {
     * run it like a script
     * } else if (theClass has a main method) {
     * run the main method
     * } else if (theClass instanceof GroovyTestCase) {
     * use the test runner to run it
     * } else if (theClass implements Runnable) {
     * if (theClass has a constructor with String[] params)
     * instantiate theClass with this constructor and run
     * else if (theClass has a no-args constructor)
     * instantiate theClass with the no-args constructor and run
     * }
     */
    private Object runScriptOrMainOrTestOrRunnable(Class scriptClass, String[] args) {
        // Always set the "args" property, regardless of what path we take in the code.
        // Bad enough to have side effects but worse if their behavior is wonky.
        context.setProperty("args", args);

        if (scriptClass == null) {
            return null;
        }

        //TODO: This logic mostly duplicates InvokerHelper.createScript.  They should probably be unified.

        if (Script.class.isAssignableFrom(scriptClass)) {
            // treat it just like a script if it is one
            try {
                Script script = InvokerHelper.newScript(scriptClass, context);
                return script.run();
            } catch (InstantiationException | InvocationTargetException | IllegalAccessException e) {
                // ignore instantiation errors,, try to do main
            }
        }
        try {
            // let's find a main method
            scriptClass.getMethod(MAIN_METHOD_NAME, String[].class);
            // if that main method exist, invoke it
            return InvokerHelper.invokeMethod(scriptClass, MAIN_METHOD_NAME, new Object[]{args});
        } catch (NoSuchMethodException e) {
            // if it implements Runnable, try to instantiate it
            if (Runnable.class.isAssignableFrom(scriptClass)) {
                return runRunnable(scriptClass, args);
            }
            GroovyRunnerRegistry runnerRegistry = GroovyRunnerRegistry.getInstance();
            for (GroovyRunner runner : runnerRegistry) {
                if (runner.canRun(scriptClass, this.loader)) {
                    return runner.run(scriptClass, this.loader);
                }
            }
            StringBuilder message = new StringBuilder("This script or class could not be run.\n" +
                    "It should either:\n" +
                    "- have a main method,\n" +
                    "- be a JUnit test or extend GroovyTestCase,\n" +
                    "- implement the Runnable interface,\n" +
                    "- or be compatible with a registered script runner. Known runners:\n");
            if (runnerRegistry.isEmpty()) {
                message.append("  * <none>");
            } else {
                for (String key : runnerRegistry.keySet()) {
                    message.append("  * ").append(key).append("\n");
                }
            }
            throw new GroovyRuntimeException(message.toString());
        }
    }

    private static Object runRunnable(Class scriptClass, String[] args) {
        Constructor constructor = null;
        Runnable runnable = null;
        Throwable reason = null;

        try {
            // first, fetch the constructor taking String[] as parameter
            constructor = scriptClass.getConstructor(String[].class);
            try {
                // instantiate a runnable and run it
                runnable = (Runnable) constructor.newInstance(new Object[]{args});
            } catch (Throwable t) {
                reason = t;
            }
        } catch (NoSuchMethodException e1) {
            try {
                // otherwise, find the default constructor
                constructor = scriptClass.getConstructor();
                try {
                    // instantiate a runnable and run it
                    runnable = (Runnable) constructor.newInstance();
                } catch (InvocationTargetException ite) {
                    throw new InvokerInvocationException(ite.getTargetException());
                } catch (Throwable t) {
                    reason = t;
                }
            } catch (NoSuchMethodException nsme) {
                reason = nsme;
            }
        }
        if (constructor != null && runnable != null) {
            runnable.run();
        } else {
            throw new GroovyRuntimeException("This script or class was runnable but could not be run. ", reason);
        }
        return null;
    }

    /**
     * Runs the given script text with command line arguments
     *
     * @param scriptText is the text content of the script
     * @param fileName   is the logical file name of the script (which is used to create the class name of the script)
     * @param args       the command line arguments to pass in
     */
    public Object run(final String scriptText, final String fileName, String[] args) throws CompilationFailedException {
        GroovyCodeSource gcs = AccessController.doPrivileged((PrivilegedAction<GroovyCodeSource>) () -> new GroovyCodeSource(scriptText, fileName, DEFAULT_CODE_BASE));
        return run(gcs, args);
    }

    /**
     * Runs the given script source with command line arguments
     *
     * @param source    is the source content of the script
     * @param args      the command line arguments to pass in
     */
    public Object run(GroovyCodeSource source, List args) throws CompilationFailedException {
        return run(source, ((String[]) args.toArray(EMPTY_STRING_ARRAY)));
    }

    /**
     * Runs the given script source with command line arguments
     *
     * @param source    is the source content of the script
     * @param args      the command line arguments to pass in
     */
    public Object run(GroovyCodeSource source, String[] args) throws CompilationFailedException {
        Class scriptClass = parseClass(source);
        return runScriptOrMainOrTestOrRunnable(scriptClass, args);
    }

    /**
     * Runs the given script source with command line arguments
     *
     * @param source    is the source content of the script
     * @param args      the command line arguments to pass in
     */
    public Object run(URI source, List args) throws CompilationFailedException, IOException {
        return run(new GroovyCodeSource(source), ((String[]) args.toArray(EMPTY_STRING_ARRAY)));
    }

    /**
     * Runs the given script source with command line arguments
     *
     * @param source    is the source content of the script
     * @param args      the command line arguments to pass in
     */
    public Object run(URI source, String[] args) throws CompilationFailedException, IOException {
        return run(new GroovyCodeSource(source), args);
    }

    /**
     * Runs the given script with command line arguments
     *
     * @param in       the stream reading the script
     * @param fileName is the logical file name of the script (which is used to create the class name of the script)
     * @param list     the command line arguments to pass in
     */
    public Object run(final Reader in, final String fileName, List list) throws CompilationFailedException {
        return run(in, fileName, (String[]) list.toArray(EMPTY_STRING_ARRAY));
    }

    /**
     * Runs the given script with command line arguments
     *
     * @param in       the stream reading the script
     * @param fileName is the logical file name of the script (which is used to create the class name of the script)
     * @param args     the command line arguments to pass in
     */
    public Object run(final Reader in, final String fileName, String[] args) throws CompilationFailedException {
        GroovyCodeSource gcs = AccessController.doPrivileged((PrivilegedAction<GroovyCodeSource>) () -> new GroovyCodeSource(in, fileName, DEFAULT_CODE_BASE));
        Class scriptClass = parseClass(gcs);
        return runScriptOrMainOrTestOrRunnable(scriptClass, args);
    }

    public Object getVariable(String name) {
        return context.getVariables().get(name);
    }

    public void setVariable(String name, Object value) {
        context.setVariable(name, value);
    }

    public void removeVariable(String name) {
        context.removeVariable(name);
    }

    /**
     * Evaluates some script against the current Binding and returns the result
     *
     * @param codeSource
     * @throws CompilationFailedException
     */
    public Object evaluate(GroovyCodeSource codeSource) throws CompilationFailedException {
        Script script = parse(codeSource);
        return script.run();
    }

    /**
     * Evaluates some script against the current Binding and returns the result
     *
     * @param scriptText the text of the script
     */
    public Object evaluate(final String scriptText) throws CompilationFailedException {
        return evaluate(scriptText, generateScriptName(), DEFAULT_CODE_BASE);
    }

    /**
     * Evaluates some script against the current Binding and returns the result
     *
     * @param scriptText the text of the script
     * @param fileName   is the logical file name of the script (which is used to create the class name of the script)
     */
    public Object evaluate(String scriptText, String fileName) throws CompilationFailedException {
        return evaluate(scriptText, fileName, DEFAULT_CODE_BASE);
    }

    /**
     * Evaluates some script against the current Binding and returns the result.
     * The .class file created from the script is given the supplied codeBase
     */
    public Object evaluate(final String scriptText, final String fileName, final String codeBase) throws CompilationFailedException {
        SecurityManager sm = System.getSecurityManager();
        if (sm != null) {
            sm.checkPermission(new GroovyCodeSourcePermission(codeBase));
        }

        GroovyCodeSource gcs = AccessController.doPrivileged((PrivilegedAction<GroovyCodeSource>) () -> new GroovyCodeSource(scriptText, fileName, codeBase));

        return evaluate(gcs);
    }

    /**
     * Evaluates some script against the current Binding and returns the result
     *
     * @param file is the file of the script (which is used to create the class name of the script)
     */
    public Object evaluate(File file) throws CompilationFailedException, IOException {
        return evaluate(new GroovyCodeSource(file, config.getSourceEncoding()));
    }

    /**
     * Evaluates some script against the current Binding and returns the result
     *
     * @param uri is the URI of the script (which is used to create the class name of the script)
     */
    public Object evaluate(URI uri) throws CompilationFailedException, IOException {
        return evaluate(new GroovyCodeSource(uri));
    }

    /**
     * Evaluates some script against the current Binding and returns the result
     *
     * @param in the stream reading the script
     */
    public Object evaluate(Reader in) throws CompilationFailedException {
        return evaluate(in, generateScriptName());
    }

    /**
     * Evaluates some script against the current Binding and returns the result
     *
     * @param in       the stream reading the script
     * @param fileName is the logical file name of the script (which is used to create the class name of the script)
     */
    public Object evaluate(Reader in, String fileName) throws CompilationFailedException {
        Script script = null;
        try {
            script = parse(in, fileName);
            return script.run();
        } finally {
            if (script != null) {
                InvokerHelper.removeClass(script.getClass());
            }
        }
    }


    /**
     * Parses the given script and returns it ready to be run
     *
     * @param reader    the stream reading the script
     * @param fileName  is the logical file name of the script (which is used to create the class name of the script)
     * @return the parsed script which is ready to be run via {@link Script#run()}
     */
    public Script parse(final Reader reader, final String fileName) throws CompilationFailedException {
        return parse(new GroovyCodeSource(reader, fileName, DEFAULT_CODE_BASE));
    }

    /**
     * Parses the groovy code contained in codeSource and returns a java class.
     */
    private Class parseClass(final GroovyCodeSource codeSource) throws CompilationFailedException {
        // Don't cache scripts
        return loader.parseClass(codeSource, false);
    }

    /**
     * Parses the given script and returns it ready to be run.  When running in a secure environment
     * (-Djava.security.manager) codeSource.getCodeSource() determines what policy grants should be
     * given to the script.
     *
     * @param codeSource
     * @return ready to run script
     */
    public Script parse(final GroovyCodeSource codeSource) throws CompilationFailedException {
        return InvokerHelper.createScript(parseClass(codeSource), context);
    }

    /**
     * Parses the given script and returns it ready to be run
     *
     * @param file is the file of the script (which is used to create the class name of the script)
     */
    public Script parse(File file) throws CompilationFailedException, IOException {
        return parse(new GroovyCodeSource(file, config.getSourceEncoding()));
    }

    /**
     * Parses the given script and returns it ready to be run
     *
     * @param uri is the URI of the script (which is used to create the class name of the script)
     */
    public Script parse(URI uri) throws CompilationFailedException, IOException {
        return parse(new GroovyCodeSource(uri));
    }

    /**
     * Parses the given script and returns it ready to be run
     *
     * @param scriptText the text of the script
     */
    public Script parse(String scriptText) throws CompilationFailedException {
        return parse(scriptText, generateScriptName());
    }

    public Script parse(final String scriptText, final String fileName) throws CompilationFailedException {
        GroovyCodeSource gcs = AccessController.doPrivileged((PrivilegedAction<GroovyCodeSource>) () -> new GroovyCodeSource(scriptText, fileName, DEFAULT_CODE_BASE));
        return parse(gcs);
    }

    /**
     * Parses the given script and returns it ready to be run
     *
     * @param in the stream reading the script
     */
    public Script parse(Reader in) throws CompilationFailedException {
        return parse(in, generateScriptName());
    }

    protected String generateScriptName() {
        return "Script" + counter.incrementAndGet() + ".groovy";
    }
}
