package com.ff.weijinxiao.util;


import org.apache.http.HttpEntity;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContextBuilder;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.Args;
import org.apache.http.util.EntityUtils;
import org.springframework.util.CollectionUtils;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.text.ParseException;
import java.util.Map;

public class HttpUtils {


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

    public static String getAuth(String url, String data, String authorization) {
        url = url + "?" + data;
        return getAuth(url, authorization);
    }

    public static String getAuth(String url, Map<String, String> params, String authorization) {
        // 构建请求参数
        String data = mapToString(params);
        return getAuth(url, data, authorization);
    }

    public static String get(String url) {
        return get(url, null);
    }

    public static String getAuth(String url, String authorization) {

        URL u = null;
        HttpURLConnection con = null;
        System.out.println("send_url get: " + url);
        try {
            u = new URL(url);
            //// POST 只能为大写，严格限制，post会不识别
            con = (HttpURLConnection) u.openConnection();
            con.setRequestMethod("GET");
            if (null != authorization && authorization.length() > 0) {
                con.setRequestProperty("Authorization", authorization);
            }
            con.setUseCaches(false);
            con.connect();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (con != null) {
                con.disconnect();
            }
        }

        // 读取返回内容
        StringBuffer buffer = new StringBuffer();
        try {
            //一定要有返回值，否则无法把请求发送给server端。
            BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream(), "UTF-8"));
            String temp;
            while ((temp = br.readLine()) != null) {
                buffer.append(temp);
                buffer.append("\n");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return buffer.toString();
    }

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

    public static String postAuth(String url, Map<String, String> params, String authorization) {
        String data = mapToString(params);
        return postAuth(url, data, authorization);
    }

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

    public static String post(String url, String jsonData) {
        return postAuth(url, jsonData, null);
    }

    public static String post(String url, String jsonData, Map<String, String> params) {
        url = url + "?" + mapToString(params);
        return postAuth(url, jsonData, null);
    }

    public static String postAuth(String url, String jsonData, String authorization) {
        URL u = null;
        HttpURLConnection con = null;
        // 构建请求参数
        //StringBuffer sb = new StringBuffer();
        //String data = mapToString(params);
        System.out.println("send_url post:" + url);
        System.out.println("send_data:" + jsonData);
        // 尝试发送请求
        try {
            u = new URL(url);
            con = (HttpURLConnection) u.openConnection();
            //// POST 只能为大写，严格限制，post会不识别
            con.setRequestMethod("POST");
            con.setDoOutput(true);
            con.setDoInput(true);
            con.setUseCaches(false);
            con.setRequestProperty("Content-Type", "application/json");

            if (null != authorization && authorization.length() > 0) {
                con.setRequestProperty("Authorization", authorization);
            }
            OutputStreamWriter osw = new OutputStreamWriter(con.getOutputStream(), "UTF-8");
            if (jsonData != null) {
                osw.write(jsonData);
            }
            osw.flush();
            osw.close();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (con != null) {
                con.disconnect();
            }
        }

        // 读取返回内容
        StringBuffer buffer = new StringBuffer();
        try {
            //一定要有返回值，否则无法把请求发送给server端。
            BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream(), "UTF-8"));
            String temp;
            while ((temp = br.readLine()) != null) {
                buffer.append(temp);
                buffer.append("\n");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return buffer.toString();
    }

    /**
     * 返回由Map组装的String
     *
     * @param params
     * @return
     */
    public static String mapToString(Map<String, String> params) {

        if (CollectionUtils.isEmpty(params)) {
            return null;
        }
        if (params.size() <= 0) {
            return "";
        }
        StringBuffer sb = new StringBuffer();
        for (Map.Entry<String, String> e : params.entrySet()) {
            sb.append(e.getKey());
            sb.append("=");
            sb.append(e.getValue());
            sb.append("&");
        }
        String mess = sb.substring(0, sb.length() - 1);
        return mess;
    }

    private static void trustAllHttpsCertificates() throws Exception {
        javax.net.ssl.TrustManager[] trustAllCerts = new javax.net.ssl.TrustManager[1];
        javax.net.ssl.TrustManager tm = new miTM();
        trustAllCerts[0] = tm;
        SSLContext sc = SSLContext
                .getInstance("SSL");
        sc.init(null, trustAllCerts, null);
        HttpsURLConnection.setDefaultSSLSocketFactory(sc
                .getSocketFactory());
    }

    static class miTM implements javax.net.ssl.TrustManager,
            javax.net.ssl.X509TrustManager {
        @Override
        public X509Certificate[] getAcceptedIssuers() {
            return null;
        }

        public boolean isServerTrusted(
                X509Certificate[] certs) {
            return true;
        }

        public boolean isClientTrusted(
                X509Certificate[] certs) {
            return true;
        }

        @Override
        public void checkServerTrusted(
                X509Certificate[] certs, String authType)
                throws CertificateException {
            return;
        }

        @Override
        public void checkClientTrusted(
                X509Certificate[] certs, String authType)
                throws CertificateException {
            return;
        }
    }

    public static String postFor(String url, String jsonData) {
        HostnameVerifier hv = new HostnameVerifier() {
            @Override
            public boolean verify(String urlHostName, SSLSession session) {
                System.out.println("Warning: URL Host: " + urlHostName + " vs. "
                        + session.getPeerHost());
                return true;
            }
        };

        try {
            trustAllHttpsCertificates();
        } catch (Exception e) {
            e.printStackTrace();
        }
        HttpsURLConnection.setDefaultHostnameVerifier(hv);

        return postAuth(url, jsonData, null);
    }

    public static void main(String[] args) throws ParseException {

    }

    public static String httpsPostFile(String url, Map<String, File> fileMap) throws Exception {
        return httpsPostFile(url, fileMap, null);
    }

    public static String httpsPostFile(String url, Map<String, File> fileMap, Map<String, String> stringMap) throws Exception {
        Args.notBlank(url, "url");
        Args.notNull(fileMap, "fileMap");
        if (fileMap.isEmpty()) {
            throw new IllegalArgumentException("fileMap may not be null");
        }
        SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {
            public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
                return true;
            }
        }).build();
        SSLConnectionSocketFactory sslFactory = new SSLConnectionSocketFactory(sslContext);
        CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(sslFactory).build();
        try {
            HttpPost httpPost = new HttpPost(url);
            final MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create();
            for (Map.Entry<String, File> entry : fileMap.entrySet()) {
                multipartEntityBuilder.addBinaryBody(entry.getKey(), entry.getValue());
            }
            if (stringMap != null && !stringMap.isEmpty()) {
                for (Map.Entry<String, String> entry : stringMap.entrySet()) {
                    multipartEntityBuilder.addTextBody(entry.getKey(), entry.getValue());
                }
            }
            HttpEntity reqEntity = multipartEntityBuilder.build();

            httpPost.setEntity(reqEntity);

            System.out.println("executing request " + httpPost.getRequestLine());
            CloseableHttpResponse response = httpClient.execute(httpPost);
            String resultString = "";
            try {
                System.out.println(response.getStatusLine());
                HttpEntity resEntity = response.getEntity();
                if (resEntity != null) {
                    //System.out.println("Response content length: " + resEntity.getContentLength());
                    resultString = EntityUtils.toString(resEntity, "UTF-8");
                    System.out.println("Response str : " + resultString);
                }
                EntityUtils.consume(resEntity);
            } finally {
                response.close();
            }
            return resultString;
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                httpClient.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return "";
    }
}
