package com.yihu.hos.core.httpclient;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.GzipDecompressingEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.ContentType;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

import java.io.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.zip.GZIPInputStream;

public class HttpHelper {
    public static String defaultHttpUrl;
    public static String clientId;
    public static String clientKey;
    public static String httpGateway;
    private static String defaultPropertiesPath = "config/http.properties";
    private static SSLConnectionSocketFactory defaultSSL;
    private static String defaultHttpUser;
    private static String defaultHttpPassword;

    static {
//        //默认配置
//        try {
//            Resource resource = new ClassPathResource(defaultPropertiesPath);
//            EncodedResource encRes = new EncodedResource(resource, "UTF-8");
//            Properties props = PropertiesLoaderUtils.loadProperties(encRes);
//
//            defaultHttpUrl = props.getProperty("httpUrl");
//            defaultHttpUser = props.getProperty("httpUser");
//            defaultHttpPassword = props.getProperty("httpPassword");
//            clientId = props.getProperty("clientId");
//            clientKey = props.getProperty("clientKey");
//            httpGateway = props.getProperty("httpGateway");
//            String sslKeystore = props.getProperty("sslKeystore");
//            String sslPassword = props.getProperty("sslPassword");
//            if (StringUtil.isEmpty(sslKeystore)) {
//                String home = System.getProperty("catalina.home").replace('\\', '/');
//                String homeUrl = home.substring(0, home.lastIndexOf('/') + 1);
//                // sslKeystore = homeUrl + "tomcat.keystore";
//                sslKeystore = "E://tomcat.keystore";
//            }
//            if (sslKeystore != null && sslKeystore.length() > 0 && sslPassword != null && sslPassword.length() > 0) {
//                SSLContext sslContext = SSLContexts.custom()
//                        .loadTrustMaterial(new File(sslKeystore), sslPassword.toCharArray(),
//                                new TrustSelfSignedStrategy())
//                        .build();
//                defaultSSL = new SSLConnectionSocketFactory(
//                        sslContext,
//                        new String[]{"TLSv1"},
//                        null,
//                        SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
//            }
//
//        } catch (Exception e) {
//            System.out.print(e.getMessage());
//        }

    }

    /**************************
     * Get方法
     ******************************************/
    public static HttpResponse get(String url) {
        return get(url, null, null);
    }

    public static HttpResponse get(String url, Map<String, Object> params) {
        return get(url, params, null);
    }

    public static HttpResponse get(String url, Map<String, Object> params, Map<String, Object> header) {
        if (url.startsWith("https")) {
            return get(url, params, header, defaultSSL);
        } else {
            //默认http不走ssl和用户密码
            return get(url, params, header, null, null, null);
        }
    }

    public static HttpResponse get(String url, Map<String, Object> params, Map<String, Object> header, Boolean isCheck) {
        if (isCheck) {
            return get(url, params, header, defaultSSL, defaultHttpUser, defaultHttpPassword);
        } else {
            return get(url, params, header, null, null, null);
        }
    }

    public static HttpResponse get(String url, Map<String, Object> params, Map<String, Object> header, SSLConnectionSocketFactory ssl) {
        return get(url, params, header, ssl, defaultHttpUser, defaultHttpPassword);
    }

    public static HttpResponse get(String url, Map<String, Object> params, Map<String, Object> header, SSLConnectionSocketFactory ssl, String user, String password) {

        return HttpClientUtil.request("GET", url, params, header, ssl, user, password);
    }

    /**************************
     * Post方法
     ******************************************/
    public static HttpResponse post(String url) {
        return post(url, null, null);
    }

    public static HttpResponse post(String url, Map<String, Object> params) {
        return post(url, params, null);
    }

    public static HttpResponse post(String url, Map<String, Object> params, Map<String, Object> header) {
        if (url.startsWith("https")) {
            return post(url, params, header, defaultSSL);
        } else {
            //默认http不走ssl和用户密码
            return post(url, params, header, null, null, null);
        }
    }

    public static HttpResponse post(String url, Map<String, Object> params, Map<String, Object> header, Boolean isCheck) {
        if (isCheck) {
            return post(url, params, header, defaultSSL, defaultHttpUser, defaultHttpPassword);
        } else {
            return post(url, params, header, null, null, null);
        }
    }

    public static HttpResponse post(String url, Map<String, Object> params, Map<String, Object> header, SSLConnectionSocketFactory ssl) {
        return post(url, params, header, ssl, defaultHttpUser, defaultHttpPassword);
    }

    public static HttpResponse post(String url, Map<String, Object> params, Map<String, Object> header, SSLConnectionSocketFactory ssl, String user, String password) {
        return HttpClientUtil.request("POST", url, params, header, ssl, user, password);
    }

    public static HttpResponse postFile(String url, List<NameValuePair> formParams, String filePath, Map<String, Object> header) {
        File file = new File(filePath);
        if (url.startsWith("https")) {
            return HttpClientUtil.postFile(url, file, formParams, defaultSSL, defaultHttpUser, defaultHttpPassword, header);
        } else {
            //默认http不走ssl和用户密码
            return HttpClientUtil.postFile(url, file, formParams, null, defaultHttpUser, defaultHttpPassword, header);
        }
    }

    public static HttpResponse postFile(String url, List<NameValuePair> formParams, File file, Map<String, Object> header) {
        if (url.startsWith("https")) {
            return HttpClientUtil.postFile(url, file, formParams, defaultSSL, defaultHttpUser, defaultHttpPassword, header);
        } else {
            //默认http不走ssl和用户密码
            return HttpClientUtil.postFile(url, file, formParams, null, defaultHttpUser, defaultHttpPassword, header);
        }
    }

    /**************************
     * Put方法
     ******************************************/
    public static HttpResponse put(String url) {
        return put(url, null, null);
    }

    public static HttpResponse put(String url, Map<String, Object> params) {
        return put(url, params, null);
    }

    public static HttpResponse put(String url, Map<String, Object> params, Map<String, Object> header) {
        if (url.startsWith("https")) {
            return put(url, params, header, defaultSSL);
        } else {
            //默认http不走ssl和用户密码
            return put(url, params, header, null, null, null);
        }
    }

    public static HttpResponse put(String url, Map<String, Object> params, Map<String, Object> header, Boolean isCheck) {
        if (isCheck) {
            return put(url, params, header, defaultSSL, defaultHttpUser, defaultHttpPassword);
        } else {
            return put(url, params, header, null, null, null);
        }
    }

    public static HttpResponse put(String url, Map<String, Object> params, Map<String, Object> header, SSLConnectionSocketFactory ssl) {
        return put(url, params, header, ssl, defaultHttpUser, defaultHttpPassword);
    }

    public static HttpResponse put(String url, Map<String, Object> params, Map<String, Object> header, SSLConnectionSocketFactory ssl, String user, String password) {

        return HttpClientUtil.request("PUT", url, params, header, ssl, user, password);
    }

    /**************************
     * Delete方法
     **************************************/
    public static HttpResponse delete(String url) {
        return delete(url, null, null);
    }

    public static HttpResponse delete(String url, Map<String, Object> params) {
        return delete(url, params, null);
    }

    public static HttpResponse delete(String url, Map<String, Object> params, Map<String, Object> header) {
        if (url.startsWith("https")) {
            return delete(url, params, header, defaultSSL);
        } else {
            //默认http不走ssl和用户密码
            return delete(url, params, header, null, null, null);
        }
    }

    public static HttpResponse delete(String url, Map<String, Object> params, Map<String, Object> header, Boolean isCheck) {
        if (isCheck) {
            return delete(url, params, header, defaultSSL, defaultHttpUser, defaultHttpPassword);
        } else {
            return delete(url, params, header, null, null, null);
        }
    }

    public static HttpResponse delete(String url, Map<String, Object> params, Map<String, Object> header, SSLConnectionSocketFactory ssl) {
        return delete(url, params, header, ssl, defaultHttpUser, defaultHttpPassword);
    }

    public static HttpResponse delete(String url, Map<String, Object> params, Map<String, Object> header, SSLConnectionSocketFactory ssl, String user, String password) {

        return HttpClientUtil.request("DELETE", url, params, header, ssl, user, password);
    }

    /**************************** 通过网关获取数据 ***************************************/
    /**
     * 通过网关获取数据
     */
    public static HttpResponse getByGateway(String code) {
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("api", code);
        params.put("param", "{}");
        return HttpClientUtil.request("GET", httpGateway, params, null, null, null, null);
    }

    /**
     * 通过网关获取数据
     */
    public static HttpResponse getByGateway(String code, Map<String, Object> queryParams) {
        Map<String, Object> params = new HashMap<String, Object>();
        ObjectMapper mapper = new ObjectMapper();
        params.put("api", code);
        String query = null;
        try {
            query = mapper.writeValueAsString(queryParams);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        params.put("param",query);
        return HttpClientUtil.request("GET", httpGateway, params, null, null, null, null);
    }


    public static String getWebPage(String url) {
        String returnString = "";
        HttpResponse re = new HttpResponse();
        CloseableHttpResponse response = null;
        CloseableHttpClient httpclient = HttpClients.custom()
                .setSSLSocketFactory(defaultSSL)
                .build();

        //设置请求信息
        try {
            HttpGet httpGet = new HttpGet(url);

            response = httpclient.execute(httpGet);
            String line;
            // 读取输入流的数据，并显示
            HttpEntity httpEntity = response.getEntity();
            Header header = response.getEntity().getContentEncoding();
            if (httpEntity.getContentLength() < 2147483647L) {            //EntityUtils无法处理ContentLength超过2147483647L的Entity
                if (header != null && "gzip".equals(header.getValue())) {
                    returnString = EntityUtils.toString(new GzipDecompressingEntity(httpEntity));
                } else {
                    returnString = EntityUtils.toString(httpEntity);
                }
            } else {
                InputStream in = httpEntity.getContent();
                if (header != null && "gzip".equals(header.getValue())) {
                    returnString = unZip(in, ContentType.getOrDefault(httpEntity).getCharset().toString());
                } else {
                    returnString = readInStreamToString(in, ContentType.getOrDefault(httpEntity).getCharset().toString());
                }
                if (in != null) {
                    in.close();
                }
            }
        } catch (Exception e) {
            re.setStatusCode(201);
            re.setBody(e.getMessage());
            e.printStackTrace();
        } finally {
            try {
                httpclient.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        System.out.println(returnString);
        return returnString;
    }

    /**
     * 解压服务器返回的gzip流
     *
     * @param in      抓取返回的InputStream流
     * @param charSet 页面内容编码
     * @return 页面内容的String格式
     * @throws IOException
     */
    private static String unZip(InputStream in, String charSet) throws IOException {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        GZIPInputStream gis = null;
        try {
            gis = new GZIPInputStream(in);
            byte[] _byte = new byte[1024];
            int len = 0;
            while ((len = gis.read(_byte)) != -1) {
                baos.write(_byte, 0, len);
            }
            String unzipString = new String(baos.toByteArray(), charSet);
            return unzipString;
        } finally {
            if (gis != null) {
                gis.close();
            }
            if (baos != null) {
                baos.close();
            }
        }
    }

    /**
     * 读取InputStream流
     *
     * @param in InputStream流
     * @return 从流中读取的String
     * @throws IOException
     */
    private static String readInStreamToString(InputStream in, String charSet) throws IOException {
        StringBuilder str = new StringBuilder();
        String line;
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(in, charSet));
        while ((line = bufferedReader.readLine()) != null) {
            str.append(line);
            str.append("\n");
        }
        if (bufferedReader != null) {
            bufferedReader.close();
        }
        return str.toString();
    }
}
