package com.stubbornjava.examples.undertow.handlebars;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.base.Strings;
import com.stubbornjava.common.SimpleResponse;
import com.stubbornjava.common.undertow.Exchange;
import com.stubbornjava.common.undertow.SimpleServer;
import com.stubbornjava.common.undertow.handlers.CustomHandlers;
import com.stubbornjava.undertow.handlers.MiddlewareBuilder;

import io.undertow.server.HttpHandler;
import io.undertow.server.HttpServerExchange;
import io.undertow.server.RoutingHandler;
import io.undertow.server.handlers.BlockingHandler;

public class WebpackServer {
    private static final Logger log = LoggerFactory.getLogger(WebpackServer.class);

    // {{start:routes}}
    // Simple not found 404 page
    public static void notFound(HttpServerExchange exchange) {
        exchange.setStatusCode(404);
        Exchange.body().sendHtmlTemplate(exchange, "static/templates/src/notfound", SimpleResponse.create());
    }

    // Default error page when something unexpected happens
    public static void error(HttpServerExchange exchange) {
        exchange.setStatusCode(500);
        Exchange.body().sendHtmlTemplate(exchange, "static/templates/src/serverError", SimpleResponse.create());
    }

    // Render homepage
    public static void home(HttpServerExchange exchange) {
        exception(exchange);
        Exchange.body().sendHtmlTemplate(exchange, "static/templates/src/home", SimpleResponse.create());
    }

    // Render hello {name} page based on the name query param.
    public static void hello(HttpServerExchange exchange) {
        exception(exchange);
        String name = Exchange.queryParams()
                              .queryParam(exchange, "name")
                              .filter(s -> !Strings.isNullOrEmpty(s))
                              .orElse("world");
        SimpleResponse response = SimpleResponse.create()
                                                .with("name", name);
        Exchange.body().sendHtmlTemplate(exchange, "static/templates/src/hello", response);
    }

    // Helper function to forcibly throw an exception whenever the query
    // parameter exception=true
    private static void exception(HttpServerExchange exchange) {
        if (Exchange.queryParams().queryParamAsBoolean(exchange, "exception").orElse(false)) {
            throw new RuntimeException("Poorly Named Exception!!!");
        }
    }
    // {{end:routes}}

    // {{start:server}}
    // We are currently handling all exceptions the same way
    private static HttpHandler exceptionHandler(HttpHandler next) {
        return CustomHandlers.exception(next)
           .addExceptionHandler(Throwable.class, WebpackServer::error);
    }

    // Useful middleware
    private static HttpHandler wrapWithMiddleware(HttpHandler handler) {
        return MiddlewareBuilder.begin(BlockingHandler::new)
                                .next(CustomHandlers::gzip)
                                .next(ex -> CustomHandlers.accessLog(ex, log))
                                .next(CustomHandlers::statusCodeMetrics)
                                .next(WebpackServer::exceptionHandler)
                                .complete(handler);
    }

    // Simple routing, anything not matching a route will fall back
    // to the not found handler.
    private static final HttpHandler ROUTES = new RoutingHandler()
        .get("/", WebpackServer::home)
        .get("/hello", WebpackServer::hello)
        .get("/static*", CustomHandlers.resource(""))
        .setFallbackHandler(WebpackServer::notFound)
    ;

    public static void main(String[] args) {
        SimpleServer server = SimpleServer.simpleServer(wrapWithMiddleware(ROUTES));
        server.start();
    }
    // {{end:server}}
}

@@ -49,16 +49,95 @@
 ebars;%0A%0A
+import static com.stubbornjava.common.undertow.handlers.CustomHandlers.timed;%0A%0A
 import o
@@ -3510,16 +3510,30 @@
 get(%22/%22,
+ timed(%22home%22,
  Webpack
@@ -3545,16 +3545,17 @@
 r::home)
+)
 %0A       
@@ -3569,16 +3569,31 @@
 /hello%22,
+ timed(%22hello%22,
  Webpack
@@ -3606,16 +3606,17 @@
 ::hello)
+)
 %0A       
@@ -3632,16 +3632,32 @@
 tatic*%22,
+ timed(%22static%22,
  CustomH
@@ -3677,16 +3677,17 @@
 rce(%22%22))
+)
 %0A       
@@ -3707,16 +3707,34 @@
 Handler(
+timed(%22notfound%22, 
 WebpackS
@@ -3749,16 +3749,17 @@
 otFound)
+)
 %0A    ;%0A%0A

Add metrics