package com.progressoft.brix.domino.api.server;

import com.progressoft.brix.domino.api.server.config.HttpServerConfigurator;
import com.progressoft.brix.domino.api.server.config.ServerConfigurationLoader;
import com.progressoft.brix.domino.api.server.config.VertxConfiguration;
import com.progressoft.brix.domino.api.server.entrypoint.VertxContext;
import com.progressoft.brix.domino.service.discovery.VertxServiceDiscovery;
import io.vertx.core.AsyncResult;
import io.vertx.core.Future;
import io.vertx.core.Vertx;
import io.vertx.core.http.HttpServerOptions;
import io.vertx.core.json.JsonObject;
import io.vertx.ext.web.Router;
import io.vertx.ext.web.handler.StaticHandler;

import java.util.ServiceLoader;

public class DominoLoader {

    public static final int DEFAULT_PORT = 8080;
    public static final String HTTP_PORT_KEY = "http.port";

    private final Vertx vertx;
    private final Router router;
    private final JsonObject config;

    public DominoLoader(Vertx vertx, Router router, JsonObject config) {
        this.vertx = vertx;
        this.router = router;
        this.config = config;
    }

    public void start(){
        ImmutableHttpServerOptions immutableHttpServerOptions=new ImmutableHttpServerOptions();
        VertxContext vertxContext = initializeContext(immutableHttpServerOptions);

        Future<HttpServerOptions> future = Future.future();
        future.setHandler(options -> {
            onHttpServerConfigurationCompleted(immutableHttpServerOptions, vertxContext, options);
        });

        configureHttpServer(vertxContext, future);
    }

    private VertxContext initializeContext(ImmutableHttpServerOptions immutableHttpServerOptions) {
        return VertxContext.VertxContextBuilder.vertx(vertx)
                .router(router)
                .serverConfiguration(new VertxConfiguration(config))
                .httpServerOptions(immutableHttpServerOptions)
                .vertxServiceDiscovery(new VertxServiceDiscovery(vertx)).build();
    }

    private void onHttpServerConfigurationCompleted(ImmutableHttpServerOptions immutableHttpServerOptions,
                                                    VertxContext vertxContext, AsyncResult<HttpServerOptions> options) {
        immutableHttpServerOptions.init(options.result(), options.result().getPort(), options.result().getHost());
        new ServerConfigurationLoader(vertxContext).loadModules();
        router.route().handler(StaticHandler.create());
        if (options.result().isSsl())
            addSecurityHeadersHandler(router);
        vertx.createHttpServer(options.result()).requestHandler(router::accept)
                .listen(options.result().getPort());
    }

    private void addSecurityHeadersHandler(Router router) {
        router.route().handler(ctx -> {
            ctx.response()
                    // do not allow proxies to cache the data
                    .putHeader("Cache-Control", "no-store, no-cache")
                    // prevents Internet Explorer from MIME - sniffing a
                    // response away from the declared content-type
                    .putHeader("X-Content-Type-Options", "nosniff")
                    // Strict HTTPS (for about ~6Months)
                    .putHeader("Strict-Transport-Security", "max-age=" + 15768000)
                    // IE8+ do not allow opening of attachments in the context of this resource
                    .putHeader("X-Download-Options", "noopen")
                    // enable XSS for IE
                    .putHeader("X-XSS-Protection", "1; mode=block")
                    // deny frames
                    .putHeader("X-FRAME-OPTIONS", "DENY");
            ctx.next();
        });
    }

    private void configureHttpServer(VertxContext vertxContext, Future<HttpServerOptions> future) {
        HttpServerOptions httpServerOptions = new HttpServerOptions();
        httpServerOptions.setPort(vertxContext.config().getInteger(HTTP_PORT_KEY, DEFAULT_PORT));
        ServiceLoader<HttpServerConfigurator> configurators = ServiceLoader.load(HttpServerConfigurator.class);
        configurators.forEach(c -> c.configureHttpServer(vertxContext, httpServerOptions));
        httpServerOptions.setCompressionSupported(true);

        future.complete(httpServerOptions);
    }

}

@@ -503,21 +503,89 @@
 tx.core.
-Vertx
+Handler;%0Aimport io.vertx.core.Vertx;%0Aimport io.vertx.core.http.HttpServer
 ;%0Aimport
@@ -661,16 +661,97 @@
 Object;%0A
+import io.vertx.core.logging.Logger;%0Aimport io.vertx.core.logging.LoggerFactory;%0A
 import i
@@ -884,16 +884,102 @@
 ader %7B%0A%0A
+    private static final Logger LOGGER= LoggerFactory.getLogger(DominoLoader.class);%0A%0A
     publ
@@ -1182,16 +1182,17 @@
 onfig;%0A%0A
+%0A
     publ
@@ -1373,16 +1373,69 @@
 d start(
+Handler%3CAsyncResult%3CHttpServer%3E%3E serverStartupHandler
 )%7B%0A     
@@ -1705,30 +1705,16 @@
 tions -%3E
- %7B%0A           
  onHttpS
@@ -1790,28 +1790,39 @@
  options
-);%0A        %7D
+, serverStartupHandler)
 );%0A%0A    
@@ -1867,32 +1867,309 @@
 future);%0A    %7D%0A%0A
+    public void start()%7B%0A        start(event -%3E %7B%0A            if(event.succeeded())%0A                LOGGER.info(%22Server started on port : %22+event.result().actualPort());%0A            else%0A                LOGGER.error(%22Failed to start server%22, event.cause());%0A        %7D);%0A    %7D%0A%0A
     private Vert
@@ -2786,24 +2786,79 @@
 ons%3E options
+, Handler%3CAsyncResult%3CHttpServer%3E%3E serverStartupHandler
 ) %7B%0A        
@@ -3298,24 +3298,46 @@
 ().getPort()
+, serverStartupHandler
 );%0A    %7D%0A%0A  
@@ -4928,11 +4928,10 @@
 ;%0A    %7D%0A
-%0A
 %7D%0A

add server startup handler