/*
 * 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.sling.scripting.esx;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.logging.Level;
import javax.jcr.Node;
import javax.jcr.RepositoryException;
import javax.jcr.nodetype.NodeType;
import javax.script.Invocable;
import javax.script.ScriptException;
import javax.script.SimpleBindings;
import jdk.nashorn.api.scripting.JSObject;
import jdk.nashorn.api.scripting.ScriptObjectMirror;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringEscapeUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ResourceUtil;
import org.apache.sling.api.resource.ValueMap;
import org.apache.sling.api.scripting.SlingScriptHelper;
import org.apache.sling.scripting.esx.plugins.ConsoleLog;
import org.apache.sling.scripting.esx.plugins.SimpleResource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Module extends SimpleBindings implements Require {

    public static final String CONTEXT_FIELD_SLING = "sling";
    public static final String CONTEXT_FIELD_PARENT = "parent";
    public static final String CONTEXT_FIELD_ID = "id";
    public static final String CONTEXT_FIELD_MAIN = "main";
    public static final String CONTEXT_FIELD_IS_LOADED = "isLoaded";
    public static final String CONTEXT_FIELD_FILENAME = "filename";
    public static final String CONTEXT_FIELD_RESOURCE = "resource";
    public static final String CONTEXT_FIELD_CHILDREN = "children";
    public static final String CONTEXT_FIELD_MODULE_RESOURCE = "moduleResource";
    public static final String CONTEXT_FIELD_EXPORTS = "exports";
    public static final String CONTEXT_FIELD_CONSOLE = "console";
    public static final String LOADER_TEXT = "text!";
    public static final String LOADER_RESOURCE = "resource!";
    public static final String LOADER_JS = "js!";
    private final Logger log = LoggerFactory.getLogger(getClass());
    private SlingScriptHelper scriptHelper;
    private final EsxScriptEngineFactory factory;
    private ModuleScript moduleScript;
    private boolean isLoaded = false;
    private final List<Module> children = new ArrayList();
    private String loader;

    /**
     *
     * @param factory
     * @param resource
     * @param moduleScript
     * @param id
     * @param parent
     * @param scriptHelper
     * @throws ScriptException
     */
    public Module(EsxScriptEngineFactory factory, Resource resource,
            ModuleScript moduleScript, String id, Module parent,
            SlingScriptHelper scriptHelper,
            String loader) throws ScriptException {
        this.factory = factory;
        this.scriptHelper = scriptHelper;
        this.moduleScript = moduleScript;
        this.loader = loader;

        put(CONTEXT_FIELD_PARENT, parent);
        put(CONTEXT_FIELD_SLING, scriptHelper);

        put(CONTEXT_FIELD_ID, id);
        put(CONTEXT_FIELD_MAIN, (parent == null) ? this : (Module) parent.get(CONTEXT_FIELD_PARENT));
        put(CONTEXT_FIELD_IS_LOADED, isLoaded);
        put(CONTEXT_FIELD_FILENAME, moduleScript.getResource().getPath());
        put(CONTEXT_FIELD_RESOURCE, resource);
        put(CONTEXT_FIELD_CHILDREN, children);
        put(CONTEXT_FIELD_MODULE_RESOURCE, moduleScript.getResource());

        put(CONTEXT_FIELD_EXPORTS, ((JSObject) factory.getNashornEngine().eval("Object")).newObject());

        log.debug("this is the main script: " + (get(CONTEXT_FIELD_MAIN) == this));

        put(CONTEXT_FIELD_CONSOLE, new ConsoleLog((String) get(CONTEXT_FIELD_FILENAME)));
    }

    private ScriptObjectMirror decorateScript(String source)
            throws ScriptException {
        return decorateScript(source, true);
    }

    /**
     *
     * @param source
     * @return
     * @throws ScriptException
     */
    private ScriptObjectMirror decorateScript(String source, boolean es6)
            throws ScriptException {
        String filename = (String) get("filename");
        if (filename.indexOf("node_modules") == -1 && es6) {
            try {
                source = factory.getSandboxService().compileSource(source);
            } catch (ScriptException e) {
                log.error("Could not transpile script", e);
                throw new ScriptException("could not load " + get("filename"));
            }
        }

        // TODO: refactor polyfill for window, global and make require outside the wrapper as function parameter        
        source = "//@sourceURL=" + (String) get("filename") + "\n"
                + "(function (exports, Require, module, __filename,"
                + " __dirname, currentNode, console, properties, sling, simpleResource) { "
                + "var window = (this.window == 'undefined' || this.window == null) ? this : this.window;"
                + "var global = (global == 'undefined') ? this : global;"
                + "function require(id) {  return Require.require(id); } require.resolve = function (id) { return Require.resolve(id, currentNode.resource, 1);  };"
                + source
                + "})";

        // use load + filenane for older JDK versions, @sourceURL is working for latest JDK version
        source = "load( { name : \"" + get("filename") + "\","
                + " script: \""
                + StringEscapeUtils.escapeEcmaScript(source)
                + "\" } )";

        ScriptObjectMirror function = null;
        try {
            function = (ScriptObjectMirror) factory.getNashornEngine().eval(
                    source
            );
            if (function == null) {
                log.error("Function is null !");
            }
        } catch (ScriptException ex) {
            // todo: better handling in future
            throw ex;
        }
        return function;
    }

    /**
     *
     * @return @throws ScriptException
     */
    public Object runScript() throws ScriptException {
        log.debug("run script with id {}", get("id"));
        ScriptObjectMirror function = factory.getModuleCache().get((String) get(CONTEXT_FIELD_FILENAME));

        Resource moduleResource = (Resource) get(CONTEXT_FIELD_MODULE_RESOURCE);
        Resource resource = (Resource) get(CONTEXT_FIELD_RESOURCE);

        if (function == null) {
            if (moduleScript.isJsFile()) {
                function = Module.this.decorateScript(
                        //readScript(moduleResource)//  
                        readScript(moduleResource)
                );
            }

            if (moduleScript.isJsonFile()) {
                String jsonfile = readScript(moduleResource);
                function = decorateScript(
                        "module.exports = " + jsonfile
                , false);
            }

            if (moduleScript.isResourceFile()) {
                Iterator<Resource> resChildren = moduleResource.listChildren();
                ArrayList<Resource> children = new ArrayList<Resource>();
                resChildren.forEachRemaining(children::add);

                put("children", children);

                /*ValueMap map = moduleResource.adaptTo(ValueMap.class);

                 Invocable invocable = (Invocable) factory.getNashornEngine();
                 Object jsonprop = null;
                 try {
                 jsonprop = invocable.invokeMethod(factory.getNashornEngine().eval("JSON"), "stringify", map);
                 } catch (NoSuchMethodException ex) {
                 throw new ScriptException(ex);
                 }
                 */
                SimpleResource simpleResource = moduleResource.adaptTo(SimpleResource.class);
                put("simpleResource", simpleResource);
                /*   String source = "exports.properties =  " + jsonprop + ";"
                 + "exports.path = currentNode.resource.path;"
                 + "exports.simpleResource = this.simpleResource;"
                 + "exports.children = this.children;";*/
                String source = "module.exports = this.simpleResource;";

                function = decorateScript(source, false);
            }
            if (!moduleScript.isResourceFile()) {
                factory.getModuleCache().put(moduleScript.getResource().getPath(), function);
            }
        } else {
            log.debug("module " + get(CONTEXT_FIELD_ID) + " received from cache");
        }

        if (moduleScript.isTextFile()) {
            log.debug("is textfile loaidng file");
            String source = StringEscapeUtils.escapeEcmaScript(readScript(moduleResource));
            log.debug("sourcE: ");
            source = "module.exports = \"" + source + "\";";
            log.debug(source);
            function = Module.this.decorateScript(source);
            factory.getModuleCache().put(moduleScript.getResource().getPath(), function);
        }
        JSObject process = (JSObject) factory.getNashornEngine().eval("Object");
        process.setMember("domain", log);

        if (function != null) {
            SimpleBindings currentNode = new SimpleBindings();
            if (resource != null) {
                currentNode.put("resource", resource);
                currentNode.put("properties", resource.adaptTo(ValueMap.class));
            } else {
                log.debug("module id {} resource is null", get(CONTEXT_FIELD_ID));
            }

            // changed require to be generated within the wrapper
            // TODO: need to be refactored
            function.call(this, get(CONTEXT_FIELD_EXPORTS), this, this, get(CONTEXT_FIELD_FILENAME),
                    ((Resource) get(CONTEXT_FIELD_MODULE_RESOURCE)).getParent().getPath(), currentNode,
                    (ConsoleLog) get(CONTEXT_FIELD_CONSOLE),
                    null,
                    (SlingScriptHelper) get(CONTEXT_FIELD_SLING),
                    resource.adaptTo(SimpleResource.class)
            );

        } else {
            log.warn("function not called because it is null");
        }

        put(CONTEXT_FIELD_EXPORTS, get(CONTEXT_FIELD_EXPORTS));

        return get(CONTEXT_FIELD_EXPORTS);
    }

    /**
     *
     * @param script
     * @return
     */
    public String readScript(Resource script) throws ScriptException {
        InputStream is = script.getChild("jcr:content").adaptTo(InputStream.class);
        BufferedReader esxScript = new BufferedReader(new InputStreamReader(is));
        StringBuilder buffer = new StringBuilder();
        String temp;
        try {
            while ((temp = esxScript.readLine()) != null) {
                buffer.append(temp).append("\r\n");
            }
            return buffer.toString();
        } catch (IOException ioex) {
            throw new ScriptException(ioex);
        }
    }

    /**
     *
     * @param path
     * @return
     */
    private boolean isLocalModule(String path) {
        return (path.startsWith("./") == true
                || path.startsWith("/") == true
                || path.startsWith("../") == true);
    }

    /**
     *
     * @param path
     * @param basePath
     * @return
     */
    private String normalizePath(String path, String basePath) {
        path = StringUtils.removeStart(cleanModulePathFromLoaders(path), basePath);
        return ResourceUtil.normalize(basePath + "/" + path);
    }

    /**
     * not implemented yet
     *
     * @param path
     * @return
     */
    private boolean isGlobalModule(String path) {
        return false;
    }

    /**
     *
     * @param file
     * @param type
     * @return
     * @throws ScriptException
     */
    private ModuleScript createModuleScript(Resource file, int type) throws ScriptException {
        log.debug("module created. " + file.getPath());
        Node currentNode = file.adaptTo(Node.class);
        if (currentNode != null) {
            log.debug("currentNode !) null = " + (currentNode != null));
            try {
                boolean isFile = currentNode.isNodeType(NodeType.NT_FILE);
                log.debug("isFile: " + isFile);
                if (isFile) {
                    return new ModuleScript(type, file);
                }
                log.debug("not a file " + currentNode.getMixinNodeTypes().toString());
            } catch (RepositoryException ex) {
                throw new ScriptException("cannot load file " + file.getPath());
            }
        }
        return null;

    }

    /**
     *
     * @param module
     * @param path
     * @param currentResource
     * @return
     * @throws ScriptException
     */
    public ModuleScript loadAsFile(String module, String path,
            Resource currentResource, String loader) throws ScriptException {
        int type = ModuleScript.JS_FILE;

        // this is need to be refactored, it is this way because I followed the
        // node.js extension handling at first but switched over to requirejs
        // loader notation        
        Resource file = currentResource.getResourceResolver().getResource(path);

        // require.extensions is deprecated, however to implement this might 
        // be a good way to handle .resource loading or to implemend loader 
        // like in requirejs e.g. similar to https://github.com/requirejs/text
        // "text!some/module.html" 
        // or require("resource!/content/homepage/jcr:content")
        if (LOADER_RESOURCE.equals(loader) && file != null) {
            return new ModuleScript(ModuleScript.RESOURCE_FILE, file);
        }

        if (LOADER_TEXT.equals(loader) && file != null) {
            return new ModuleScript(ModuleScript.TEXT_FILE, file);
        }

        //special handling for json file require
        if (path.endsWith(".json") && file != null) {
            return new ModuleScript(ModuleScript.JSON_FILE, file);
        }

        if (path.endsWith(".bin") && file != null) {
            log.warn(".bin loder are currently not supported (file  requested: " + path);
        }

        try {
            if (file == null || !file.adaptTo(Node.class).isNodeType(NodeType.NT_FILE)) {
                file = currentResource.getResourceResolver().getResource(path + ".js");
                if (file == null) {
                    file = currentResource.getResourceResolver().getResource(path + ".json");
                    if (file == null) {
                        return null;
                    }
                    type = ModuleScript.JSON_FILE;
                } else {
                    type = ModuleScript.JS_FILE;
                }
            }
        } catch (RepositoryException ex) {
            log.error(module + "", ex);
        }

        return createModuleScript(file, type);
    }

    private String cleanModulePathFromLoaders(String path) {
        if (path.startsWith("resource!")) {
            return path.substring("resource!".length(), path.length());
        }

        if (path.startsWith("text!")) {
            return path.substring("text!".length(), path.length());
        }

        return path;
    }

    /**
     *
     * @param module
     * @param path
     * @param currentResource
     * @return
     * @throws ScriptException
     */
    public ModuleScript loadAsDirectory(String module, String path, Resource currentResource, String loader) throws ScriptException {

        ResourceResolver resolver = currentResource.getResourceResolver();
        Resource packageJson = resolver.getResource(path + "/package.json");

        if (packageJson != null) {
            Node jsonFile = packageJson.adaptTo(Node.class);

            try {
                boolean isFile = (jsonFile.isNodeType(NodeType.NT_FILE) || jsonFile.isNodeType(NodeType.NT_RESOURCE));

                if (isFile) {

                    InputStream is = packageJson.getChild("jcr:content").adaptTo(InputStream.class);
                    try {
                        String jsonData = IOUtils.toString(is);

                        Invocable invocable = (Invocable) factory.getNashornEngine();
                        JSObject jsonprop = null;
                        try {
                            jsonprop = (JSObject) invocable.invokeMethod(factory.getNashornEngine().eval("JSON"), "parse", jsonData);
                        } catch (NoSuchMethodException ex) {
                            throw new ScriptException(ex);
                        }

                        Object main = jsonprop.getMember("main");
                        if (main != null) {
                            String packageModule = (String) main;

                            String mainpath = normalizePath(packageModule,
                                    path);
                            return loadAsFile(packageModule, mainpath, currentResource, loader);
                        }

                    } catch (IOException ex) {
                        throw new ScriptException(ex);
                    }
                }

            } catch (RepositoryException ex) {
                throw new ScriptException(ex);
            }

        }

        Resource indexjs = resolver.getResource(path + "/index.js");

        if (indexjs != null) {
            return createModuleScript(indexjs, ModuleScript.JS_FILE);
        }

        Resource indexjson = resolver.getResource(path + "/index.json");

        if (indexjson != null) {
            return createModuleScript(indexjson, ModuleScript.JSON_FILE);
        }

        Resource indexnode = resolver.getResource(path + "/index.node");
        if (indexnode != null) {
            throw new ScriptException("Node module .node (binary) loading is currently not supported");
        }

        return null;
    }

    /**
     *
     * @param module
     * @param currentResource
     * @return
     * @throws ScriptException
     */
    public ModuleScript loadAsModule(String module, Resource currentResource, String loader) throws ScriptException {
        return loadAsModule(module, currentResource, true, loader);
    }

    /**
     *
     * @param paths
     * @return
     */
    private String[] loadModulePaths(String paths) {
        String[] parts = paths.split("/");
        List<String> dirs = new ArrayList<String>();

        for (int i = (parts.length - 1); i > 0;) {
            log.debug(parts[i]);
            if (parts[i] == "node_modules" || parts[i] == "esx_modules") {
                continue;
            }
            String part = StringUtils.join(parts, "/", 0, i);
            String dir = part + "/node_modules";
            log.debug("load dir: " + dir);
            dirs.add(part + "/esx_modules");
            dirs.add(dir);
            i = i - 1;
        }

        // if the regular module resoultion is not finding anything, try and check the
        // global paths. needs to be optimized.
        dirs.add("/apps/esx/esx_modules");
        dirs.add("/apps/esx/node_modules");
        dirs.add("/libs/esx/esx_modules");
        dirs.add("/libs/esx/node_modules");

        return dirs.stream().toArray(String[]::new);
    }

    /**
     *
     * @param module
     * @param currentResource
     * @param isFileResource
     * @return
     * @throws ScriptException
     */
    public ModuleScript loadAsModule(String module, Resource currentResource, boolean isFileResource, String loader) throws ScriptException {
        ModuleScript script = null;

        String[] dirs = loadModulePaths(currentResource.getPath());
        log.debug("loading modules from dir path");
        for (String dir : dirs) {
            log.debug("trying to resolve. " + dir);
            Resource searchPath = currentResource.getResourceResolver().resolve(dir);
            log.debug("searchpath  = " + searchPath.getPath());
            if (searchPath != null && !ResourceUtil.isNonExistingResource(searchPath)) {
                log.debug("searchpath loadasmodule: " + searchPath.getPath());
                script = loadLocalModule(module, searchPath, false, loader);
                if (script != null) {
                    return script;
                }
            } else {
                log.debug("dir is null = " + dir);
            }
        }
        log.debug("finsihed loading dirs, script is loaded?!");
        return script;
    }

    /**
     *
     * @param module
     * @param currentResource
     * @return
     * @throws ScriptException
     */
    public ModuleScript loadLocalModule(String module, Resource currentResource, String loader) throws ScriptException {
        return loadLocalModule(module, currentResource, false, loader);
    }

    /**
     *
     * @param resource
     * @return
     */
    private boolean resourceIsfile(Resource resource) {
        try {
            return resource.adaptTo(Node.class).isNodeType(NodeType.NT_FILE);
        } catch (RepositoryException ex) {
            log.error("resourceIsfile", ex);
        }
        return false;
    }

    /**
     *
     * @param module
     * @param currentResource
     * @param isFile
     * @return
     * @throws ScriptException
     */
    public ModuleScript loadLocalModule(String module, Resource currentResource, boolean isFile, String loader) throws ScriptException {
        String basePath = (resourceIsfile(currentResource))
                ? currentResource.getParent().getPath() : currentResource.getPath();
        String path = normalizePath(module, basePath);

        if (module.startsWith("/")) {
            path = module;
        }
        ModuleScript script = loadAsFile(module, path, currentResource, loader);

        if (script != null) {
            return script;
        }

        return loadAsDirectory(module, path, currentResource, loader); // load as directory                              
    }

    /**
     * p´
     *
     * @param module
     * @param currentResource
     * @return
     * @throws javax.script.ScriptException
     */
    public ModuleScript resolve(String module, Resource currentResource, String loader) throws ScriptException {
        // if x is core module / library return directly the one
        log.debug("resolving module: " + module);
        ModuleScript script;

        if (isGlobalModule(module)) {
            // ignore for now
        }

        if (isLocalModule(module)) {
            script = loadLocalModule(module, currentResource, loader);
            if (script != null) {
                return script;
            }
        }

        // load as module (first split path, then load)
        script = loadAsModule(module, currentResource, loader);
        if (script != null) {
            return script;
        }

        throw new ScriptException("module not found " + module);
    }

    @Override
    public Object require(String id) throws ScriptException, IOException {
        log.debug("Trying to require Module with Id: " + id);
        // different behavior if we are the main module, require directly
        // run runScript directly on this module
        if (get("id").equals(id)
                && get("main") == this) {
            return runScript();
        }

        String loader = LOADER_JS;
        if (id.startsWith(LOADER_TEXT)) {
            loader = LOADER_TEXT;
        }

        if (id.startsWith(LOADER_RESOURCE)) {
            loader = LOADER_RESOURCE;
        }
        ModuleScript subModuleScript = resolve(cleanModulePathFromLoaders(id), (Resource) get(CONTEXT_FIELD_MODULE_RESOURCE), loader);

        Module subModule = new Module(factory, (Resource) get(CONTEXT_FIELD_RESOURCE),
                subModuleScript, id, this, (SlingScriptHelper) get(CONTEXT_FIELD_SLING), loader);
        Object result = subModule.runScript();
        children.add(subModule);
        subModule.put(CONTEXT_FIELD_IS_LOADED, true);
        return result;
    }
}
