package org.projectodd.wunderboss.ruby.rack;

import org.projectodd.wunderboss.Application;
import org.projectodd.wunderboss.Component;
import org.projectodd.wunderboss.ComponentInstance;
import org.projectodd.wunderboss.Options;
import org.projectodd.wunderboss.ruby.RuntimeHelper;
import org.jruby.Ruby;
import org.jruby.runtime.builtin.IRubyObject;

import java.util.HashMap;
import java.util.Map;

public class RackComponent extends Component{
    @Override
    public String[] getLanguageDependencies() {
        return new String[]{"ruby"};
    }

    @Override
    public String[] getComponentDependencies() {
        return new String[]{"servlet"};
    }

    @Override
    public void boot() {
    }

    @Override
    public void shutdown() {
    }

    @Override
    public void configure(Options options) {
    }

    @Override
    public ComponentInstance start(Application application, Options options) {
        String context = options.getString("context", "/");
        String root = options.getString("root", ".");
        String staticDirectory = options.getString("static_dir", root + "/public");

        String rackScript = "require 'rack'\n" +
                "app, _ = Rack::Builder.parse_file(File.join('" + root + "', 'config.ru'))\n" +
                "app\n";
        IRubyObject rackApplication = RuntimeHelper.evalScriptlet(getRuntime(application), rackScript, false);

        Map<String, Object> servletContextAttributes = new HashMap<>();
        servletContextAttributes.put("rack_application", rackApplication);

        Options servletOptions = new Options();
        servletOptions.put("context", context);
        servletOptions.put("static_dir", staticDirectory);
        servletOptions.put("servlet_class", RackServlet.class);
        servletOptions.put("context_attributes", servletContextAttributes);
        ComponentInstance servlet = application.start("servlet", servletOptions);

        Options instanceOptions = new Options();
        instanceOptions.put("servlet", servlet);
        return new ComponentInstance(this, instanceOptions);
    }

    @Override
    public void stop(ComponentInstance instance) {
        ComponentInstance servlet = (ComponentInstance) instance.getOptions().get("servlet");
        servlet.stop();
    }

    private Ruby getRuntime(Application application) {
        return (Ruby) application.getRuntime();
    }
}

@@ -1110,17 +1110,209 @@
 blic%22);%0A
-%0A
+        Object rackApp = options.get(%22rack_app%22);%0A%0A        IRubyObject rackApplication;%0A        if (rackApp != null) %7B%0A            rackApplication = (IRubyObject) rackApp;%0A        %7D else %7B%0A    
         
@@ -1348,24 +1348,28 @@
 'rack'%5Cn%22 +%0A
+    
             
@@ -1464,24 +1464,28 @@
             
+    
 %22app%5Cn%22;%0A   
@@ -1485,35 +1485,27 @@
 n%22;%0A        
-IRubyObject
+   
  rackApplica
@@ -1583,16 +1583,26 @@
  false);
+%0A        %7D
 %0A%0A      

Add support for deploy already-created Rack apps