package mycomp.web.server;

import java.io.File;
import java.io.FileInputStream;
import java.io.OutputStream;
import java.net.ConnectException;
import java.net.InetAddress;
import java.net.Socket;
import java.net.URL;
import java.security.ProtectionDomain;

import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.HandlerList;
import org.eclipse.jetty.server.nio.SelectChannelConnector;
import org.eclipse.jetty.util.thread.QueuedThreadPool;
import org.eclipse.jetty.webapp.WebAppContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


public class EmbeddedJettyServer
{
    private final static Logger logger = LoggerFactory.getLogger(EmbeddedJettyServer.class);
    
    private int port;
    private int shutdownPort;
    private String contextPath;
    private String workPath;
    private URL location;
    private String secret;
    private String webappContextPath;
    
    public static void main(String[] args) throws Exception {   
        EmbeddedJettyServer sc = new EmbeddedJettyServer();
        sc.parseAndRun(args);
    }
    
    protected void parseAndRun(String[] args) throws Exception {
        
        if (args.length == 0 || "start".equals(args[0])) start();
        else if ("stop".equals(args[0])) stop();
        else usage();
    }
    
    protected void usage() {
        System.out.println("Usage: java -jar <file.jar> [start|stop]\n\t" +
                "start Start the server (default)\n\t" +
                "stop Stop the server gracefully\n"
        );
        System.exit(-1);
    }
    
    public EmbeddedJettyServer() {
    	configure();
    }
    
    protected void configure() {
	// trying to load some properties from different places
        try {
            String jettyConfPath = System.getProperty("jetty.properties");
            File jettyConfFile = null;
            if ( jettyConfPath != null ) {
                jettyConfFile = new File(jettyConfPath);
            }
            
            if ( jettyConfFile == null || !jettyConfFile.exists() ) {
                jettyConfPath = "etc/jetty.properties";
            }
            
            System.getProperties().load(new FileInputStream(jettyConfPath));
            
        } catch (Exception e) {
        }

        port = Integer.parseInt(System.getProperty("jetty.port", "8080"));
        shutdownPort = Integer.parseInt(System.getProperty("jetty.shutdownPort", "8081"));
        contextPath = System.getProperty("jetty.contextPath", contextPath);
        workPath = System.getProperty("jetty.workDir", null);
 
        secret = System.getProperty("jetty.secret", "admin");
        webappContextPath = System.getProperty("webapp.contextPath", "/");
        
        ProtectionDomain domain = EmbeddedJettyServer.class.getProtectionDomain();
        location = domain.getCodeSource().getLocation();
    }
 
    public String getWebAppDescriptor() {
        return location.toExternalForm() + "/WEB-INF/web.xml";
    }
    
    public String getWarPath() {
        return location.toExternalForm();
    }
    
    public String getContextPath() {
        return contextPath;
    }
    
    protected void start() {
    	Monitor.monitor(shutdownPort, secret);

        Server server = new Server();
        server.setStopAtShutdown(true);
        server.setGracefulShutdown(1000);

        QueuedThreadPool threadPool = new QueuedThreadPool();
        threadPool.setMaxThreads(100);
        server.setThreadPool(threadPool);

        Connector connector = new SelectChannelConnector();
        connector.setPort(port);
        connector.setMaxIdleTime(30000);
        server.setConnectors(new Connector[]{connector});
        
        WebAppContext webapp = new WebAppContext();
        webapp.setContextPath(webappContextPath);
        webapp.setDescriptor(getWebAppDescriptor());
        webapp.setWar(getWarPath());

        prepareWithHotDeployment(server, webapp);
        
        resetTempDirectory(webapp, workPath);

        
        HandlerList handlers = new HandlerList();
        handlers.addHandler(webapp);
        server.setHandler(handlers);
        
        try {
            server.start();
            server.join();
        } catch (InterruptedException ignored) {
            
        } catch (Exception startException) {
        } finally {
        	
            if ( !server.isFailed() )
                try {
                    server.stop();
                } catch (Exception ignored) {}
        }
    }
    
    public void prepareWithHotDeployment(Server server, WebAppContext context) {
        
    }
    
    protected void stop() {
    	// some more code...
    }

    private void resetTempDirectory(WebAppContext context, String currentDir) {
        File workDir;
        if (workPath != null) {
            workDir = new File(workPath);
        } else {
            workDir = new File(currentDir, "work");
        }
        
        workDir.delete();
        context.setTempDirectory(workDir);
    }
}
