package com.lz.common.utils;

import org.apache.http.*;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
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.client.methods.HttpUriRequest;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.scheme.PlainSocketFactory;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpParams;
import org.apache.http.params.HttpProtocolParams;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.net.ssl.*;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.security.KeyStore;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.*;

/**
 * @author 陈金虎 2017年1月16日 下午11:41:47
 * @类描述：http请求工具
 * @注意：本内容仅限于杭州霖梓网络科技有限公司内部传阅，禁止外泄以及用于其他的商业目的
 */
@SuppressWarnings("deprecation")
public class HttpUtil {

    public static final int cache = 10 * 1024;
    public static final boolean isWindows;
    public static final String splash;
    public static final String root;

    static {

        if (System.getProperty("os.name") != null &&
                System.getProperty("os.name").toLowerCase().contains("windows")) {
            isWindows = true;
            splash = "\\";
            root = "D:";
        } else {
            isWindows = false;
            splash = "/";
            root = "/search";
        }
    }

    protected static final Logger logger = LoggerFactory.getLogger(HttpUtil.class);

    /**
     * 执行GET请求
     *
     * @param url
     * @param timeout
     * @return
     */
    public static String doGet(String url, int timeout) {
        logger.info("doGet url = {}", url);
        BufferedReader in = null;
        OutputStreamWriter out = null;
        String result = "";
        try {
            URL realUrl = new URL(url);
            URLConnection conn = realUrl.openConnection();
            conn.setConnectTimeout(timeout);
            conn.setDoOutput(true);
            conn.setDoInput(true);
            conn.setRequestProperty("content-type", "application/x-www-form-urlencoded");
            in = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"));
            String line;
            while ((line = in.readLine()) != null) {
                result += line;
            }
        } catch (Exception e) {
            logger.error("发送失败" + e);
            return "";
        } finally {
            try {
                if (out != null) {
                    out.close();
                }
                if (in != null) {
                    in.close();
                }
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
        logger.info("doGet result = {}", result);
        return result;
    }

    /**
     * 执行GET请求
     *
     * @param url
     * @param
     * @return
     */
    public static String doPost(String url, String param) {
        BufferedReader in = null;
        OutputStreamWriter out = null;
        String result = "";
        try {
            URL realUrl = new URL(url);
            URLConnection conn = realUrl.openConnection();
            conn.setConnectTimeout(20 * 1000);
            conn.setDoOutput(true);
            conn.setDoInput(true);
            conn.setRequestProperty("content-type", "application/x-www-form-urlencoded");
            out = new OutputStreamWriter(conn.getOutputStream());
            // 把数据写入请求的Body
            out.write(param);
            out.flush();
            in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
            String line;
            while ((line = in.readLine()) != null) {
                result += line;
            }
        } catch (Exception e) {
            logger.error("发送失败" + e);
            return "";
        } finally {
            try {
                if (out != null) {
                    out.close();
                }
                if (in != null) {
                    in.close();
                }
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
        return result;
    }

//    /**
//     * 发送post请求
//     *
//     * @param url
//     * @param paramsMap
//     * @return
//     * @throws ClientProtocolException
//     * @throws IOException
//     */
//    public static String httpPost(String url, Map<String, String> paramsMap) {
//    	logger.info("httpPost begin url = {}, paramsMap = {}",url, paramsMap);
//        HttpClientBuilder builder = HttpClientBuilder.create();
//        CloseableHttpClient httpClient = builder.build();
//        // 要传递的参数
//        List<NameValuePair> query = new ArrayList<NameValuePair>();
//        for (String name : paramsMap.keySet()) {
//            NameValuePair paramItem = new BasicNameValuePair(name, paramsMap.get(name));
//            query.add(paramItem);
//        }
//        if (url.indexOf("?") > 0) {
//            url = url + "&";
//        } else {
//            url = url + "?";
//        }
//        url = url + URLEncodedUtils.format(query, CharEncoding.UTF_8);
//        HttpUriRequest request = new HttpPost(url);
//        HttpResponse response = null;
//        HttpPost postMethod = new HttpPost();
//        postMethod.setURI(request.getURI());
//        postMethod.setHeader("content-type", "application/json;charset=utf-8");
//        try {
//            response = httpClient.execute(postMethod);
//            HttpEntity entity = response.getEntity();
//            // System.out.println(response.getStatusLine());
//            // 显示结果
//            if (!url.contains("preview")) {
//                BufferedReader reader = new BufferedReader(new InputStreamReader(entity.getContent(), "UTF-8"));
//
//                String line = null;
//                StringBuffer sb = new StringBuffer();
//                while ((line = reader.readLine()) != null) {
//                    sb.append(line);
//                }
//                reader.close();
//                logger.info("httpPost result = {}",sb.toString());
//                return sb.toString();
//            } else {
//                BufferedInputStream bi = new BufferedInputStream(entity.getContent());
//                FileOutputStream fo = new FileOutputStream(new File("D:/picture/" + new Date().getTime() + ".jpg"));
//                int readByte = 0;
//                while ((readByte = bi.read()) != -1) {
//                    fo.write(readByte);
//                }
//                bi.close();
//                fo.close();
//                return null;
//            }
//        } catch (Exception e) {
//            logger.error("httpPost", e);
//            return "";
//        }
//    }

    /**
     * 发送POST请求，将参数放置到BODY里边
     *
     * @param url
     * @param param
     * @return
     */
    public static String doHttpPost(String url, String param) {
        logger.info("doHttpPost begin url = {} param = {}", url, param);
        BufferedReader in = null;
        OutputStreamWriter out = null;
        String result = "";
        try {
            URL realUrl = new URL(url);
            URLConnection conn = realUrl.openConnection();
            conn.setDoOutput(true);
            conn.setDoInput(true);
            conn.setRequestProperty("content-type", "application/x-www-form-urlencoded");
            out = new OutputStreamWriter(conn.getOutputStream());
            // 把数据写入请求的Body
            out.write(param);
            out.flush();
            in = new BufferedReader(new InputStreamReader(conn.getInputStream(), "utf-8"));
            String line;
            while ((line = in.readLine()) != null) {
                result += line;
            }
        } catch (Exception e) {
            logger.error("发送失败" + e);
            e.printStackTrace();
        } finally {
            try {
                if (out != null) {
                    out.close();
                }
                if (in != null) {
                    in.close();
                }
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
        logger.info("doHttpPost result = {}", result);
        return result;
    }

    /**
     * <b>功能描述:</b>
     *
     * @param reqUrl
     * @param parameters
     * @param recvEncoding
     * @return java.lang.String
     * <b>修改历史:</b>(修改人,修改时间,修改原因/内容)
     * @author : chenruhui
     * <b>创建日期 :</b>
     * @date 2018/10/30 10:42
     */
    public static String doHttpPost(String reqUrl, Map parameters, String recvEncoding) {
        HttpURLConnection urlCon = null;
        String responseContent = null;
        try {
            StringBuffer params = new StringBuffer();
            Iterator iter = parameters.entrySet().iterator();
            while (iter
                    .hasNext()) {
                Map.Entry element = (Map.Entry) iter.next();
                params.append(element.getKey().toString());
                params.append("=");
                params.append(URLEncoder.encode(element.getValue().toString(),
                        "UTF-8"));
                params.append("&");
            }
            if (params.length() > 0) {
                params = params.deleteCharAt(params.length() - 1);
            }
            URL url = new URL(reqUrl);
            urlCon = (HttpURLConnection) url.openConnection();
            urlCon.setRequestMethod("POST");
            System.setProperty("sun.net.client.defaultConnectTimeout",
                    String.valueOf(5000));
            System.setProperty("sun.net.client.defaultReadTimeout",
                    String.valueOf(10000));

            urlCon.setDoOutput(true);
            byte[] b = params.toString().getBytes();
            urlCon.getOutputStream().write(b, 0, b.length);
            urlCon.getOutputStream().flush();
            urlCon.getOutputStream().close();

            InputStream in = urlCon.getInputStream();
            BufferedReader rd = new BufferedReader(
                    new InputStreamReader(in,
                            recvEncoding));
            String tempLine = rd.readLine();
            StringBuilder tempStr = new StringBuilder();
            String crlf = System.getProperty("line.separator");
            while (tempLine != null) {
                tempStr.append(tempLine);
                tempStr.append(crlf);
                tempLine = rd.readLine();
            }
            responseContent = tempStr.toString();
            rd.close();
            in.close();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (urlCon != null) {
                urlCon.disconnect();
            }
        }
        return responseContent;
    }

    /**
     * 发送POST请求，将参数放置到BODY里边
     *
     * @param url
     * @param param
     * @return
     */
    public static String doHttpPostJsonParam(String url, String param) {
        BufferedReader in = null;
        OutputStreamWriter out = null;
        String result = "";
        try {
            URL realUrl = new URL(url);
            URLConnection conn = realUrl.openConnection();
            conn.setDoOutput(true);
            conn.setDoInput(true);
            conn.setRequestProperty("content-type", "application/json");
            conn.setRequestProperty("Accept-Charset", "utf-8");
            conn.setRequestProperty("contentType", "utf-8");
            conn.setConnectTimeout(2000);

            out = new OutputStreamWriter(conn.getOutputStream());
            // 把数据写入请求的Body
            out.write(param);
            out.flush();
            in = new BufferedReader(new InputStreamReader(conn.getInputStream(), "utf-8"));
            String line;
            while ((line = in.readLine()) != null) {
                result += line;
            }
        } catch (Exception e) {
            logger.error("发送失败" + e);
            e.printStackTrace();
        } finally {
            try {
                if (out != null) {
                    out.close();
                }
                if (in != null) {
                    in.close();
                }
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
        return result;
    }


    /**
     * 根据url下载文件，保存到filepath中
     *
     * @param url      文件路径
     * @param filepath 下载至地址文件
     * @return
     */
    public static String download(String url, String filepath) {
        try {
            HttpClient client = new DefaultHttpClient();
            HttpGet httpget = new HttpGet(url);
            HttpResponse response = client.execute(httpget);

            HttpEntity entity = response.getEntity();
            InputStream is = entity.getContent();
            if (filepath == null) {
                filepath = getFilePath(response);
            }
            File file = new File(filepath);
            file.getParentFile().mkdirs();
            FileOutputStream fileOut = new FileOutputStream(file);
            //根据实际运行效果 设置缓冲区大小
            byte[] buffer = new byte[cache];
            int ch = 0;
            while ((ch = is.read(buffer)) != -1) {
                fileOut.write(buffer, 0, ch);
            }
            is.close();
            fileOut.flush();
            fileOut.close();

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


    /**
     * 根据url下载文件，保存到流中
     *
     * @param url 文件路径
     * @return
     */
    public static String downloadWithStream(String url) {
        try {
            HttpClient client = new DefaultHttpClient();
            HttpGet httpget = new HttpGet(url);
            HttpResponse response = client.execute(httpget);

            HttpEntity entity = response.getEntity();
            InputStream is = entity.getContent();
            ByteArrayOutputStream fileout = new ByteArrayOutputStream();
            // 根据实际运行效果 设置缓冲区大小
            byte[] buffer = new byte[cache];
            int ch = 0;
            while ((ch = is.read(buffer)) != -1) {
                fileout.write(buffer, 0, ch);
            }
            is.close();
            fileout.flush();
            fileout.close();
            //保存文件信息
            String result = new String(fileout.toByteArray(), "ISO-8859-1");
            result = URLEncoder.encode(result, "ISO-8859-1");
            return result;

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


    /**
     * 发送POST请求，将参数放置到BODY里边
     *
     * @param url
     * @param param
     * @param cookie
     * @return
     */
    public static String httpPost(String url, String param, String cookie) {
        BufferedReader in = null;
        OutputStreamWriter out = null;
        String result = "";
        try {
            URL realUrl = new URL(url);
            URLConnection conn = realUrl.openConnection();
            conn.setDoOutput(true);
            conn.setDoInput(true);
            conn.setRequestProperty("content-type", "application/json");
            conn.setRequestProperty("Cookie", cookie);
            out = new OutputStreamWriter(conn.getOutputStream());
            // 把数据写入请求的Body
            out.write(param);
            out.flush();
            in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
            String line;
            while ((line = in.readLine()) != null) {
                result += line;
            }
        } catch (Exception e) {
            logger.error("发送失败" + e);
            e.printStackTrace();
        } finally {
            try {
                if (out != null) {
                    out.close();
                }
                if (in != null) {
                    in.close();
                }
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
        return result;
    }

    /**
     * 发送HTTPS的POST请求，并且忽略证书验证,将参数放置到BODY里边
     *
     * @param urlString
     * @param query
     * @return
     */
    public static String doHttpsPostIgnoreCert(String urlString, String query) {

        ByteArrayOutputStream buffer = new ByteArrayOutputStream(512);
        try {
            URL url = new URL(urlString);
            /*
             * use ignore host name verifier
             */
            HttpsURLConnection.setDefaultHostnameVerifier(ignoreHostnameVerifier);
            HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();

            // Prepare SSL Context
            TrustManager[] tm = {ignoreCertificationTrustManger};
            SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
            sslContext.init(null, tm, new java.security.SecureRandom());
            // 设置doOutput属性为true表示将使用此urlConnection写入数据
            connection.setDoOutput(true);
            connection.setConnectTimeout(5000);
            connection.setReadTimeout(20000);
            // 从上述SSLContext对象中得到SSLSocketFactory对象
            SSLSocketFactory ssf = sslContext.getSocketFactory();
            connection.setSSLSocketFactory(ssf);
            connection.setConnectTimeout(10000);
            connection.setReadTimeout(20000);

            OutputStreamWriter out = new OutputStreamWriter(connection.getOutputStream());
            // 把数据写入请求的Body
            out.write(query);
            out.flush();
            out.close();

            InputStream reader = connection.getInputStream();
            byte[] bytes = new byte[512];
            int length = reader.read(bytes);

            do {
                buffer.write(bytes, 0, length);
                length = reader.read(bytes);
            } while (length > 0);

            reader.close();
            connection.disconnect();
        } catch (Exception ex) {
            logger.error("发送失败 url " + urlString + "| params " + query, ex);
        } finally {
        }
        String repString = new String(buffer.toByteArray());
        return repString;
    }

    /**
     * 忽视证书HostName
     */
    private static HostnameVerifier ignoreHostnameVerifier = new HostnameVerifier() {

        @Override
        public boolean verify(String s, SSLSession sslsession) {
            logger.debug("WARNING: Hostname is not matched for cert.");
            return true;
        }
    };

    /**
     * Ignore Certification
     */
    private static TrustManager ignoreCertificationTrustManger = new X509TrustManager() {

        private X509Certificate[] certificates;

        @Override
        public void checkClientTrusted(X509Certificate certificates[], String authType) throws CertificateException {
            if (this.certificates == null) {
                this.certificates = certificates;
                logger.debug("init at checkClientTrusted");
            }
        }

        @Override
        public void checkServerTrusted(X509Certificate[] ax509certificate, String s) throws CertificateException {
            if (this.certificates == null) {
                this.certificates = ax509certificate;
                logger.debug("init at checkServerTrusted");
            }
        }

        @Override
        public X509Certificate[] getAcceptedIssuers() {
            return null;
        }
    };

    public static String post(String url, Map<String, String> params) {
        DefaultHttpClient httpclient = new DefaultHttpClient();
        String body = null;

        logger.info("create httppost:" + url + ",params=" + params);
        HttpPost post = postForm(url, params);

        body = invoke(httpclient, post);

        httpclient.getConnectionManager().shutdown();

        return body;
    }



    /**
     * HTTP 操作类（POST提交）
     *
     * @param postdata POST提交的数据
     */
    public static String http(String url, String postdata) {
        PrintWriter out = null;
        BufferedReader in = null;
        String result = "";
        try {
            URL realUrl = new URL(url);
            URLConnection conn = realUrl.openConnection();
            conn.setRequestProperty("accept", "*/*");
            conn.setRequestProperty("connection", "Keep-Alive");
            conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
            conn.setDoOutput(true);
            conn.setDoInput(true);
            out = new PrintWriter(conn.getOutputStream());
            out.print(postdata);
            out.flush();
            in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
            String line;
            while ((line = in.readLine()) != null) {
                result += line;
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (out != null) {
                    out.close();
                }
                if (in != null) {
                    in.close();
                }
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
        return result;
    }


    /**
     * 合并String数组为字符串
     *
     * @param fg    分隔符
     * @param phone 存储手机号的字符数组
     */
    public static String implode(String fg, String[] phone) {
        StringBuffer sb = new StringBuffer();
        sb.append(phone[0]);
        for (int i = 1; i < phone.length; i++) {
            sb.append(fg + phone[i]);
        }
        return sb.toString();
    }

    private static String invoke(DefaultHttpClient httpclient, HttpUriRequest httpost) {

        HttpResponse response = sendRequest(httpclient, httpost);
        String body = paseResponse(response);

        return body;
    }

    private static String paseResponse(HttpResponse response) {
        logger.info("get response from http server..");
        HttpEntity entity = response.getEntity();

        logger.info("response status: " + response.getStatusLine());
        String charset = EntityUtils.getContentCharSet(entity);
        logger.info(charset);

        String body = null;
        try {
            body = EntityUtils.toString(entity);
            logger.info(body);
        } catch (ParseException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return body;
    }

    private static HttpResponse sendRequest(DefaultHttpClient httpclient, HttpUriRequest httpost) {
        logger.info("execute post...");
        HttpResponse response = null;

        try {
            response = httpclient.execute(httpost);
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return response;
    }

    private static HttpPost postForm(String url, Map<String, String> params) {

        HttpPost httpost = new HttpPost(url);
        List<NameValuePair> nvps = new ArrayList<NameValuePair>();

        Set<String> keySet = params.keySet();
        for (String key : keySet) {
            nvps.add(new BasicNameValuePair(key, params.get(key)));
        }

        try {
            logger.info("set utf-8 form entity to httppost");
            httpost.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8));
            httpost.setConfig(RequestConfig.custom()
                    .setConnectTimeout(60000)
                    .setConnectionRequestTimeout(30000)
                    .setSocketTimeout(60000).build());
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }

        return httpost;
    }

    /**
     * 获取response要下载的文件的默认路径
     *
     * @param response
     * @return
     */
    private static String getFilePath(HttpResponse response) {
        String filePath = root + splash;
        String filename = getFileName(response);

        if (filename != null) {
            filePath += filename;
        } else {
            filePath += getRandomFileName();
        }
        return filePath;
    }


    /**
     * 获取response header中Content-Disposition中的filename值
     *
     * @param response
     * @return
     */
    private static String getFileName(HttpResponse response) {
        Header contentHeader = response.getFirstHeader("Content-Disposition");
        String filename = null;
        if (contentHeader != null) {
            HeaderElement[] values = contentHeader.getElements();
            if (values.length == 1) {
                NameValuePair param = values[0].getParameterByName("filename");
                if (param != null) {
                    try {
                        //转换成UTF-8
                        //filename = new String(param.getValue().toString().getBytes(), "utf-8");
                        //filename=URLDecoder.decode(param.getValue(),"utf-8");
                        filename = param.getValue();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }
        return filename;
    }


    /**
     * 获取随机文件名
     *
     * @return
     */
    private static String getRandomFileName() {
        return String.valueOf(System.currentTimeMillis());
    }

    public static String feishuPost(String urlStr, String data, String authorization) {
        PrintWriter out = null;
        BufferedReader in = null;
        String result = "";
        try {
            URL url = new URL(urlStr);
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setDoInput(true); // 设置可输入
            connection.setDoOutput(true); // 设置该连接是可以输出的
            connection.setRequestMethod("POST"); // 设置请求方式
            connection.setRequestProperty("Content-Type", "application/json;charset=UTF-8");
            connection.setRequestProperty("Authorization", "Bearer " + authorization);

            out = new PrintWriter(new BufferedOutputStream(connection.getOutputStream()));
//            System.out.println(objectMapper.writeValueAsString(data));
            logger.info("飞书入参：" + data);
            logger.info("飞书authorization：" + authorization);
            out.write(data);
            out.flush();

            in = new BufferedReader(new InputStreamReader(connection.getInputStream(), "utf-8"));
            String line = null;
            StringBuilder resultBr = new StringBuilder();
            while ((line = in.readLine()) != null) { // 读取数据
                resultBr.append(line + "\n");
            }
            connection.disconnect();
            logger.info("飞书出参：" + resultBr.toString());
            result =  resultBr.toString();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (out != null) {
                    out.close();
                }
                if (in != null) {
                    in.close();
                }
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
        return result;
    }


    public static String feishuGet(String urlStr, String authorization) {
        try {
            URL url = new URL(urlStr);
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setDoInput(true); // 设置可输入
            connection.setDoOutput(true); // 设置该连接是可以输出的
            connection.setRequestMethod("GET"); // 设置请求方式
            connection.setRequestProperty("Authorization", "Bearer " + authorization);

            BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream(), "utf-8"));
            String line = null;
            StringBuilder result = new StringBuilder();
            while ((line = br.readLine()) != null) { // 读取数据
                result.append(line + "\n");
            }
            connection.disconnect();
            return result.toString();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "";
    }


}
