package cn.com.ctop.common.module.utils;

import com.alibaba.fastjson.JSONObject;
import com.google.gson.Gson;
import lombok.extern.slf4j.Slf4j;
import org.apache.fontbox.ttf.CmapSubtable;
import org.apache.fontbox.ttf.GlyphData;
import org.apache.fontbox.ttf.TTFParser;
import org.apache.fontbox.ttf.TrueTypeFont;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.client.CookieStore;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.CookieSpecs;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.util.EntityUtils;

import javax.net.ssl.SSLContext;
import java.io.*;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.*;

@Slf4j
public class HttpUtils2 {
    public static CookieStore cookieStore = new BasicCookieStore();
    /**
     * setProxy(new HttpHost("106.125.239.179", 4245))
     */
    public static Map<String, Map<String, String>> fontsMap = new HashMap<>();
    public static String USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36";

    public static CloseableHttpClient createSSLClientDefault() {
        try {
            SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {
                //信任所有证书
                @Override
                public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
                    return true;
                }
            }).build();
            RequestConfig globalConfig = RequestConfig.custom().setConnectTimeout(30000).setSocketTimeout(30000).setCookieSpec(CookieSpecs.STANDARD).build();
            SSLConnectionSocketFactory sslFactory = new SSLConnectionSocketFactory(sslContext);
            return HttpClients.custom().setDefaultCookieStore(cookieStore).setDefaultRequestConfig(globalConfig).setConnectionReuseStrategy((response, context) -> false).setSSLSocketFactory(sslFactory).build();
        } catch (Exception e) {
            log.error("处理Https证书异常", e);
        }
        return HttpClients.createDefault();
    }

    public static CloseableHttpClient createSSLClientDefault(CookieStore setCookieStore) {
        try {
            SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {
                //信任所有证书
                @Override
                public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
                    return true;
                }
            }).build();
            RequestConfig globalConfig = RequestConfig.custom().setConnectTimeout(30000).setSocketTimeout(30000).setCookieSpec(CookieSpecs.STANDARD).build();
            SSLConnectionSocketFactory sslFactory = new SSLConnectionSocketFactory(sslContext);
            return HttpClients.custom().setDefaultCookieStore(setCookieStore).setDefaultRequestConfig(globalConfig).setConnectionReuseStrategy((response, context) -> false).setSSLSocketFactory(sslFactory).build();
        } catch (Exception e) {
            log.error("处理Https证书异常", e);
        }
        return HttpClients.createDefault();
    }

    public static String httpPostParamRequest(String url, Map<String, Object> param, Map<String, String> headers) {
        HttpClient httpClient = createSSLClientDefault();
        String strReturn = "";
        try {
            HttpPost httppost = new HttpPost(url);
            httppost.setHeader("User-Agent", USER_AGENT);

            for (String key : headers.keySet()) {
                httppost.setHeader(key, headers.get(key));
            }
            List<NameValuePair> paramList = new ArrayList<NameValuePair>();
            for (String key : param.keySet()) {
                BasicNameValuePair basicNameValuePair = new BasicNameValuePair(key, String.valueOf(param.get(key)));
                paramList.add(basicNameValuePair);
            }

            // 第二步：我们发现Entity是一个接口，所以只能找实现类，发现实现类又需要一个集合，集合的泛型是NameValuePair类型
            UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(paramList);
            // 第一步：通过setEntity 将我们的entity对象传递过去
            httppost.setEntity(formEntity);
            HttpEntity respentity;

            HttpResponse response = httpClient.execute(httppost);
            int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode == HttpStatus.SC_MOVED_PERMANENTLY || statusCode == HttpStatus.SC_MOVED_TEMPORARILY) {
                String newUrl = response.getFirstHeader("Location").getValue();
                return httpPostParamRequest(newUrl, param, headers);
            } else if (statusCode == HttpStatus.SC_OK) {
                respentity = response.getEntity();
                strReturn = EntityUtils.toString(respentity);
                return strReturn;
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error(e.getMessage());
        }
        return strReturn;
    }

    public static void getFile(String url,Map<String,String> headerMap,String filePath){
        HttpClient httpClient = createSSLClientDefault();
        HttpResponse response = null;
        HttpGet httpGet = new HttpGet(url);
        String result = null;
        try {
            httpGet.setHeader("User-Agent", USER_AGENT);
            response = httpClient.execute(httpGet);
            HttpEntity entity = response.getEntity();
            try (InputStream in = entity.getContent()) {
                File file = new File(filePath);
                FileOutputStream fout = new FileOutputStream(file);
                int l = -1;
                byte[] tmp = new byte[1024];
                while ((l = in.read(tmp)) != -1) {
                    fout.write(tmp, 0, l);
                }
                fout.flush();
                fout.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
            // 关闭低层流。
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
    public static String httpPostRequest(String url, Map<String, Object> param, Map<String, String> headers) {
        HttpClient httpClient = createSSLClientDefault();
        String strReturn = "";
        try {
            HttpPost httppost = new HttpPost(url);
            httppost.setHeader("User-Agent", USER_AGENT);
            httppost.addHeader("Content-Type", "application/json");
            if (headers != null) {
                for (String key : headers.keySet()) {
                    httppost.setHeader(key, headers.get(key));
                }
            }

            httppost.setEntity(new StringEntity(new Gson().toJson(param), StandardCharsets.UTF_8));
            HttpEntity respentity;

            HttpResponse response = httpClient.execute(httppost);
            int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode == HttpStatus.SC_MOVED_PERMANENTLY || statusCode == HttpStatus.SC_MOVED_TEMPORARILY) {
                String newUrl = response.getFirstHeader("Location").getValue();
                return httpPostRequest(newUrl, param, headers);
            } else if (statusCode == HttpStatus.SC_OK) {
                respentity = response.getEntity();
                strReturn = EntityUtils.toString(respentity);
                return strReturn;
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error(e.getMessage());
        }
        return strReturn;
    }


    public static String httpPostRequestTest(String url, String body, Map<String, String> headers) {
        HttpClient httpClient = createSSLClientDefault();
        String strReturn = "";
        try {
            HttpPost httppost = new HttpPost(url);
            httppost.setHeader("User-Agent", USER_AGENT);
            httppost.addHeader("Content-Type", "application/json");
            for (String key : headers.keySet()) {
                httppost.setHeader(key, headers.get(key));
            }
            httppost.setEntity(new StringEntity(body, StandardCharsets.UTF_8));
            HttpEntity respentity;

            HttpResponse response = httpClient.execute(httppost);
            int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode == HttpStatus.SC_MOVED_PERMANENTLY || statusCode == HttpStatus.SC_MOVED_TEMPORARILY) {
                String newUrl = response.getFirstHeader("Location").getValue();
                return httpPostRequestTest(newUrl, body, headers);
            } else if (statusCode == HttpStatus.SC_OK) {
                respentity = response.getEntity();
                strReturn = EntityUtils.toString(respentity);
                return strReturn;
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error(e.getMessage());
        }
        return strReturn;
    }


    public static String kuaiShouhttpPostRequest(String url, String body, Map<String, String> headers) {
        HttpClient httpClient = createSSLClientDefault();
        String strReturn = "";
        try {
            HttpPost httppost = new HttpPost(url);
            if (!Check.isNullMap(headers)) {
                for (String key : headers.keySet()) {
                    httppost.setHeader(key, headers.get(key));
                }
            }
            httppost.setHeader("User-Agent", USER_AGENT);
            if (!Check.isNull(body)) {
                httppost.setEntity(new StringEntity(body, StandardCharsets.UTF_8));
            }
            HttpEntity respentity;
            HttpResponse response = httpClient.execute(httppost);
            int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode == HttpStatus.SC_OK) {
                respentity = response.getEntity();
                strReturn = EntityUtils.toString(respentity);
                return strReturn;
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error(e.getMessage());
        }
        return strReturn;
    }


    public static String httpPostRequest(String url, JSONObject params, Map<String, String> headers) {
        HttpClient httpClient = createSSLClientDefault();
        String strReturn = "";
        try {
            HttpPost httppost = new HttpPost(url);
            httppost.setHeader("User-Agent", USER_AGENT);
            httppost.addHeader("Content-Type", "application/json");
            if (headers != null) {
                for (String key : headers.keySet()) {
                    httppost.setHeader(key, headers.get(key));
                }
            }
            if (params != null) {
                httppost.setEntity(new StringEntity(params.toJSONString(), StandardCharsets.UTF_8));
            }

            HttpEntity respentity;

            HttpResponse response = httpClient.execute(httppost);
            int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode == HttpStatus.SC_MOVED_PERMANENTLY || statusCode == HttpStatus.SC_MOVED_TEMPORARILY) {
                String newUrl = response.getFirstHeader("Location").getValue();
                return httpPostRequest(newUrl, params, headers);
            } else if (statusCode == HttpStatus.SC_OK) {
                respentity = response.getEntity();
                strReturn = EntityUtils.toString(respentity);
                return strReturn;
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error(e.getMessage());
        }
        return strReturn;
    }

    public static String getRedirectUrl(String url){
        HttpClient httpClient = createSSLClientDefault();
        HttpResponse response = null;
        HttpGet httpGet = new HttpGet(url);
        String result = null;
        try {
//            httpGet.setHeader("User-Agent", USER_AGENT);
            response = httpClient.execute(httpGet);
            int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode == HttpStatus.SC_MOVED_PERMANENTLY || statusCode == HttpStatus.SC_MOVED_TEMPORARILY) {
                return response.getFirstHeader("Location").getValue();
            }

        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }

    public static String httpGetRequest(String url) {
        HttpClient httpClient = createSSLClientDefault();
        HttpResponse response = null;
        HttpGet httpGet = new HttpGet(url);
        String result = null;
        try {
            httpGet.setHeader("User-Agent", USER_AGENT);
            response = httpClient.execute(httpGet);
            int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode == HttpStatus.SC_MOVED_PERMANENTLY || statusCode == HttpStatus.SC_MOVED_TEMPORARILY) {
                String newUrl = response.getFirstHeader("Location").getValue();
                return httpGetRequest(newUrl);
            } else if (statusCode == HttpStatus.SC_OK) {
                BufferedReader reader = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
                String line = null;
                StringBuilder builder = new StringBuilder();
                while ((line = reader.readLine()) != null) {
                    builder.append(line);
                }
                result = builder.toString();
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    public static String httpRequest(String url, String strParams) throws Exception {
        HttpClient httpClient = createSSLClientDefault();
        String strReturn = "";
        try {

            HttpPost httppost = new HttpPost(url);
            httppost.addHeader("Content-Type", "application/json");
            httppost.setEntity(new StringEntity(strParams, StandardCharsets.UTF_8));
            HttpEntity respentity;
            HttpResponse response = httpClient.execute(httppost);
            int code = response.getStatusLine().getStatusCode();

            respentity = response.getEntity();
            strReturn = EntityUtils.toString(respentity);
        } catch (Exception e) {
            e.printStackTrace();
            log.error(e.getMessage());
        }
        return strReturn;
    }

    public static String httpRequest(String url, CookieStore cookies, Map<String, String> parameterMap) throws Exception {
        HttpClient httpClient = createSSLClientDefault();
        String strReturn = "";
        try {
            HttpPost httppost = new HttpPost(url);
            httppost.setHeader("Content-Type", "application/json");
            UrlEncodedFormEntity postEntity = new UrlEncodedFormEntity(
                    getParam(parameterMap), "UTF-8");
            httppost.setEntity(postEntity);
            HttpEntity respentity;
            HttpResponse response = httpClient.execute(httppost);
            respentity = response.getEntity();
            strReturn = EntityUtils.toString(respentity);
        } catch (Exception e) {
            e.printStackTrace();
            log.error(e.getMessage());
        }
        return strReturn;
    }

    public static List<NameValuePair> getParam(Map parameterMap) {
        List<NameValuePair> param = new ArrayList<NameValuePair>();
        Iterator it = parameterMap.entrySet().iterator();
        while (it.hasNext()) {
            Map.Entry parmEntry = (Map.Entry) it.next();
            param.add(new BasicNameValuePair((String) parmEntry.getKey(),
                    (String) parmEntry.getValue()));
        }
        return param;
    }

    public static HttpClient getHttpclient() {
        RequestConfig defaultRequestConfig = RequestConfig.custom().setSocketTimeout(180000).setConnectTimeout(30000)
                .setConnectionRequestTimeout(30000).setStaleConnectionCheckEnabled(true).build();
        return HttpClients.custom().setDefaultRequestConfig(defaultRequestConfig).build();
    }

    public static String callingGraph(String url, String json) {
        HttpClient httpClient = createSSLClientDefault();
        HttpResponse response = null;
        HttpPost httpPost = new HttpPost(url);
        httpPost.setHeader("Content-Type", "application/json");
        String result = null;

        try {
            StringEntity entity = new StringEntity(json, "utf-8");
            httpPost.setHeader("User-Agent", USER_AGENT);
            httpPost.setEntity(entity);
            response = httpClient.execute(httpPost);
            BufferedReader reader = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
            String line = null;
            StringBuilder builder = new StringBuilder();
            while ((line = reader.readLine()) != null) {
                builder.append(line);
            }
            result = builder.toString();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    public static Map<String, Integer> kuaishouNumberMap;

    public static Integer getKuaishouNumber(String key) {
        if (kuaishouNumberMap == null) {
            kuaishouNumberMap = new HashMap<>();
            kuaishouNumberMap.put("494.0#735.0", 0);
            kuaishouNumberMap.put("265.0#713.0", 1);
            kuaishouNumberMap.put("495.0#719.0", 2);
            kuaishouNumberMap.put("500.0#736.0", 3);
            kuaishouNumberMap.put("510.0#718.0", 4);
            kuaishouNumberMap.put("493.0#722.0", 5);
            kuaishouNumberMap.put("491.0#737.0", 6);
            kuaishouNumberMap.put("498.0#704.0", 7);
            kuaishouNumberMap.put("492.0#738.0", 8);
            kuaishouNumberMap.put("484.0#737.0", 9);
        }
        return kuaishouNumberMap.get(key);
    }

    public static void kuaishouTtf(String ttfName) {
        try {
            URL url = new URL("https://static.yximgs.com/udata/pkg/kuaishou-front-end-live/" + ttfName);
            URLConnection urlconn = url.openConnection();
            TTFParser ttfParser = new TTFParser();
            TrueTypeFont ttf = ttfParser.parse(urlconn.getInputStream());
            GlyphData[] datas = ttf.getGlyph().getGlyphs();
            CmapSubtable[] tables = ttf.getCmap().getCmaps();
            CmapSubtable table = tables[0];
            Map<String, String> fontMap = new HashMap<>();
            for (int i = 0; i <= 13; i++) {
                GlyphData data = datas[i];
                if (data != null) {
                    float fx = data.getBoundingBox().getLowerLeftX();
                    float fy = data.getBoundingBox().getLowerLeftY();
                    float rx = data.getBoundingBox().getUpperRightX();
                    float ry = data.getBoundingBox().getUpperRightY();
                    Integer num = getKuaishouNumber(String.valueOf(rx - fx) + "#" + String.valueOf(ry - fy));
                    fontMap.put(String.valueOf((char) table.getCharCodes(i).get(0).intValue()), String.valueOf(num));
                }
            }
            fontsMap.put(ttfName, fontMap);
            for (GlyphData data : datas) {
                if (data != null) {
                    float fx = data.getBoundingBox().getLowerLeftX();
                    float fy = data.getBoundingBox().getLowerLeftY();
                    float rx = data.getBoundingBox().getUpperRightX();
                    float ry = data.getBoundingBox().getUpperRightY();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    public static String mapParamsSortToStringBySeperator(TreeMap<String, Object> treeMap, String seperator) {
        String result = "";
        if (null != treeMap && !treeMap.isEmpty()) {
            for (Map.Entry<String, Object> entry : treeMap.entrySet()) {
                String key = entry.getKey();
                String value = (String) entry.getValue();
                result += (key + "=" + value + seperator);
            }
            if (result.length() > 0) {
                result = result.substring(0, result.length() - seperator.length());
            }
        }
        return result;
    }


    public static String httpGetRequest(String url, Map<String, String> headers, TreeMap<String, Object> params) {
        HttpClient httpClient = createSSLClientDefault();
        String strReturn = "";
        try {
            String uri = url + "?" + mapParamsSortToStringBySeperator(params, "&");
            HttpGet httpGet = new HttpGet(uri);
            if (headers != null) {
                Iterator<String> keyIter = headers.keySet().iterator();
                while (keyIter.hasNext()) {
                    String curKey = keyIter.next();
                    if (curKey != null && headers.get(curKey) != null) {
                        httpGet.addHeader(curKey, headers.get(curKey));
                    }
                }
            }
            HttpEntity respentity;
            HttpResponse response = httpClient.execute(httpGet);
            respentity = response.getEntity();
            strReturn = EntityUtils.toString(respentity);
        } catch (Exception e) {
            e.printStackTrace();
            log.error(e.getMessage());
        }
        return strReturn;
    }

    public static String httpGetRequest(String url, Map<String, String> headers, JSONObject params) {
        HttpClient httpClient = createSSLClientDefault();
        String strReturn = "";
        try {
            HttpGetWithBodyEntity httpGet = new HttpGetWithBodyEntity(url);
            if (headers != null) {
                Iterator<String> keyIter = headers.keySet().iterator();
                while (keyIter.hasNext()) {
                    String curKey = keyIter.next();
                    if (curKey != null && headers.get(curKey) != null) {
                        httpGet.addHeader(curKey, headers.get(curKey));
                    }
                }
            }
            httpGet.setEntity(new StringEntity(params.toJSONString(), StandardCharsets.UTF_8));
            HttpEntity respentity;
            HttpResponse response = httpClient.execute(httpGet);
            respentity = response.getEntity();
            strReturn = EntityUtils.toString(respentity);
        } catch (Exception e) {
            e.printStackTrace();
            log.error(e.getMessage());
        }
        return strReturn;
    }


    public static String httpGet(String url, Map<String, Object> paramsMap, Map<String, String> headers) {
        String result = null;
        try {
            // CloseableHttpClient httpClient = HttpClients.createDefault();
            //创建参数列表
            HttpClient httpclient = getHttpclient();
            StringBuilder postBody = null;
            if (!Check.isNull(paramsMap)) {
                postBody = new StringBuilder();
                for (Map.Entry<String, Object> entry : paramsMap.entrySet()) {
                    if (entry.getValue() == null) {
                        continue;
                    }
                    postBody.append(entry.getKey()).append("=").append(URLEncoder.encode(entry.getValue().toString(),
                            "utf-8")).append("&");
                }
                if (!paramsMap.isEmpty()) {
                    postBody.deleteCharAt(postBody.length() - 1);
                }
            }
            String urlStr;
            if (!Check.isNull(postBody)) {
                urlStr = url + "?" + postBody;
            } else {
                urlStr = url;
            }
            HttpGet httpget = new HttpGet(urlStr);
            httpget.setHeader("User-Agent", USER_AGENT);
            if (!Check.isNullMap(headers)) {
                for (String key : headers.keySet()) {
                    httpget.setHeader(key, headers.get(key));
                }
            }
            HttpEntity respEntity;
            HttpResponse response = httpclient.execute(httpget);
            respEntity = response.getEntity();
            result = EntityUtils.toString(respEntity);
        } catch (Exception e) {
            log.error("http get请求异常");
            e.printStackTrace();
        }
        return result;
    }


    public static String httpPostRequest(String url, Map<String, Object> param, Map<String, String> headers, CookieStore cookieStore) {
        HttpClient httpClient = createSSLClientDefault(cookieStore);
        String strReturn = "";
        try {
            HttpPost httppost = new HttpPost(url);
            httppost.setHeader("User-Agent", USER_AGENT);
            httppost.addHeader("Content-Type", "application/json");
            if (headers != null) {
                for (String key : headers.keySet()) {
                    httppost.setHeader(key, headers.get(key));
                }
            }

            httppost.setEntity(new StringEntity(new Gson().toJson(param), StandardCharsets.UTF_8));
            HttpEntity respentity;

            HttpResponse response = httpClient.execute(httppost);
            int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode == HttpStatus.SC_MOVED_PERMANENTLY || statusCode == HttpStatus.SC_MOVED_TEMPORARILY) {
                String newUrl = response.getFirstHeader("Location").getValue();
                return httpPostRequest(newUrl, param, headers);
            } else if (statusCode == HttpStatus.SC_OK) {
                respentity = response.getEntity();
                strReturn = EntityUtils.toString(respentity);
                return strReturn;
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error(e.getMessage());
        }
        return strReturn;
    }
}
