package log;

import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
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.client.methods.HttpRequestBase;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.ByteArrayBody;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;


/**
 * http工具类
 * @author jiaotianqi
 */
public class HttpClientUtil {
    static Logger logger = LogManager.getLogger(HttpClientUtil.class);
    /**
     * 描述:form表单提交
     *
     * @param url
     * @param param
     * @param header
     * @return java.lang.String
     * @author jiaotq
     * @created 2019/5/29 9:15
     * @since v1.0.0
     */
    public static String doPost(String url, Map<String, String> param, Map<String, String> header) {
        return getHttpClientRetStr(doPostRetResp(url, param, header));
    }

    /**
     * 描述:form表单提交
     *
     * @param url
     * @param param
     * @param header
     * @return CloseableHttpResponse
     * @author jiaotq
     * @created 2019/5/29 9:15
     * @since v1.0.0
     */
    public static CloseableHttpResponse doPostRetResp(String url, Map<String, String> param, Map<String, String> header) {
        HttpPost httppost = new HttpPost(url);
        if (header != null) {
            header.forEach(httppost::setHeader);
        }
        // 创建参数队列
        List<NameValuePair> formparams = new ArrayList<NameValuePair>();
        if (param != null) {
            for (Entry<String, String> value : param.entrySet()) {
                formparams.add(new BasicNameValuePair(value.getKey(), value.getValue()));
            }
        }
        UrlEncodedFormEntity uefEntity = null;
        try {
            uefEntity = new UrlEncodedFormEntity(formparams, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            logger.warn(e.getMessage(), e);
        }
        httppost.setEntity(uefEntity);
        return getHttpResponse(httppost);
    }

    /**
     * 描述:form表单提交
     *
     * @param url
     * @param param
     * @return java.lang.String
     * @author jiaotq
     * @created 2019/5/29 9:15
     * @since v1.0.0
     */
    public static String doPost(String url, Map<String, String> param) {
        return doPost(url, param, null);
    }



    /**
     * 描述:post传文件
     * @param url
     * @param fileName
     * @param bytes
     * @param param
     * @param header
     * @return String
     * @author jiaotq
     * @created 2019/5/29 9:16
     * @since v1.0.0
     */
    public static String postMultipart(String url, String fileName, byte[] bytes,
                                       Map<String, String> param, Map<String, String> header) {
        return getHttpClientRetStr(postMultiparRetResp(url, fileName, bytes, param, header));
    }
    /**
     * 描述:post传多个文件
     * @param url
     * @param files key文件名称,value 文件流
     * @param param
     * @param header
     * @return String
     * @author jiaotq
     * @created 2019/5/29 9:16
     * @since v1.0.0
     */
    public static String postMultiparts(String url,Map<String,byte[]> files,
                                        Map<String, String> param, Map<String, String> header) {
        return getHttpClientRetStr(postMultiparsRetResp(url, files, param, header));
    }
    /**
     * 描述:post传文件
     * 返回  CloseableHttpResponse 对象，需要手动将连接归还池中
     * ，请调用  HttpClientUtil.close(CloseableHttpResponse)  方法
     * @param url
     * @param fileName
     * @param bytes
     * @param param
     * @param header
     * @return CloseableHttpResponse
     * @author jiaotq
     * @created 2019/5/29 9:16
     * @since v1.0.0
     */
    public static CloseableHttpResponse postMultiparRetResp(String url, String fileName, byte[] bytes,
                                                            Map<String, String> param, Map<String, String> header) {
        return  postMultiparRetResp(url,fileName,new ByteArrayBody(bytes,ContentType.MULTIPART_FORM_DATA,fileName),param,header);
    }

    /**
     * 描述:post传文件
     * 返回  CloseableHttpResponse 对象，需要手动将连接归还池中
     * ，请调用  HttpClientUtil.close(CloseableHttpResponse)  方法
     * @param url
     * @param paramName
     * @param data
     * @param param
     * @param header
     * @return CloseableHttpResponse
     * @author jiaotq
     * @created 2019/5/29 9:16
     * @since v1.0.0
     */
    public static CloseableHttpResponse postMultiparRetResp(String url, String paramName, ByteArrayBody data,
                                                            Map<String, String> param, Map<String, String> header) {
        HttpPost httppost = new HttpPost(url);
        if (header != null) {
            header.forEach((k, v) -> {
                httppost.setHeader(k, v);
            });
        }

        MultipartEntityBuilder builder = MultipartEntityBuilder.create();
        builder.addPart(paramName, data);
        if (param != null) {

            param.forEach((k, v) -> {
                builder.addTextBody(k, v, ContentType.TEXT_PLAIN);
            });
        }

        HttpEntity entity = builder.build();
        httppost.setEntity(entity);
        return getHttpResponse(httppost);
    }

    /**
     * 描述:post多个传文件
     * 返回  CloseableHttpResponse 对象，需要手动将连接归还池中
     * ，请调用  HttpClientUtil.close(CloseableHttpResponse)  方法
     * @param url
     * @param files  key文件名称,value 文件流
     * @param param
     * @param header
     * @return CloseableHttpResponse
     * @author jiaotq
     * @created 2019/5/29 9:16
     * @since v1.0.0
     */
    public static CloseableHttpResponse postMultiparsRetResp(String url,Map<String,byte[]> files,
                                                             Map<String, String> param, Map<String, String> header) {
        HttpPost httppost = new HttpPost(url);
        if (header != null) {
            header.forEach((k, v) -> {
                httppost.setHeader(k, v);
            });
        }

        MultipartEntityBuilder builder = MultipartEntityBuilder.create();
        if(files!=null){
            files.forEach((k,v)->{
                builder.addBinaryBody(k, v, ContentType.MULTIPART_FORM_DATA, k);
            });
        }
        if (param != null) {
            param.forEach((k, v) -> {
                builder.addTextBody(k, v, ContentType.TEXT_PLAIN);
            });
        }

        HttpEntity entity = builder.build();
        httppost.setEntity(entity);
        return getHttpResponse(httppost);
    }



    /**
     * 描述:post传xml
     *
     * @param url
     * @param xml
     * @return java.lang.String
     * @author jiaotq
     * @created 2019/5/29 9:17
     * @since v1.0.0
     */
    public static String postXml(String url, String xml) {
        return postXml(url, xml, null);
    }

    /**
     * 描述:post传xml
     *
     * @param url
     * @param xml
     * @param header
     * @return java.lang.String
     * @author jiaotq
     * @created 2019/5/29 9:17
     * @since v1.0.0
     */
    public static String postXml(String url, String xml, Map<String, String> header) {
        return getHttpClientRetStr(postXmlRetResp(url, xml, header));
    }

    /**
     * 描述:post提交xml
     * 返回  CloseableHttpResponse 对象，需要手动将连接归还池中
     * ，请调用  HttpClientUtil.close(CloseableHttpResponse)  方法
     *
     * @param url
     * @param xml
     * @param header
     * @return java.lang.String
     * @author jiaotq
     * @created 2019/5/29 9:17
     * @since v1.0.0
     */
    public static CloseableHttpResponse postXmlRetResp(String url, String xml, Map<String, String> header) {
        HttpPost httppost = new HttpPost(url);
        if (header != null) {
            header.forEach((k, v) -> {
                httppost.setHeader(k, v);
            });
        }
        StringEntity postingString = new StringEntity(xml, "UTF-8");
        httppost.setEntity(postingString);
        httppost.setHeader("Content-type", "text/xml");
        return getHttpResponse(httppost);
    }

    /**
     * 描述:post传json
     *
     * @param url
     * @param json
     * @return java.lang.String
     * @author jiaotq
     * @created 2019/5/29 9:17
     * @since v1.0.0
     */
    public static String postJson(String url, String json) {
        return postJson(url, json, null);
    }

    /**
     * 描述:post传json
     *
     * @param url
     * @param json
     * @param header
     * @return java.lang.String
     * @author jiaotq
     * @created 2019/5/29 9:17
     * @since v1.0.0
     */
    public static String postJson(String url, String json, Map<String, String> header) {

        return getHttpClientRetStr(postJsonRetResp(url, json, header));
    }

    public static String postDelJson(String url, String json, Map<String, String> header) {

        return getHttpClientRetStr(postDelJsonResp(url, json, header));
    }

    private static CloseableHttpResponse postDelJsonResp(String url, String json, Map<String, String> header) {
        HttpDeleteWithBody deleteWithBody = new HttpDeleteWithBody(url);
        if (header != null) {
            header.forEach(deleteWithBody::setHeader);
        }
        StringEntity postingString = new StringEntity(json, "UTF-8");
        deleteWithBody.setEntity(postingString);
        deleteWithBody.setHeader("Content-type", "application/json");
        return getHttpResponse(deleteWithBody);
    }


    /**
     * 描述:post 提交json
     * 返回 CloseableHttpResponse 对象，需要手动将连接归还池中
     * ，请调用  HttpClientUtil.close(CloseableHttpResponse)  方法
     *
     * @param url
     * @param json
     * @param header
     * @return org.apache.http.client.methods.CloseableHttpResponse
     * @author jiaotq
     * @created 2019/6/10 11:44
     * @since v1.0.0
     */
    public static CloseableHttpResponse postJsonRetResp(String url, String json, Map<String, String> header) {
        HttpPost httppost = new HttpPost(url);
        if (header != null) {
            header.forEach(httppost::setHeader);
        }
        StringEntity postingString = new StringEntity(json, "UTF-8");
        httppost.setEntity(postingString);
        RequestConfig config = RequestConfig.custom().setConnectionRequestTimeout(10000).build() ;
        httppost.setConfig(config);
        httppost.setHeader("Content-type", "application/json");

        return getHttpResponse(httppost);
    }

    /**
     * 描述:get提交
     *
     * @param url
     * @return java.lang.String
     * @author jiaotq
     * @created 2019/5/29 9:17
     * @since v1.0.0
     */
    public static String get(String url) {
        return get(url, null, null);
    }

    /**
     * 描述:get提交
     *
     * @param url
     * @param param
     * @return java.lang.String
     * @author jiaotq
     * @created 2019/5/29 9:17
     * @since v1.0.0
     */
    public static String get(String url, Map<String, String> param) {
        return get(url, param, null);
    }

    /**
     * 描述:get提交
     *
     * @param url
     * @param param
     * @param header
     * @return java.lang.String
     * @author jiaotq
     * @created 2019/5/29 9:17
     * @since v1.0.0
     */
    public static String get(String url, Map<String, String> param, Map<String, String> header) {

        return getHttpClientRetStr(getHttpResponse(url, param, header));

    }

    /**
     * 描述: get 获取
     * 返回 CloseableHttpResponse 对象，需要手动将连接归还池中
     * ，请调用  HttpClientUtil.close(CloseableHttpResponse)  方法
     *
     * @param url
     * @param param
     * @param header
     * @return org.apache.http.client.methods.CloseableHttpResponse
     * @author jiaotq
     * @created 2019/6/10 11:35
     * @since v1.0.0
     */
    public static CloseableHttpResponse getHttpResponse(String url, Map<String, String> param, Map<String, String> header) {
        StringBuilder reqParamStr = new StringBuilder();
        if (param != null) {
            reqParamStr.append("?");
            param.forEach((k, v) -> {
                reqParamStr.append(k).append("=").append(v).append("&");
            });
        }
        HttpGet httpGet = new HttpGet(url + reqParamStr.toString());
        if (header != null) {
            header.forEach((k, v) -> {
                httpGet.setHeader(k, v);
            });
        }

        return getHttpResponse(httpGet);

    }


    public static CloseableHttpResponse getHttpResponse(HttpRequestBase http) {
        CloseableHttpClient httpClient = HttpClientEnum.INITIALIZE.getHttpClient();
        CloseableHttpResponse response = null;
        try {
            response = httpClient.execute(http);
        } catch (Exception e) {
            logger.warn(e.getMessage(), e);
            close(response);
        }
        return response;
    }

    /**
     * 描述:归还连接池
     *
     * @param response
     * @return void
     * @author jiaotq
     * @created 2019/6/10 12:41
     * @since v1.0.0
     */
    public static void close(CloseableHttpResponse response) {
        if (response != null) {
            try {
                response.close();
            } catch (IOException e) {
                logger.warn(e.getMessage(), e);
            }
        }
    }

    /**
     * 描述:以字符串形式返回响应的结果
     *
     * @param response
     * @return java.lang.String
     * @author jiaotq
     * @created 2019/6/10 12:48
     * @since v1.0.0
     */
    public static String getHttpClientRetStr(CloseableHttpResponse response) {
        if (response == null) {
            return null;
        }
        HttpEntity responseEntity = response.getEntity();
        if (responseEntity != null) {
            try {
                return EntityUtils.toString(responseEntity, "UTF-8");
            } catch (Exception e) {
                logger.warn(e.getMessage(), e);
            } finally {
                close(response);
            }
        }
        return null;
    }
    /**
     * 描述:将流转bytes数组     *
     * @author  jiaotq
     * @created 2019/6/10 12:54
     * @since   v1.0.0
     */
    public static final byte[] inputToByte(InputStream inStream) throws IOException {
        ByteArrayOutputStream swapStream = new ByteArrayOutputStream();
        byte[] buff = new byte[1024];
        int rc = 0;
        while ((rc = inStream.read(buff, 0, 1024)) > 0) {
            swapStream.write(buff, 0, rc);
        }
        byte[] in2b = swapStream.toByteArray();
        swapStream.close();
        return in2b;
    }
}
