package cn.com.qmth.examcloud.tool.utils;

import okhttp3.ConnectionPool;
import okhttp3.OkHttpClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.net.ssl.*;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.concurrent.TimeUnit;

public class HttpClientBuilder {

    private static final Logger log = LoggerFactory.getLogger(HttpClientBuilder.class);

    private static OkHttpClient client;

    static {
        client = Client.INSTANCE.getInstance();
    }

    public static OkHttpClient getClient() {
        return client;
    }

    private enum Client {

        INSTANCE;

        Client() {
            ConnectionPool connectionPool = new ConnectionPool(10, 5L, TimeUnit.MINUTES);

            instance = new OkHttpClient
                    .Builder()
                    // .retryOnConnectionFailure(false)
                    .connectionPool(connectionPool)
                    .connectTimeout(30, TimeUnit.SECONDS)
                    .readTimeout(60, TimeUnit.SECONDS)
                    .writeTimeout(60, TimeUnit.SECONDS)
                    .sslSocketFactory(sslSocketFactory(), trustAllCert())
                    .hostnameVerifier(trustAllHost())
                    .build();

            log.debug("OkHttpClient init..");
        }

        private OkHttpClient instance;

        public OkHttpClient getInstance() {
            return instance;
        }
    }

    private static SSLSocketFactory sslSocketFactory() {
        try {
            SSLContext sslContext = SSLContext.getInstance("TLS");
            sslContext.init(null, new TrustManager[]{trustAllCert()}, new SecureRandom());
            return sslContext.getSocketFactory();
        } catch (Exception e) {
            log.error(e.getMessage());
            throw new RuntimeException(e);
        }
    }

    private static HostnameVerifier trustAllHost() {
        return (hostname, sslSession) -> true;
    }

    private static X509TrustManager trustAllCert() {
        return new X509TrustManager() {

            @Override
            public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {

            }

            @Override
            public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {

            }

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

}
