package com.semperos.screwdriver.js;

import com.semperos.screwdriver.Config;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.Scriptable;

import java.io.IOException;
import java.util.HashMap;
import java.util.List;

/**
 * @todo Steps needed:
 *   * Create generic {@link org.mozilla.javascript.ScriptableObject} class to handle
 *     properties used for RequireJS optimizer's config (see hardcoded-build.js).
 *   * For each needed build (determined by user-provided list of main JS modules to target),
 *     create unique instance of that object and set it's data accordingly (i.e., change values
 *     based on the config needs for each main JS module)
 *   * Add those objects to an array, say of __Screwdriver.rjsMainModules, which can then
 *     be iterated through in the evaluated JavaScript and passed to requirejs.optimize
 */
public class RjsConfigCompiler {
    private RhinoCompiler rhinoCompiler;
    private List<String> rjsModules;

    public RjsConfigCompiler(Config cfg) {
        JsRuntimeSupport jsRuntimeSupport = new JsRuntimeSupport();
        rhinoCompiler = new RhinoCompiler(jsRuntimeSupport);
        rjsModules = cfg.getRjsModules();
        HashMap<String,String> deps = new HashMap<String,String>();
        deps.put("r.js", "com/semperos/screwdriver/js/vendor/r-patched.js");
        rhinoCompiler.addDependencies(deps);
    }

    public void compile() throws IOException, RhinoEvaluatorException {
        processRjsModuleConfigs();
        rhinoCompiler.registerCompiler("process-rjs", "com/semperos/screwdriver/js/extension/process-rjs.js");
        rhinoCompiler.compile();
    }

    public Scriptable newBaseConfig() {
        Context ctx = Context.enter();
        Scriptable baseConfigObj = ctx.newObject(rhinoCompiler.getInstanceScope());
        try {
            baseConfigObj.put("mainConfigFile", baseConfigObj, "src/test/resources/com/semperos/screwdriver/sample/output/javascripts/common.js");
            baseConfigObj.put("optimize", baseConfigObj, "closure");
            Scriptable closureConfigObj = ctx.newObject(rhinoCompiler.getInstanceScope());
            closureConfigObj.put("CompilerOptions", closureConfigObj, ctx.newObject(rhinoCompiler.getInstanceScope()));
            closureConfigObj.put("CompilationLevel", closureConfigObj, "SIMPLE_OPTIMIZATIONS");
            closureConfigObj.put("loggingLevel", closureConfigObj, "WARNING");
            baseConfigObj.put("closure", baseConfigObj, closureConfigObj);
            baseConfigObj.put("baseUrl", baseConfigObj, "src/test/resources/com/semperos/screwdriver/sample/output/javascripts");
            baseConfigObj.put("findNestedDependencies", baseConfigObj, true);
            baseConfigObj.put("name", baseConfigObj, "vendor/almond-0.2.4");
            baseConfigObj.put("wrap", baseConfigObj, true);
            baseConfigObj.put("logLevel", baseConfigObj, 0);
        } finally {
            Context.exit();
        }
        return baseConfigObj;
    }

    /**
     * Given list of module names, dynamically generate array of r.js configs,
     * one per module. Stick those as an array in {@code __Screwdriver.rjs.moduleConfigs}.
     */
    public void processRjsModuleConfigs() {
        Context ctx = Context.enter();
        try{
            // Now include module-specific configuration for each target module
            Scriptable rjs = ctx.newObject(rhinoCompiler.getInstanceScope());
            Scriptable moduleConfigs = ctx.newArray(rhinoCompiler.getInstanceScope(), rjsModules.size());
            for (int i = 0; i < rjsModules.size(); i++) {
                String m = rjsModules.get(i);
                Object[] ms = new Object[]{ m };
                Scriptable baseConfigObj = newBaseConfig();
                baseConfigObj.put("include", baseConfigObj, ctx.newArray(rhinoCompiler.getInstanceScope(), ms));
                baseConfigObj.put("insertRequire", baseConfigObj, ctx.newArray(rhinoCompiler.getInstanceScope(), ms));
                baseConfigObj.put("out", baseConfigObj, "src/test/resources/com/semperos/screwdriver/sample/output/built/javascripts/" + m + "-built.js");
                moduleConfigs.put(i, moduleConfigs, baseConfigObj);
            }
            // "Save" changes
            rjs.put("moduleConfigs", rjs, moduleConfigs);
            rhinoCompiler.addInstanceField("rjs", rjs);
        } finally {
            Context.exit();
        }
    }
}

@@ -242,140 +242,28 @@
 %0A * 
-@todo Steps needed:%0A *   * Create generic %7B@link org.mozilla.javascript.ScriptableObject%7D class to handle%0A *     properties used for
+Generate and process
  Req
@@ -282,469 +282,45 @@
 izer
-'s
  config
- (see hardcoded-build.js).%0A *   * For each needed build (determined by user-provided list of main JS modules to target),%0A *     create unique instance of that object and set it's data accordingly (i.e., change values%0A *     based on the config needs for each main JS module)%0A *   * Add those objects to an array, say of __Screwdriver.rjsMainModules, which can then%0A *     be iterated through in the evaluated JavaScript and passed to requirejs.optimize
+urations for JavaScript files.
 %0A */

Update documentation for RjsConfigCompiler