package com.fri.http.rest.server;

import com.fri.http.rest.config.YXDefaultServerConfig;
import com.fri.http.rest.connections.HttpClientPool;
import com.fri.http.rest.logging.YXLogging;
import com.fri.http.rest.resources.YXRestResources;
import com.fri.http.rest.resources.CTIDRestResources;
import com.fri.http.rest.resources.YXServerStatus;
import com.fri.http.rest.utils.TimeUtils;

import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;

import org.eclipse.jetty.util.thread.QueuedThreadPool;

import java.io.IOException;

import java.util.logging.Level;
import java.util.logging.Logger;


/**
 * Created by zhangdahui on 4/27/17.
 */
public class YXHttpRestServer {

    public static Server jettyServer = null;

    public static void main(String[] args) throws IOException {


        Logger logger = YXLogging.CreateLogger(YXDefaultServerConfig.LOGGING_NAME_HTTP_SERVER, Level.ALL);
        YXLogging.CreateLogger(YXDefaultServerConfig.LOGGING_NAME_REQUEST_SERVER, Level.ALL);
        YXLogging.CreateLogger(YXDefaultServerConfig.LOGGING_NAME_RESPONSE_SERVER, Level.ALL);



        logger.info("-----------------------------------------------------------------------");
        logger.info("|          YingXin Application Server Framework                       |");
        logger.info("|          YingXin " + YXDefaultServerConfig.APPLICATION_NAME + "        |");
        logger.info("-----------------------------------------------------------------------");

        //Server Thread Pool
        QueuedThreadPool httpThreadPool = new QueuedThreadPool();
        httpThreadPool.setMaxThreads(YXDefaultServerConfig.SERVER_THREAD_POOL_COUNT);

        logger.info("-----------------------------------------------------------------------");
        logger.info(" Initialize Jetty HTTP Server:" + TimeUtils.currentDateAsString());

        //Build HttpServer
        jettyServer = new Server(httpThreadPool);
        logger.info("|- SERVER_HOST = " + YXDefaultServerConfig.SERVER_HOST);
        logger.info("|- SERVER_THREAD_POOL_COUNT = " + YXDefaultServerConfig.SERVER_THREAD_POOL_COUNT);

        /*
        NCSARequestLog requestLog = new NCSARequestLog(YXLogging.getJettyServerLoggerName());
        requestLog.setAppend(true);
        requestLog.setExtended(false);
        requestLog.setLogLatency(true);
        requestLog.setRetainDays(YXDefaultServerConfig.LOGGING_HTTP_REQUEST_REMAIN_DAYS);
        jettyServer.setRequestLog(requestLog);
         */

        logger.info("-----------------------------------------------------------------------");
        logger.info(" Create Http Rest Service Connector");

        ServerConnector httpConnector = new ServerConnector(jettyServer);
        httpConnector.setHost(YXDefaultServerConfig.SERVER_HOST);  //Host IP & Address
        httpConnector.setPort(YXDefaultServerConfig.SERVER_PORT);  //Port
        httpConnector.setIdleTimeout(YXDefaultServerConfig.SERVER_IDLE_TIMEOUT); //Connection idle time out
        httpConnector.setStopTimeout(YXDefaultServerConfig.SERVER_STOP_TIMEOUT);
        httpConnector.setAcceptQueueSize(YXDefaultServerConfig.SERVER_ACCEPT_QUEUE_SIZE);

        logger.info("|- SERVER_PORT = " + YXDefaultServerConfig.SERVER_PORT);
        logger.info("|- SERVER_IDLE_TIMEOUT = " + YXDefaultServerConfig.SERVER_IDLE_TIMEOUT);
        logger.info("|- SERVER_STOP_TIMEOUT = " + YXDefaultServerConfig.SERVER_STOP_TIMEOUT);
        logger.info("|- SERVER_ACCEPT_QUEUE_SIZE = " + YXDefaultServerConfig.SERVER_ACCEPT_QUEUE_SIZE);

        logger.info("-----------------------------------------------------------------------");
        logger.info(" Create Http Monitor Service Connector");

        ServerConnector httpMonitorConnector = new ServerConnector(jettyServer);
        httpMonitorConnector.setHost(YXDefaultServerConfig.SERVER_HOST);  //Host IP & Address
        httpMonitorConnector.setPort(YXDefaultServerConfig.SERVER_MONITOR_PORT);  //Port
        logger.info("|- SERVER_MONITOR_PORT = " + YXDefaultServerConfig.SERVER_MONITOR_PORT);



        //Build Context
        ServletContextHandler context = new ServletContextHandler(ServletContextHandler.NO_SESSIONS);
        context.setContextPath("/");

        //The following code show how to add two or more rest services in http server
        ServletHolder restServlet = context.addServlet(org.glassfish.jersey.servlet.ServletContainer.class, YXDefaultServerConfig.SERVER_REST_ROOT_PATH + "/*");
        restServlet.setInitOrder(0);
        restServlet.setInitParameter("jersey.config.server.provider.classnames", YXRestResources.class.getCanonicalName());

        logger.info("|- Rest Resource Name = " + YXRestResources.class.getCanonicalName());
        logger.info("|- Rest Resource Root = " + YXDefaultServerConfig.SERVER_REST_ROOT_PATH + "/*");

        ServletHolder monitorServlet = context.addServlet(org.glassfish.jersey.servlet.ServletContainer.class, YXDefaultServerConfig.SERVER_MONITOR_PATH + "/*");
        monitorServlet.setInitOrder(1);
        monitorServlet.setInitParameter("jersey.config.server.provider.classnames", YXServerStatus.class.getCanonicalName());
        logger.info("|- Rest Monitor Name = " + YXServerStatus.class.getCanonicalName());
        logger.info("|- Rest Monitor Root = " + YXDefaultServerConfig.SERVER_MONITOR_PATH + "/*");

        ServletHolder identityServlet = context.addServlet(org.glassfish.jersey.servlet.ServletContainer.class, YXDefaultServerConfig.SERVER_CTID_IDENTITY_PATH + "/*");
        identityServlet.setInitOrder(2);
        identityServlet.setInitParameter("jersey.config.server.provider.classnames", CTIDRestResources.class.getCanonicalName());
        logger.info("|- Rest Monitor Name = " + CTIDRestResources.class.getCanonicalName());
        logger.info("|- Rest Monitor Root = " + YXDefaultServerConfig.SERVER_CTID_IDENTITY_PATH + "/*");


        jettyServer.addConnector(httpConnector);
        jettyServer.addConnector(httpMonitorConnector);
        jettyServer.setHandler(context);

        // Start Server
        try {
            jettyServer.start();

            logger.info("-----------------------------------------------------------------------");
            logger.info(" Init HttpClient Link Pool");
            HttpClientPool.initConnectionPool();

        } catch (Exception e) {
            logger.info("Exception:" + e.getMessage());
        } finally {
            try {
                Thread.sleep(1000);
                if (jettyServer.isRunning()) {
                    logger.info("Starting Succeeded.");
                    jettyServer.join();
                } else {
                    logger.info("Starting Failed");
                    jettyServer.stop();
                }
            } catch (Exception e) {
                logger.info("Exception:" + e.getMessage());
            }
        }
    }
}
