package org.projectodd.nodyn;

import org.dynjs.runtime.DynJS;
import org.dynjs.runtime.DynObject;
import org.dynjs.runtime.ExecutionContext;
import org.dynjs.runtime.GlobalObject;
import org.dynjs.runtime.GlobalObjectFactory;
import org.dynjs.runtime.InitializationListener;
import org.dynjs.vertx.DynJSVerticle;
import org.dynjs.vertx.DynJSVerticleFactory;
import org.projectodd.nodyn.util.QueryString;
import org.projectodd.nodyn.buffer.BufferType;
import org.vertx.java.platform.Verticle;

public class NodeJSVerticleFactory extends DynJSVerticleFactory {
    private GlobalObjectFactory globalObjectFactory = new NodeJSGlobalObjectFactory();
    private String filename;

    @Override
    protected GlobalObjectFactory getGlobalObjectFactory() {
        return this.globalObjectFactory;
    }

    @Override
    public Verticle createVerticle(String main) throws Exception {
        this.filename = main;
        return new NodeJSVerticle(this, main);
    }

    private class NodeJSGlobalObjectFactory extends DynJSGlobalObjectFactory {
        @Override
        public GlobalObject newGlobalObject(final DynJS runtime) {
            GlobalObject global = super.newGlobalObject(runtime);
            BufferType bufferType = new BufferType(global);
            DynObject node = new DynObject(global);
            node.put("buffer", bufferType);
            node.put("QueryString", new QueryString(global));
            global.defineGlobalProperty("nodyn", node);
            global.defineGlobalProperty("Buffer", bufferType);
            global.defineGlobalProperty("__filename", filename);
            return global;
        }
    }
    
    protected class NodeJSVerticle extends DynJSVerticle {

        public NodeJSVerticle(DynJSVerticleFactory factory, String scriptName) {
            super(factory, scriptName);
        }
        
        @Override
        protected ExecutionContext initializeRootContext() {
            return ExecutionContext.createGlobalExecutionContext(getRuntime(), new InitializationListener()
            {
                @Override
                public void initialize(ExecutionContext context) {
                    try {
                        getRuntime().evaluate("include('node.js')");
                    } catch (Exception e) {
                        System.err.println("[ERROR] Cannot initialize Nodyn. " + e.getMessage());
                        e.printStackTrace();
                    }
                }
            });
        }

    }

}

@@ -487,16 +487,35 @@
 ticle;%0A%0A
+import java.io.*;%0A%0A
 public c
@@ -2175,267 +2175,1371 @@
     
-try %7B%0A                        getRuntime().evaluate(%22include('node.js')%22);%0A                    %7D catch (Exception e) %7B%0A                        System.err.println(%22%5BERROR%5D Cannot initialize Nodyn. %22 + e.getMessage());%0A                        e.printStackTrace(
+// not sure why this is necessary, but if we just have %60process = require('process')%60 in node.js%0A                    // it's not loaded globally. We must both define the global property right here, and also%0A                    // require the file from within node.js - strange.%0A                    // I still don't really understand how to make something truly global in dynjs%0A                    GlobalObject globalObject = context.getGlobalObject();%0A                    globalObject.defineGlobalProperty(%22process%22, runtime.newRunner().withContext(context).withSource(%22require('process')%22).execute());%0A                    globalObject.defineGlobalProperty(%22console%22, runtime.newRunner().withContext(context).withSource(%22require('node_console')%22).execute());%0A                    InputStream is = runtime.getConfig().getClassLoader().getResourceAsStream(%22node.js%22);%0A                    if (is != null) %7B%0A                        BufferedReader reader = new BufferedReader(new InputStreamReader(is));%0A                        runtime.newRunner().withSource(reader).evaluate();%0A                        try %7B%0A                            is.close();%0A                        %7D catch (IOException e) %7B%0A                            // ignore%0A                        %7D%0A                    %7D else %7B%0A                        System.err.println(%22%5BERROR%5D Cannot initialize Nodyn.%22
 );%0A 

Define process and console in the root context