package cn.freemud.config;

import org.apache.http.Header;
import org.apache.http.client.HttpRequestRetryHandler;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultConnectionKeepAliveStrategy;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicHeader;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Profile;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.http.converter.ByteArrayHttpMessageConverter;
import org.springframework.http.converter.FormHttpMessageConverter;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * All rights Reserved, Designed By www.freemud.com
 *
 * @version V1.0
 * @Title:
 * @Package: cn.freemud.config
 * @Descripttion:
 * @author: shuhu.hou
 * @date: 2019/4/28
 * @Copyright: 2017 www.freemud.cn Inc. All rights reserved.
 * 注意：本内容仅限于上海非码科技内部传阅，禁止外泄以及用于其他的商业目.
 */
@Component
public class RestTemplateConfig {

    /**
     * 通知第三方用的restTemplate
     *
     * @return
     */
    @Bean("openStoreRestTemplate")
    public RestTemplate openStoreRestTemplate() {
        return getRestTemplate(5000, 5000, null);
    }

    /**
     * 获取商户平台配置
     *
     * @return
     */
    @Profile({"dev", "test", "default", "pre-release"})
    @Bean("configRestTemplate")
    public RestTemplate configRestTemplateTest() {
        return getRestTemplate(5000, 5000, null);
    }

    /**
     * 获取商户平台配置
     *
     * @return
     */
    @Profile({"qa", "pro"})
    @Bean("configRestTemplate")
    @LoadBalanced
    public RestTemplate configRestTemplatePro() {
        return getRestTemplate(5000, 5000, null);
    }

    private static RestTemplate getRestTemplate(int connectTimeOut, int readTimeOut, HttpRequestRetryHandler retryHandler) {
        CloseableHttpClient httpClient;
        RestTemplate restTemplate;
        try {
            PoolingHttpClientConnectionManager pollingConnectionManager = new PoolingHttpClientConnectionManager(30, TimeUnit.SECONDS);
            // 总连接数
            pollingConnectionManager.setMaxTotal(1000);
            // 同路由的并发数
            pollingConnectionManager.setDefaultMaxPerRoute(1000);
            RequestConfig requestConfig = RequestConfig.custom()
                    // 连接不够用的等待时间，不宜过长，必须设置，比如连接不够用时，时间过长将是灾难性的
                    .setConnectionRequestTimeout(connectTimeOut)
                    // 连接超时
                    .setConnectTimeout(connectTimeOut)
                    // 数据读取超时时间
                    .setSocketTimeout(readTimeOut).build();
            HttpClientBuilder httpClientBuilder = HttpClients.custom();
            httpClientBuilder.setConnectionManager(pollingConnectionManager);
            if (retryHandler != null) {
                httpClientBuilder.setRetryHandler(retryHandler);
            }
            // 保持长连接配置，需要在头添加Keep-Alive
            httpClientBuilder.setKeepAliveStrategy(DefaultConnectionKeepAliveStrategy.INSTANCE);
            List<Header> headers = new ArrayList<>();
            headers.add(new BasicHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.16 Safari/537.36"));
            headers.add(new BasicHeader("Accept-Encoding", "gzip,deflate"));
            headers.add(new BasicHeader("Accept-Language", "zh-CN,zh;q=0.8,en;q=0.6"));
            headers.add(new BasicHeader("Connection", "keep-alive"));

            httpClientBuilder.setDefaultHeaders(headers).setDefaultRequestConfig(requestConfig);

            httpClient = httpClientBuilder.build();

            // httpClient连接配置，底层是配置RequestConfig
            HttpComponentsClientHttpRequestFactory clientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory(httpClient);
            // 缓冲请求数据，默认值是true。通过POST或者PUT大量发送数据时，建议将此属性更改为false，以免耗尽内存。
            // clientHttpRequestFactory.setBufferRequestBody(false);

            // 添加内容转换器
            List<HttpMessageConverter<?>> messageConverters = new ArrayList<>();
            messageConverters.add(new StringHttpMessageConverter(Charset.forName("UTF-8")));
            messageConverters.add(new FormHttpMessageConverter());
            //messageConverters.add(new MappingJackson2XmlHttpMessageConverter());
            messageConverters.add(new MappingJackson2HttpMessageConverter());
            messageConverters.add(new ByteArrayHttpMessageConverter());
            messageConverters.add(new FormHttpMessageConverter());

            restTemplate = new RestTemplate(messageConverters);
            restTemplate.setRequestFactory(clientHttpRequestFactory);
        } catch (Exception e) {
            System.err.println("RestTemplateUtils getRetryRestTemplate " + e);
            return new RestTemplate();
        }
        return restTemplate;
    }

}
