package cz.muni.fi.lasaris.sbms;

import org.glassfish.grizzly.http.server.HttpHandler;
import org.glassfish.grizzly.http.server.HttpServer;
import org.glassfish.grizzly.http.server.NetworkListener;
import org.glassfish.grizzly.http.server.StaticHttpHandler;
import org.glassfish.grizzly.ssl.SSLContextConfigurator;
import org.glassfish.grizzly.ssl.SSLEngineConfigurator;

import cz.muni.fi.lasaris.sbms.semantics.model.TdbConnector;

import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

import javax.ws.rs.ext.RuntimeDelegate;

/**
 * Main class.
 *
 */
public class Main {

    /**
     * Starts Grizzly HTTP server exposing JAX-RS resources defined in this application.
     * @return Grizzly HTTP server.
     */
    
    private static cz.muni.fi.lasaris.sbms.semantics.Application semApp;
    private static cz.muni.fi.lasaris.sbms.data.Application dataApp;
    
    private static Properties prop;
    
    public static HttpServer startServer() throws IOException {
        
    	HttpServer g = new HttpServer(); 
    	
    	semApp = cz.muni.fi.lasaris.sbms.semantics.Application.getInstance();
		dataApp = cz.muni.fi.lasaris.sbms.data.Application.getInstance();
    	
		
		NetworkListener l = new NetworkListener("SemanticBMSlistener", 
				prop.getProperty("server.host"), 
				Integer.parseInt(prop.getProperty("server.port")));
		
		if(Boolean.parseBoolean(prop.getProperty("server.https"))) {
			System.out.println("HTTPS enabled");
			// https://www.sslshopper.com/article-how-to-create-a-self-signed-certificate-using-java-keytool.html
			// http://stackoverflow.com/questions/21098105/ssl-with-grizzly-and-jersey
			SSLContextConfigurator sslCon = new SSLContextConfigurator();
			sslCon.setKeyStoreFile(prop.getProperty("server.https.keystore.path")); // contains server keypair
		    sslCon.setKeyStoreType("JKS");
		    sslCon.setKeyStorePass(prop.getProperty("server.https.keystore.pass"));
			sslCon.setKeyPass(prop.getProperty("server.https.keystore.key"));
			l.setSecure(true);
			l.setSSLEngineConfig(new SSLEngineConfigurator(sslCon, false, false, false));
			
		}
		g.addListener(l);
		
		//semanticAPI
		g.getServerConfiguration().addHttpHandler(RuntimeDelegate.getInstance().createEndpoint(semApp, HttpHandler.class), prop.getProperty("server.semantics.api.uri"));
		//daAPI
		g.getServerConfiguration().addHttpHandler(RuntimeDelegate.getInstance().createEndpoint(dataApp, HttpHandler.class), prop.getProperty("server.data.api.uri"));
		
		// enable client
        StaticHttpHandler staticHttpHandler = new StaticHttpHandler(prop.getProperty("server.client.path"));
        staticHttpHandler.setFileCacheEnabled(false);
        g.getServerConfiguration().addHttpHandler(staticHttpHandler, prop.getProperty("server.client.uri"));
        g.start();

        return g;
    }

    /**
     * Main method.
     * @param args
     * @throws IOException
     */
    public static void main(String[] args) throws IOException {
    	prop = new Properties();
		try {
			String propFileName = "server.properties";

			InputStream inputStream = TdbConnector.class.getClassLoader().getResourceAsStream(propFileName);

			if (inputStream != null) {
				prop.load(inputStream);
			} else {
				System.err.println("Property file '" + propFileName + "' not found in the classpath");
				return;
			}
		} catch (Exception ex) {
			System.err.println(ex);
			System.err.println("Error occured when reading properties");
			return;
		}
    	
    	final HttpServer server = startServer();
        System.out.println(String.format("Jersey app started with WADLs available at "
                + "%sapplication.wadl\n%sapplication.wadl\nHit enter to stop it...", 
                prop.getProperty("server.semantics.api.uri"), prop.getProperty("server.data.api.uri")));
        System.in.read();
        semApp.close();
        server.shutdownNow();
    }
}

