package com.k317h.restez;

import java.io.IOException;
import java.util.Iterator;
import java.util.Optional;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.k317h.restez.io.Request;
import com.k317h.restez.io.Response;
import com.k317h.restez.route.RouteMatch;

public class Application extends HttpServlet {
  private Router router;

  public Application(Router router) {
    this.router = router;
  }
  
  @Override
  protected void service(HttpServletRequest httpReq, HttpServletResponse httpRes) throws ServletException, IOException {
    try {
      Optional<RouteMatch> route = router.getRouteMatches()
          .stream()
          .filter(rm -> rm.matches(httpReq)).findFirst();
      
      if (route.isPresent()) {
        Request request = new Request(httpReq, route.get().parsePathParam(httpReq.getRequestURI()));
        Response response = new Response(httpRes);
        
        try {
          handleRouteMatch(request, response, route.get().getHandler(), route.get().getMiddleware().iterator());
        } catch (Exception e) {
          httpRes.setStatus(500);
        }
      } else {
        httpRes.setStatus(404);
        handleTopLevelMiddlewaresOnly(new Request(httpReq, null), new Response(httpRes), router.getMiddleware().iterator());
      }
    } catch(Exception e) {
      httpRes.setStatus(500);
    }
 
  }
  
  private void handleTopLevelMiddlewaresOnly(Request request, Response response, Iterator<Middleware> middlewares) throws Exception {
    if (middlewares.hasNext()) {
      middlewares.next().handle(request, response, (req, res) -> {
        handleTopLevelMiddlewaresOnly(req, res, middlewares);
      });
    }
  }
  
  private void handleRouteMatch(Request request, Response response, Handler h, Iterator<Middleware> middlewares) throws Exception {
    if (!middlewares.hasNext()) {
      h.handle(request, response);
    } else {
      middlewares.next().handle(request, response, (req, res) -> {
        handleRouteMatch(req, res, h, middlewares);
      });
    }
  }

  
}

@@ -101,16 +101,68 @@
 ptional;
+%0Aimport java.util.concurrent.atomic.AtomicReference;
 %0A%0Aimport
@@ -1331,39 +1331,26 @@
   handle
-TopLevelMiddlewaresOnly
+RouteMatch
 (new Req
@@ -1392,16 +1392,22 @@
 ttpRes),
+ null,
  router.
@@ -1519,324 +1519,8 @@
 %0A  %0A
-  private void handleTopLevelMiddlewaresOnly(Request request, Response response, Iterator%3CMiddleware%3E middlewares) throws Exception %7B%0A    if (middlewares.hasNext()) %7B%0A      middlewares.next().handle(request, response, (req, res) -%3E %7B%0A        handleTopLevelMiddlewaresOnly(req, res, middlewares);%0A      %7D);%0A    %7D%0A  %7D%0A
   %0A 
@@ -1660,11 +1660,9 @@
   if
- (!
+(
 midd
@@ -1686,56 +1686,8 @@
 ) %7B%0A
-      h.handle(request, response);%0A    %7D else %7B%0A
     
@@ -1811,16 +1811,78 @@
     %7D);%0A
+    %7D else if(null != h) %7B%0A      h.handle(request, response);%0A
     %7D%0A  

clean up some functions