/**
 * 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 org.apache.pig.scripting.js;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.pig.FuncSpec;
import org.apache.pig.impl.PigContext;
import org.apache.pig.impl.util.UDFContext;
import org.apache.pig.scripting.ScriptEngine;
import org.apache.pig.tools.pigstats.PigStats;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.EcmaError;
import org.mozilla.javascript.Function;
import org.mozilla.javascript.ImporterTopLevel;
import org.mozilla.javascript.NativeFunction;
import org.mozilla.javascript.Scriptable;

/**
 * {@link ScriptEngine} implementation for JavaScript
 */
public class JsScriptEngine extends ScriptEngine {
    private static final Log LOG = LogFactory.getLog(JsScriptEngine.class);

    /** holds the instance created on client side to parse the js */
    private static JsScriptEngine clientInstance;

    /** holds the singleton for UDFs */
    private static final class Holder {
        static JsScriptEngine instance;
        static {
            if (clientInstance!=null) { 
                /** on client side UDFs re-use the same instance */ 
                instance = clientInstance;
            } else {
                /** on the hadoop slave a new instance is created using the UDFContext for initialization */
                instance = new JsScriptEngine();
                String scriptPath = (String) UDFContext.getUDFContext().getUDFProperties(JsFunction.class).get(JsScriptEngine.class.getName()+".scriptFile");
                instance.scriptPath = scriptPath;
                if (scriptPath == null) {
                    throw new IllegalStateException("could not get script path from UDFContext");
                }
                InputStream is = getScriptAsStream(scriptPath);
                try {
                    instance.load(scriptPath, is);
                } finally {
                    try {
                        is.close();
                    } catch (IOException e) {
                        LOG.warn("Could not close stream for file "+scriptPath, e);
                    }
                }

            }
        }
    }

    public static JsScriptEngine getInstance() {
        JsScriptEngine instance = Holder.instance;
        /** add script path information in the UDFContext */
        UDFContext.getUDFContext().getUDFProperties(JsFunction.class).put(JsScriptEngine.class.getName()+".scriptFile", instance.scriptPath);        
        return instance;
    }

    private ThreadLocal<Context> cx = new ThreadLocal<Context>();
    private Scriptable scope;
    private String scriptPath;

    /** print functions to help with debugging */
    private static final String printSource =
        "function print(str) {                \n" +
        "    if (typeof(str) == 'undefined') {         \n" +
        "        str = 'undefined';                    \n" +
        "    } else if (str == null) {                 \n" +
        "        str = 'null';                         \n" +
        "    }\n" +
        "    java.lang.System.out.print(String(str));\n" +
        "}\n" +
        "function println(str) {                       \n" +
        "    if (typeof(str) == 'undefined') {         \n" +
        "        str = 'undefined';                    \n" +
        "    } else if (str == null) {                 \n" +
        "        str = 'null';                         \n" +
        "    }\n" +
        "    java.lang.System.out.println(String(str));\n" +
        "}";

    /**
     * @return the javascript context for the current thread
     */
    private Context getContext() {
        Context context = cx.get();
        if (context == null) {
            context = Context.enter();
            cx.set(context);
        }
        return context;
    }

    /**
     * evaluate a javascript String
     * @param name the name of the script (for error messages)
     * @param script the content of the script
     * @return the result
     */
    public Object jsEval(String name, String script) {
        try {
            return getContext().evaluateString(scope, script, name, 1, null);
        } catch (EcmaError e) {
            throw new RuntimeException("can't evaluate "+name+": "+script,e);
        }
    }

    /**
     * evaluate javascript from a reader
     * @param name the name of the script (for error messages)
     * @param scriptReader the content of the script
     * @return the result
     */
    public Object jsEval(String name, Reader scriptReader) {
        try {
            return getContext().evaluateReader(scope, scriptReader, name, 1, null);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * put a value in the current scope
     * @param name the name of the variable
     * @param value its value
     */
    public void jsPut(String name, Object value) {
        scope.put(name, scope, value);
    }

    /**
     * call a javascript function
     * @param functionName the name of the function
     * @param passedParams the parameters to pass
     * @return the result of the function
     */
    public Object jsCall(String functionName, Object[] passedParams) {
        Function f = (Function)scope.get(functionName, scope);
        Object result = f.call(getContext(), scope, scope, passedParams);
        return result;
    }

    Scriptable getScope() {
        return scope;
    }

    /**
     * creates a new JavaScript object
     * @return an empty object
     */
    public Scriptable jsNewObject() {
        return getContext().newObject(scope);
    }

    /**
     * creates a new javascript array
     * @param size the size of the array
     * @return an empty array of the given size
     */
    public Scriptable jsNewArray(long size) {
        return getContext().newArray(scope, (int)size);
    }

    public JsScriptEngine() {
        Context context = getContext();
        scope = new ImporterTopLevel(context); // so that we can use importPackage()
        context.evaluateString(scope, printSource, "print", 1, null); // so that we can print on std out

    }

    protected Object eval(String expr) {
        return jsEval(expr, "new String("+expr+")");
    }

    protected void load(String name, InputStream script) {
        jsEval(name, new InputStreamReader(script));
    }

    @Override
    protected Map<String, List<PigStats>> main(PigContext pigContext,
            String scriptFile) throws IOException {

        File f = new File(scriptFile);

        if (!f.canRead()) {
            throw new IOException("Can't read file: " + scriptFile);
        }

        registerFunctions(scriptFile, null, pigContext);    

        // run main
        jsEval("main", "main();");

        return getPigStatsMap();
    }

    @Override
    public void registerFunctions(String path, String namespace,
            PigContext pigContext) throws IOException {
        // to enable passing of information to the slave
        this.scriptPath = path;
        JsScriptEngine.clientInstance = this;

        pigContext.addScriptJar(getJarPath(Context.class));
        namespace = (namespace == null) ? "" : namespace + NAMESPACE_SEPARATOR;
        FileInputStream fis = new FileInputStream(path);
        try {
            load(path, fis);
        } finally {
            fis.close();
        }
        Object[] ids = scope.getIds();
        for (Object id : ids) {
            if (id instanceof String) {
                String name = (String) id;
                Object value = scope.get(name, scope);
                if (value instanceof Function
                        && !name.equals("print") // ignoring the print functions that were added by this class in the initialization
                        && !name.equals("println")) {

                    FuncSpec funcspec = new FuncSpec(JsFunction.class.getCanonicalName() + "('" + name + "')");
                    LOG.info("Register scripting UDF: " + name);
                    pigContext.registerFunction(namespace + name, funcspec);           
                }
            }
        }
        pigContext.addScriptFile(path);

    }


    @Override
    protected Map<String, Object> getParamsFromVariables() throws IOException {
        Map<String, Object> params = new HashMap<String, Object>();
        Object[] ids = scope.getIds();
        for (Object id : ids) {
            if (id instanceof String) {
                String name = (String) id;
                Object value = scope.get(name, scope);
                if (!(value instanceof NativeFunction)) {
                    LOG.debug("Registering parameter "+name+" => "+scope.get(name, scope));
                    params.put(name, eval(name).toString());
                }
            }
        }
        return params;
    }

    @Override
    protected String getScriptingLang() {
        return "javascript";
    }

}
