package de.ugoe.cs.autoquest.htmlmonitor;

import org.eclipse.jetty.servlets.CrossOriginFilter;
import org.mortbay.jetty.Handler;
import org.mortbay.jetty.Server;
import org.mortbay.jetty.servlet.Context;
import org.mortbay.jetty.servlet.FilterHolder;
import org.mortbay.jetty.servlet.ServletHolder;

import de.ugoe.cs.util.console.Console;

/**
 * <p>
 * this is the web server, that receives the client messages. It also provides the java script
 * that is used by the client via the URL /script/autoquest-htmlmonitor.js. It is initialized
 * with a port on which it shall listen, as well as a message listener to forward the received
 * messages to. Internally it starts a jetty web server with a single {@link HtmlMonitorServlet}
 * to receive the messages as well as a .
 * </p>
 * 
 * @author Patrick Harms
 */
class HtmlMonitorServer implements HtmlMonitorComponent {
    
    /**
     * the port to listen on
     */
    private int port;

    /**
     * the jetty web server used for receiving messages
     */
    private Server server;

    /**
     * the message listener to forward the messages to
     */
    private HtmlMonitorMessageListener messageListener;

    /**
     * <p>
     * initializes the server with the port to listen on and the message listener to forward
     * the messages to.
     * </p>
     *
     * @param port            the port to listen on
     * @param messageListener the message listener to forward the messages to
     */
    HtmlMonitorServer(int port, HtmlMonitorMessageListener messageListener) {
        this.port = port;
        this.messageListener = messageListener;
    }

    /* (non-Javadoc)
     * @see de.ugoe.cs.autoquest.htmlmonitor.HtmlMonitorComponent#init()
     */
    @Override
    public synchronized void init() {
        if (server != null) {
            throw new IllegalStateException("already initialized. First call stop()");
        }

        server = new Server(port);
        
        /*
        // the following code can be used to support SSL directly
        server = new Server();
        
        SslSocketConnector connector = new SslSocketConnector();
        connector.setPort(port);
        connector.setKeystore("data/keystore");
        connector.setPassword("123456");
        connector.setKeyPassword("123456");
        connector.setTruststore("data/keystore");
        connector.setTrustPassword("123456");
        server.addConnector(connector);*/

        Context root = new Context(server, "/", Context.SESSIONS);

        HtmlMonitorServlet servlet = new HtmlMonitorServlet(messageListener);
        ServletHolder servletHolder = new ServletHolder(servlet);
        root.addServlet(servletHolder, "/*");
        
        CrossOriginFilter filter = new CrossOriginFilter();
        FilterHolder filterHolder = new FilterHolder(filter);
        filterHolder.setInitParameter("allowedOrigins", "*");
        filterHolder.setInitParameter("allowedMethods", "GET,POST");
        root.addFilter(filterHolder, "/*", Handler.ALL);
    }

    /* (non-Javadoc)
     * @see de.ugoe.cs.autoquest.htmlmonitor.HtmlMonitorComponent#start()
     */
    @Override
    public synchronized void start() throws HtmlMonitorException {
        if (server == null) {
            throw new IllegalStateException("server not initialized yet. First call init()");
        }
        
        try {
            server.start();
        }
        catch (Exception e) {
            throw new HtmlMonitorException("could not start server", e);
        }
    }


    /* (non-Javadoc)
     * @see de.ugoe.cs.autoquest.htmlmonitor.HtmlMonitorComponent#stop()
     */
    @Override
    public synchronized void stop() {
        try {
            if (server != null) {
                server.stop();
            }
        }
        catch (Exception e) {
            Console.printerrln("could not stop HTML monitor server: " + e.getMessage());
            Console.logException(e);
        }
    }

}
