package com.diaoyun.zion.master.util;

import com.diaoyun.zion.chinafrica.enums.PlatformEnum;
import com.google.common.collect.Lists;
import org.apache.http.*;
import org.apache.http.client.CookieStore;
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.client.methods.RequestBuilder;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.client.utils.URLEncodedUtils;
import org.apache.http.entity.ContentType;
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.BasicHeader;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.*;
import java.nio.charset.Charset;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class HttpClientUtil {
    private static Logger logger = LoggerFactory.getLogger(HttpClientUtil.class);
    /**
     * 获取url链接中的content 内容
     * @param sourceUrl 目标url
     * @param sourceType
     * @return
     * @throws URISyntaxException
     * @throws IOException
     */
    public static String getContentByUrl(String sourceUrl, String sourceType) throws URISyntaxException, IOException {
        sourceUrl= urlEncode(sourceUrl,Consts.UTF_8.name());
        URL url = new URL(sourceUrl);
        //构建URI
        URI uri=new URI(url.getProtocol(), url.getHost(), url.getPath(), url.getQuery(), null);
        //创建一个HttpContext对象，用来保存Cookie
        //HttpClientContext httpClientContext = HttpClientContext.create();
        //构造自定义的HttpClient对象
        CloseableHttpClient httpClient;
        if(PlatformEnum.TB.getValue().equals(sourceType)) {
            httpClient = createBrowserClient();
        } else if(PlatformEnum.TM.getValue().equals(sourceType)) {
            //天猫用手机端访问拿的数据 香港服务器不可行
            httpClient= createIphoneClient();
            //httpClient= createBrowserClient();
        } else {
            httpClient = createBrowserClient();
        }

        /* 构造请求对象 */
        HttpUriRequest httpUriRequest = RequestBuilder.get().setUri(uri).build();
        /* ****************获取商品详情链接******************* */
        //执行请求，传入HttpContext，将会得到请求结果的信息
        //httpClient.execute(httpUriRequest,httpClientContext)

        HttpResponse httpResponse=httpClient.execute(httpUriRequest);
        //拿到返回的HttpResponse的"实体"
        HttpEntity result = httpResponse.getEntity();
        //System.getProperties().list(System.out);//输出当前环境属性 55555555
        /*if(result.getContentEncoding()!=null) {
            if ("gzip".equalsIgnoreCase(result.getContentEncoding().getValue())) {
                result = new GzipDecompressingEntity(result);
            } else if ("deflate".equalsIgnoreCase(result.getContentEncoding().getValue())) {
                result = new DeflateDecompressingEntity(result);
            }
        }*/
        String defaultCharset=Consts.UTF_8.name();
        if(PlatformEnum.TM.getValue().equals(sourceType)) {
            defaultCharset=Consts.UTF_8.name();
        }
        String content = EntityUtils.toString(result, defaultCharset);
        //logger.info(content);
        //关闭连接
        httpClient.close();
        return content;
    }
    /**
     * 获取url链接中的content 网页内容
     * @param url 目标url
     * @return
     * @throws URISyntaxException
     * @throws IOException
     */
    public static String getContentByUrl(String url, BasicHeader basicHeader) throws URISyntaxException, IOException {
        URI sibUri=new URIBuilder(url).build();
        //构造请求对象
        HttpUriRequest sibUriRequest = RequestBuilder.get().setUri(sibUri).build();
        //构造自定义的HttpClient对象
        CloseableHttpClient sibClient = createBrowserClient(basicHeader);
        //创建一个HttpContext对象，用来保存Cookie
        //HttpClientContext sibClientContext = HttpClientContext.create();
        //执行请求，传入HttpContext，将会得到请求结果的信息
        HttpResponse sibResponse=sibClient.execute(sibUriRequest);
        //拿到返回的HttpResponse的"实体"
        HttpEntity sibResult = sibResponse.getEntity();
        String sibContent = EntityUtils.toString(sibResult);
        //unicode 解码
        //关闭连接
        sibClient.close();
        return sibContent;
    }

    /**
     * 创建带浏览器头部的连接
     * @return
     */
    public static CloseableHttpClient createBrowserClient() {
        //构造自定义Header信息
        List<Header> headerList = Lists.newArrayList();
        headerList.add(new BasicHeader(HttpHeaders.ACCEPT, "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3"));
        headerList.add(new BasicHeader(HttpHeaders.USER_AGENT, "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36"));
        headerList.add(new BasicHeader(HttpHeaders.ACCEPT_ENCODING, "gzip, deflate, br"));
        headerList.add(new BasicHeader(HttpHeaders.CACHE_CONTROL, "max-age=0"));
        headerList.add(new BasicHeader(HttpHeaders.CONNECTION, "keep-alive"));
        headerList.add(new BasicHeader(HttpHeaders.ACCEPT_LANGUAGE, "zh-CN,zh;q=0.9"));
        headerList.add(new BasicHeader(HttpHeaders.CONTENT_TYPE, "application/json;charset=utf-8"));
        //cookie
        CookieStore cookieStore = new BasicCookieStore();
        return HttpClients.custom().setDefaultHeaders(headerList).setDefaultCookieStore(cookieStore).build();
    }

    /**
     * 创建带浏览器头部的连接
     * @return
     */
    public static CloseableHttpClient createBrowserClient(BasicHeader basicHeader) {
        //构造自定义Header信息
        List<Header> headerList = Lists.newArrayList();
        headerList.add(new BasicHeader(HttpHeaders.ACCEPT, "text/html,application/xhtml+xml,application/xml;q=0.9," +
                "image/webp,image/apng,*/*;q=0.8"));
        headerList.add(new BasicHeader(HttpHeaders.USER_AGENT, "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36"));
        headerList.add(new BasicHeader(HttpHeaders.ACCEPT_ENCODING, "gzip, deflate, br"));
        headerList.add(new BasicHeader(HttpHeaders.CACHE_CONTROL, "max-age=0"));
        headerList.add(new BasicHeader(HttpHeaders.CONNECTION, "keep-alive"));
        headerList.add(new BasicHeader(HttpHeaders.ACCEPT_LANGUAGE, "zh-CN,zh;q=0.9"));
        headerList.add(basicHeader);
        //cookie
        CookieStore cookieStore = new BasicCookieStore();
        return HttpClients.custom().setDefaultHeaders(headerList).setDefaultCookieStore(cookieStore).build();
    }

    /**
     * 创建带苹果手机头部的连接
     * @return
     */
    public static CloseableHttpClient createIphoneClient() {
        //构造自定义Header信息
        List<Header> headerList = Lists.newArrayList();
        headerList.add(new BasicHeader(HttpHeaders.ACCEPT, "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3"));
        headerList.add(new BasicHeader(HttpHeaders.USER_AGENT, "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1"));
        //headerList.add(new BasicHeader(HttpHeaders.ACCEPT_ENCODING, "gzip, deflate, br"));
        headerList.add(new BasicHeader(HttpHeaders.CACHE_CONTROL, "max-age=0"));
        headerList.add(new BasicHeader(HttpHeaders.CONNECTION, "keep-alive"));
        headerList.add(new BasicHeader(HttpHeaders.ACCEPT_LANGUAGE, "zh-CN,zh;q=0.9"));
        //cookie
        CookieStore cookieStore = new BasicCookieStore();
        return HttpClients.custom().setDefaultHeaders(headerList).setDefaultCookieStore(cookieStore).build();
    }

    //发送请求
    public static String createConnection(String url,Map<String, Object> paramMap,String charset) throws IOException {
        List<NameValuePair> formparams = setHttpParams(paramMap);
        String param = URLEncodedUtils.format(formparams, charset);
        HttpGet httpGet = new HttpGet();    //构建一个GET请求
        httpGet.setURI(URI.create(url + "?" + param));
        CloseableHttpClient httpClient=createBrowserClient();
        HttpResponse sibResponse=httpClient.execute(httpGet);
        HttpEntity sibResult = sibResponse.getEntity();//拿到返回的HttpResponse的"实体"
        return EntityUtils.toString(sibResult);
    }

    private static List<NameValuePair> setHttpParams(Map<String, Object> paramsMap) {
        List<NameValuePair> list = new ArrayList<>();
        for (Map.Entry<String, Object> stringObjectEntry : paramsMap.entrySet()) {
            String key = stringObjectEntry.getKey();
            String value = (String) stringObjectEntry.getValue();
            list.add(new BasicNameValuePair(key, value));
        }
        return list;
    }

    /**
     * 获取连接中的参数
     * @param targetUrl
     * @return
     */
    public static Map<String, String> getParamMap(String targetUrl) throws URISyntaxException, MalformedURLException {
        URL url = new URL(targetUrl);
        //构建URI
        URI uri=new URI(url.getProtocol(), url.getHost(), url.getPath(), url.getQuery(), null);
        List<NameValuePair> params = URLEncodedUtils.parse(uri, Charset.forName(Consts.UTF_8.name()));
        Map<String,String> paramMap=new HashMap<>();
        for (NameValuePair param : params) {
            paramMap.put(param.getName(),param.getValue());
        }
        return paramMap;
    }

    /**
     * 发送带body参数的post请求
     * @param url
     * @param paramMap
     * @return
     * @throws URISyntaxException
     * @throws IOException
     */
    public static String sendPostWithBodyParameter(String url,Map<String,Object> paramMap) throws  IOException {
        HttpPost httpPost = new HttpPost();    //构建一个Post请求
        httpPost.setURI(URI.create(url));
        httpPost.setHeader("Content-Type", "application/json");
        //放参数
        StringEntity entity = new StringEntity(GsonUtil.GsonString(paramMap), ContentType.APPLICATION_JSON);
        httpPost.setEntity(entity);
        //构造自定义的HttpClient对象
        CloseableHttpClient sibClient = HttpClients.custom().build();
        //执行请求，传入HttpContext，将会得到请求结果的信息
        HttpResponse sibResponse=sibClient.execute(httpPost);
        //拿到返回的HttpResponse的"实体"
        HttpEntity sibResult = sibResponse.getEntity();
        String sibContent = EntityUtils.toString(sibResult);
        //unicode 解码
        //关闭连接
        sibClient.close();
        return sibContent;
    }

    /**
     * 对链接进行url编码
     * @param url
     * @param chartSet
     * @return
     */
    public static String urlEncode(String url,String chartSet)
    {
        try {
            Matcher matcher = Pattern.compile("[^\\x00-\\xff]").matcher(url);//双字节,包括中文和中文符号[^\x00-\xff]  中文[\u4e00-\u9fa5]
            while (matcher.find()) {
                String tmp=matcher.group();
                url=url.replaceAll(tmp,java.net.URLEncoder.encode(tmp,chartSet));
            }
        } catch (UnsupportedEncodingException e) {
            logger.error("双字节编码异常：", e);
        }
        return url;
    }

}
