package org.codelogger.utils.component;

import static com.google.common.collect.Maps.newHashMap;
import static org.codelogger.utils.MapUtils.isNotEmpty;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Map;
import java.util.Map.Entry;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;

import org.apache.http.Header;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.ssl.TrustStrategy;
import org.codelogger.utils.IOUtils;
import org.codelogger.utils.beans.HttpRequest;
import org.codelogger.utils.beans.HttpResponse;
import org.codelogger.utils.exceptions.HttpException;

public class HttpDownloader {

  public HttpResponse doGet(final String url) {

    HttpRequest httpRequest = new HttpRequest(url);
    return doGet(httpRequest);
  }

  public HttpResponse doGet(final String url, final Map<String, String> headers) {

    HttpRequest httpRequest = new HttpRequest(url, headers);
    return doGet(httpRequest);
  }

  public HttpResponse doGet(final HttpRequest httpRequest) {

    HttpGet httpPost = new HttpGet(httpRequest.getUrl());
    CloseableHttpClient httpClient = null;
    CloseableHttpResponse httpResponse = null;
    try {
      if (isNotEmpty(httpRequest.getHeaders())) {
        for (Entry<String, String> entry : httpRequest.getHeaders().entrySet()) {
          httpPost.addHeader(entry.getKey(), entry.getValue());
        }
      }
      httpClient = httpRequest.isIgnoreSslCertificate() ? getIgnoreSslCertificateHttpClient()
        : getHttpClient();
      httpResponse = httpClient.execute(httpPost);
      return parseHttpResponse(httpResponse);
    } catch (Exception e) {
      throw new HttpException(e);
    } finally {
      try {
        if (httpResponse != null) {
          httpResponse.close();
        }
      } catch (IOException e) {
      }
      try {
        if (httpClient != null) {
          httpClient.close();
        }
      } catch (IOException e) {
      }
    }
  }

  public HttpResponse doPost(final String url, final Map<String, String> headers, final String body) {

    try {
      HttpRequest httpRequest = new HttpRequest(url, headers, new StringEntity(body));
      return doPost(httpRequest);
    } catch (UnsupportedEncodingException e) {
      throw new HttpException("Encoding failed.", e);
    }

  }

  public HttpResponse doPost(final HttpRequest httpRequest) {

    HttpPost httpPost = new HttpPost(httpRequest.getUrl());
    CloseableHttpClient httpClient = null;
    CloseableHttpResponse httpResponse = null;
    try {
      if (isNotEmpty(httpRequest.getHeaders())) {
        for (Entry<String, String> entry : httpRequest.getHeaders().entrySet()) {
          httpPost.addHeader(entry.getKey(), entry.getValue());
        }
      }
      if (httpRequest.getHttpEntity() != null) {
        httpPost.setEntity(httpRequest.getHttpEntity());
      }
      httpClient = getHttpClient();
      httpResponse = httpClient.execute(httpPost);
      return parseHttpResponse(httpResponse);
    } catch (Exception e) {
      throw new HttpException(e);
    } finally {
      try {
        if (httpResponse != null) {
          httpResponse.close();
        }
      } catch (IOException e) {
      }
      try {
        if (httpClient != null) {
          httpClient.close();
        }
      } catch (IOException e) {
      }
    }
  }

  private HttpResponse parseHttpResponse(final CloseableHttpResponse httpResponse)
    throws IOException {

    int statusCode = httpResponse.getStatusLine().getStatusCode();
    Map<String, String> responseHeaders = newHashMap();
    for (Header header : httpResponse.getAllHeaders()) {
      responseHeaders.put(header.getName(), header.getValue());
    }
    byte[] content = IOUtils.getBytes(httpResponse.getEntity().getContent());
    return new HttpResponse(statusCode, responseHeaders, content);
  }

  private CloseableHttpClient getHttpClient() {

    HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
    CloseableHttpClient httpClient = httpClientBuilder.build();
    return httpClient;
  }

  public CloseableHttpClient getIgnoreSslCertificateHttpClient() {

    HttpClientBuilder b = HttpClientBuilder.create();
    SSLContext sslContext = null;;
    try {
      sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {

        @Override
        public boolean isTrusted(final X509Certificate[] arg0, final String arg1)
          throws CertificateException {

          return true;
        }
      }).build();
    } catch (Exception e) {
      throw new HttpException("can not create http client.", e);
    }
    b.setSslcontext(sslContext);
    HostnameVerifier hostnameVerifier = new NoopHostnameVerifier();
    SSLConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(sslContext,
      hostnameVerifier);
    Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder
      .<ConnectionSocketFactory> create()
      .register("http", PlainConnectionSocketFactory.getSocketFactory())
      .register("https", sslSocketFactory).build();
    PoolingHttpClientConnectionManager connMgr = new PoolingHttpClientConnectionManager(
      socketFactoryRegistry);
    b.setConnectionManager(connMgr);
    return b.build();
  }
}

@@ -367,47 +367,8 @@
 y;%0A%0A
-import javax.net.ssl.HostnameVerifier;%0A
 impo
@@ -3671,16 +3671,93 @@
 Client =
+ httpRequest.isIgnoreSslCertificate() ? getIgnoreSslCertificateHttpClient() :
  getHttp
@@ -5000,62 +5000,8 @@
  %7B%0A%0A
-    HttpClientBuilder b = HttpClientBuilder.create();%0A
     
@@ -5031,16 +5031,16 @@
  null;;%0A
+
     try 
@@ -5426,109 +5426,8 @@
   %7D%0A
-    b.setSslcontext(sslContext);%0A    HostnameVerifier hostnameVerifier = new NoopHostnameVerifier();%0A
     
@@ -5521,17 +5521,25 @@
 ,%0A      
-h
+new NoopH
 ostnameV
@@ -5545,16 +5545,18 @@
 Verifier
+()
 );%0A    R
@@ -5918,17 +5918,75 @@
 y);%0A    
-b
+return HttpClientBuilder.create().setSslcontext(sslContext)
 .setConn
@@ -6011,22 +6011,15 @@
 Mgr)
-;
 %0A    
-return b
+  
 .bui

update httpDownloader post method