package lein.ring;

import clojure.lang.RT;
import clojure.lang.IFn;
import clojure.lang.Var;
import clojure.lang.Symbol;


import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.GenericServlet;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

public class Servlet extends GenericServlet {

    public IFn handler;

    public static Var REQUIRE = RT.var("clojure.core", "require");
    public static Var SYMBOL = RT.var("clojure.core", "symbol");
    public static Var RESOLVE = RT.var("clojure.core", "resolve");
    public static Var DEREF = RT.var("clojure.core", "deref");
    public static Symbol SERVLET_NS =  Symbol.create("ring.util.servlet");
    public static Var MAKE_SERVICE_METHOD =
        RT.var("ring.util.servlet", "make-service-method");

    static {
        REQUIRE.invoke(SERVLET_NS);
    }

    // TODO: destroy

    public Servlet() {;}

    public void init() throws ServletException {
        ServletConfig config = this.getServletConfig();

        // Handler
        require(config.getInitParameter("ns-name"));
        handler = createServiceMethod(config.getInitParameter("ns-name"),
                                      config.getInitParameter("handler-name"));

        // Init
        require(config.getInitParameter("init-ns-name"));
        invoke(config.getInitParameter("init-ns-name"),
               config.getInitParameter("init-name"));
    }

    public void service(ServletRequest request, ServletResponse response) {
        handler.invoke(this, request, response);
    }

    private void require(String namespace) {
        REQUIRE.invoke(SYMBOL.invoke(namespace));
    }

    private IFn createServiceMethod(String namespace, String handler) {
        return (IFn) MAKE_SERVICE_METHOD.invoke(DEREF.invoke(RT.var(namespace, handler)));
    }

    private void invoke(String namespace, String var) {
        RT.var(namespace, var).invoke();
    }

}

@@ -531,216 +531,11 @@
 tic 
-Var RESOLVE = RT.var(%22clojure.core%22, %22resolve%22);%0A    public static Var DEREF = RT.var(%22clojure.core%22, %22deref%22);%0A    public static Symbol SERVLET_NS =  Symbol.create(%22ring.util.servlet%22);%0A    public static Var
+IFn
  MAK
@@ -561,22 +561,18 @@
         
-RT.var
+fn
 (%22ring.u
@@ -614,64 +614,8 @@
 );%0A%0A
-    static %7B%0A        REQUIRE.invoke(SERVLET_NS);%0A    %7D%0A%0A
     
@@ -787,61 +787,8 @@
 ler%0A
-        require(config.getInitParameter(%22ns-name%22));%0A
     
@@ -958,66 +958,8 @@
 nit%0A
-        require(config.getInitParameter(%22init-ns-name%22));%0A
     
@@ -1067,24 +1067,146 @@
 %22));%0A    %7D%0A%0A
+    public static IFn fn(String ns, String fnName) %7B%0A        require(ns);%0A        return (IFn) RT.var(ns, fnName);%0A    %7D%0A%0A
     public v
@@ -1333,24 +1333,31 @@
     private 
+static 
 void require
@@ -1558,27 +1558,10 @@
 oke(
-DEREF.invoke(RT.var
+fn
 (nam
@@ -1577,17 +1577,16 @@
 andler))
-)
 ;%0A    %7D%0A
@@ -1650,22 +1650,18 @@
         
-RT.var
+fn
 (namespa
@@ -1685,11 +1685,10 @@
 ;%0A    %7D%0A
-%0A
 %7D%0A

simplify clojure interop a bit