package lux.appserver;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Properties;

import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.DefaultServlet;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.webapp.WebAppContext;

public class AppServer {
    
    private static final String LUX_APPSERVER_PORT = "lux.appserver.port";
    private static final String LUX_SOLR_URL = "lux.solr.url";
    private static final String LUX_RESOURCE_BASE = "lux.appserver.resourceBase";
    private static final String LUX_CONTEXT = "lux.appserver.context";
    
    public static final String DEFAULT = "default";
    public static final String LUX_APP_FORWARDER = "lux.app-forwarder";
    
    // defaults
    private int port = 8080;            // -p
    private String context = "/";       // -c
    private String resourceBase = ".";  // -r
    
    private ServletHolder appForwarderHolder;
    private ServletHolder resourcesHolder;
    private static WebAppContext luxWebapp;
    private Server server;
    
    public static void main (String ... argv) throws Exception {
        //System.setProperty("org.eclipse.jetty.LEVEL", "DEBUG");
        AppServer server = new AppServer(argv);
        server.start();
    }
    
    public AppServer (String ... argv) {
        AppHandler handler = new AppHandler();
        
        AppForwarder xqueryForward = new AppForwarder();
        appForwarderHolder = new ServletHolder(xqueryForward);
        appForwarderHolder.setName(LUX_APP_FORWARDER);
        handler.addServlet(appForwarderHolder);
        
        DefaultServlet resources = new DefaultServlet();
        resourcesHolder = new ServletHolder(resources);
        resourcesHolder.setInitParameter("dirAllowed", "false");
        resourcesHolder.setName(DEFAULT);
        handler.addServlet(resourcesHolder);

        handleProperties();
        handleArguments(argv);

        resourcesHolder.setInitParameter("resourceBase", resourceBase);
        appForwarderHolder.setInitParameter("resourceBase", resourceBase);
        
        if (appForwarderHolder.getInitParameter("solr-host") == null) {
            // embedded solr war:
            // FIXME: expose these paths via configuration?
            luxWebapp = new WebAppContext(handler, "src/main/webapp", "/solr");
            xqueryForward.setServletPath ("/solr");
            xqueryForward.setForwardPath ("/solr/lux");
            xqueryForward.setSolrPort (port);
            handler.setSolrWebapp (luxWebapp);
            // server.setHandler(webapp);
        }

        server = new Server(port);

        ServletContextHandler root = new ServletContextHandler(server, context);
        root.setWelcomeFiles(new String[] { "index.xqy" });
        root.setServletHandler(handler);
        
    }
    
    // read properties from lux.properties in the current directory, if it exists
    private void handleProperties () {
        File f = new File ("lux.properties");
        if (!f.canRead()) {
            return;
        }
        Properties props = new Properties();
        try {
            props.load(new FileInputStream(f));
        } catch (FileNotFoundException e) {
           error (e.getMessage());
        } catch (IOException e) {
            error (e.getMessage());
        }
        if (props.containsKey(LUX_APPSERVER_PORT)) {
           setPort (props.getProperty(LUX_APPSERVER_PORT));
        }
        if (props.containsKey(LUX_SOLR_URL)) {
            setSolrURL(props.getProperty(LUX_SOLR_URL));
        }
        if (props.containsKey(LUX_RESOURCE_BASE)) {
            resourceBase = props.getProperty(LUX_RESOURCE_BASE);
        }
        if (props.containsKey(LUX_CONTEXT)) {
            context = props.getProperty(LUX_CONTEXT);
        }
    }

    private void handleArguments (String... argv) {
        for (int i = 0; i < argv.length; i+=2) {
            String arg = argv[i];
            if (i == argv.length - 1) {
               usage ();
            }
            String value = argv[i+1];
            if (arg.equals("-p")) {
                setPort(value);
            }
            else if (arg.equals("-c")) {
                context = value;
            }
            else if (arg.equals("-s")) {
                setSolrURL(value);
            }
            else if (arg.equals("-r")) {
                resourceBase = value;
            }
        }
    }

    private void setSolrURL(String value) {
        URL solrURL=null;
        try {
            solrURL = new URL(value);
        } catch (MalformedURLException e) {
            error ("-s must be followed by a valid URL, not " + value);
        }
        appForwarderHolder.setInitParameter("solr-host", solrURL.getHost());
        int solrPort = solrURL.getPort();
        if (solrPort > 0) {
            appForwarderHolder.setInitParameter("solr-port", Integer.toString(solrPort));
        }
        appForwarderHolder.setInitParameter("forward-path", solrURL.getPath());
    }

    private void setPort(String value) {
        try {
            port = Integer.valueOf(value);
        } catch (NumberFormatException e) {
            error ("port must be a valid port number, not " + value);
        }
    }
    
    private void start () throws Exception {
        server.start();
        server.join();
    }
    
    private static void error (String error) {
        System.err.println (error);
        System.exit(-1);
    }
    
    private static void usage () {
        error ("Usage: java -jar lux-appserver.jar [-p {port}] [-c {context}] [-s http://{solr-host}:{solr-port}/{forward-path}] [-r {resource-base}]");
    }
    
}

@@ -1493,32 +1493,109 @@
 ing ... argv) %7B%0A
+        %0A        handleProperties();%0A        handleArguments(argv);%0A        %0A
         AppHandl
@@ -2136,67 +2136,8 @@
 );%0A%0A
-        handleProperties();%0A        handleArguments(argv);%0A
 %0A   
@@ -3530,152 +3530,268 @@
     
-if (props.containsKey(LUX_APPSERVER_PORT)) %7B%0A           setPort (props.getProperty(LUX_APPSERVER_PORT));%0A        %7D%0A        if (props.containsKey
+for (Object o : props.keySet()) %7B%0A            String pname = o.toString();%0A            String value = props.getProperty(pname);%0A            if (pname.equals(LUX_APPSERVER_PORT)) %7B%0A                setPort (value);%0A            %7D%0A            else if (pname.equals
 (LUX
@@ -3808,32 +3808,36 @@
 ) %7B%0A            
+    
 setSolrURL(props
@@ -3835,81 +3835,63 @@
 URL(
-props.getProperty(LUX_SOLR_URL));%0A        %7D%0A        if (props.containsKey
+value);%0A            %7D%0A            else if (pname.equals
 (LUX
@@ -3913,32 +3913,36 @@
 ) %7B%0A            
+    
 resourceBase = p
@@ -3944,85 +3944,62 @@
 e = 
-props.getProperty(LUX_RESOURCE_BASE);%0A        %7D%0A        if (props.containsKey
+value;%0A            %7D%0A            else if (pname.equals
 (LUX
@@ -4015,32 +4015,36 @@
 ) %7B%0A            
+    
 context = props.
@@ -4041,39 +4041,111 @@
 t = 
-props.getProperty(LUX_CONTEXT);
+value;%0A            %7D%0A            else %7B%0A                System.setProperty(pname, value);%0A            %7D
 %0A   

enable setting system properties via lux.properties file