package fr.synchrotron.soleil.ica.ci.service.multirepoproxy;


import fr.synchrotron.soleil.ica.proxy.midlleware.HttpEndpointInfo;
import fr.synchrotron.soleil.ica.proxy.midlleware.MiddlewareContext;
import fr.synchrotron.soleil.ica.proxy.midlleware.ProxyRequestType;
import fr.synchrotron.soleil.ica.proxy.midlleware.ProxyService;
import fr.synchrotron.soleil.ica.proxy.midlleware.response.DefaultClientResponseHandler;
import io.netty.handler.codec.http.HttpResponseStatus;
import org.vertx.java.core.Handler;
import org.vertx.java.core.Vertx;
import org.vertx.java.core.http.HttpClient;
import org.vertx.java.core.http.HttpClientRequest;
import org.vertx.java.core.http.HttpClientResponse;
import org.vertx.java.core.http.HttpServerRequest;
import org.vertx.java.core.logging.Logger;
import org.vertx.java.core.logging.impl.LoggerFactory;

import java.nio.channels.UnresolvedAddressException;
import java.util.List;

/**
 * @author Gregory Boissinot
 */
public class MutltiGETHandler implements Handler<HttpServerRequest> {

    private static final Logger LOG = LoggerFactory.getLogger(MutltiGETHandler.class);

    private final Vertx vertx;
    private final RepositoryScanner repositoryScanner;
    private final String proxyPath;

    public MutltiGETHandler(Vertx vertx, String proxyPath, List<HttpEndpointInfo> repos) {
        this.vertx = vertx;

        if (repos == null || repos.size() == 0) {
            throw new IllegalArgumentException("repos");
        }
        this.repositoryScanner = new RepositoryScanner(repos);
        this.proxyPath = proxyPath;
    }

    @Override
    public void handle(final HttpServerRequest request) {
        processRepository(request, 0);
    }

    private void processRepository(final HttpServerRequest request,
                                   final int repoIndex) {

        if (repositoryScanner.isLastRepo(repoIndex)) {
            request.response().setStatusCode(HttpResponseStatus.NOT_FOUND.code());
            request.response().setStatusMessage("Artifact NOT FOUND");
            request.response().end();
            return;
        }

        System.out.println("Trying to download " + request.path() + "from " + repositoryScanner.getRepoFromIndex(repoIndex));

        final HttpEndpointInfo httpEndpointInfo = repositoryScanner.getRepoFromIndex(repoIndex);

        //We have here a particular situation (reverse proxy).
        //We create an HttpClient object for each server request
        //It is supposed to be lightweight
        final HttpClient httpClient = vertx.createHttpClient()
                .setHost(httpEndpointInfo.getHost())
                .setPort(httpEndpointInfo.getPort())
                .setKeepAlive(false);

        //Sample use case: timeout on client request
        request.exceptionHandler(new Handler<Throwable>() {
            @Override
            public void handle(Throwable t) {
                LOG.error("Severe error during request processing :", t);
                request.response().setStatusCode(HttpResponseStatus.INTERNAL_SERVER_ERROR.code());
                request.response().end();
                httpClient.close();
            }
        });


       final MiddlewareContext context = new MiddlewareContext(vertx, proxyPath, request, httpClient, httpEndpointInfo, ProxyRequestType.ANY);

        HttpClientRequest vertxRequest = httpClient.head(context.getClientRequestPath(), new Handler<HttpClientResponse>() {
            @Override
            public void handle(HttpClientResponse clientResponse) {

                switch (clientResponse.statusCode()) {
                    case 200:
                        if ("HEAD".equals(request.method())) {
                            request.response().setStatusCode(clientResponse.statusCode());
                            request.response().headers().set(clientResponse.headers());
                            clientResponse.endHandler(new Handler<Void>() {
                                public void handle(Void event) {
                                    request.response().end();
                                    httpClient.close();
                                }
                            });
                        } else {
                            ProxyService proxyService = new ProxyService();
                            HttpClientRequest clientRequest = proxyService.getClientRequest(context, new DefaultClientResponseHandler(context).get());
                            clientRequest.headers().set(request.headers());
                            clientRequest.exceptionHandler(new Handler<Throwable>() {
                                @Override
                                public void handle(Throwable throwable) {
                                    ProxyService proxyService = new ProxyService();
                                    proxyService.sendError(request, throwable);
                                    httpClient.close();
                                }
                            });
                            clientRequest.end();
                        }
                        break;
                    case 301:
                    case 404:
                        httpClient.close();
                        processRepository(request, repositoryScanner.getNextIndex(repoIndex));
                        break;
                    default:
                        request.response().setStatusCode(clientResponse.statusCode());
                        request.response().setStatusMessage(clientResponse.statusMessage());
                        request.response().end();
                        httpClient.close();
                        break;
                }
            }
        });

        vertxRequest.exceptionHandler(new Handler<Throwable>() {
            @Override
            public void handle(Throwable throwable) {
                if (isUnreasolvedHost(throwable)) {
                    processRepository(request, repositoryScanner.getNextIndex(repoIndex));
                } else {
                    ProxyService proxyService = new ProxyService();
                    proxyService.sendError(request, throwable);
                }
            }

            private boolean isUnreasolvedHost(Throwable throwable) {
                return throwable.getClass().equals(UnresolvedAddressException.class);
            }
        });

        vertxRequest.end();
    }

}

@@ -2110,26 +2110,16 @@
     
-System.out.println
+LOG.info
 (%22Tr
@@ -2704,69 +2704,33 @@
     
-//Sample use case: timeout on client request%0A        request.
+final Handler%3CThrowable%3E 
 exce
@@ -2733,33 +2733,35 @@
 exceptionHandler
-(
+ = 
 new Handler%3CThro
@@ -2835,16 +2835,24 @@
 owable t
+hrowable
 ) %7B%0A    
@@ -2867,271 +2867,395 @@
     
-LOG.error(%22Severe error during request processing :%22, t);%0A                request.response().setStatusCode(HttpResponseStatus.INTERNAL_SERVER_ERROR.code());%0A                request.response().end();%0A                httpClient.close();%0A            %7D%0A        %7D);%0A
+ProxyService proxyService = new ProxyService();%0A                proxyService.sendError(request, throwable);%0A                if (httpClient != null) %7B%0A                    httpClient.close();%0A                %7D%0A            %7D%0A        %7D;%0A        request.exceptionHandler(exceptionHandler); //Sample use case: timeout on client request%0A        httpClient.exceptionHandler(exceptionHandler);
 %0A%0A
+ 
     
@@ -3420,21 +3420,22 @@
 Request 
-vertx
+client
 Request 
@@ -4410,33 +4410,36 @@
 tpClientRequest 
-c
+getC
 lientRequest = p
@@ -4546,33 +4546,36 @@
                 
-c
+getC
 lientRequest.hea
@@ -4625,33 +4625,36 @@
                 
-c
+getC
 lientRequest.exc
@@ -4671,482 +4671,123 @@
 ler(
-new Handler%3CThrowable%3E() %7B%0A                                @Override%0A                                public void handle(Throwable throwable) %7B%0A                                    ProxyService proxyService = new ProxyService();%0A                                    proxyService.sendError(request, throwable);%0A                                    httpClient.close();%0A                                %7D%0A                            %7D);%0A                            clientRequest.end
+exceptionHandler);%0A                            getClientRequest.end();%0A                            httpClient.close
 ();%0A
@@ -5452,37 +5452,38 @@
    %7D);%0A%0A        
-vertx
+client
 Request.exceptio
@@ -6117,21 +6117,22 @@
         
-vertx
+client
 Request.

Fix httpClient.close()