package com.trade.common.utils.http;

import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;

import javax.net.ssl.*;

import com.trade.common.exception.HttpProcessException;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;

/**
 * 设置ssl
 * <p>
 * Copyright (c) 2022 - 2029 摸金校尉 All Rights Reserved.
 * <p>
 * Created by wanxiangZ 2022/8/15 11:07
 */
public class SSLs {

    private static final SSLHandler simpleVerifier = new SSLHandler();
    private static SSLConnectionSocketFactory sslConnFactory;
    private static SSLConnectionSocketFactory sslConnFactoryPV1_1;
    /** 采用TLSv1.2 **/
    private SSLContext sc;
    /** 采用TLSv1.1 */
    private SSLContext sslContextPV1_1;
    private static SSLs sslUtil = new SSLs();

    public static SSLs getInstance() {
        return sslUtil;
    }

    public static SSLs custom() {
        return new SSLs();
    }

    // 重写X509TrustManager类的三个方法,信任服务器证书
    private static class SSLHandler implements X509TrustManager, HostnameVerifier {

        @Override
        public java.security.cert.X509Certificate[] getAcceptedIssuers() {
            return new java.security.cert.X509Certificate[] {};
        }

        @Override
        public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) {
        }

        @Override
        public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) {
        }

        @Override
        public boolean verify(String paramString, SSLSession paramSSLSession) {
            return true;
        }
    }

    public synchronized SSLConnectionSocketFactory getSSLCONNSF(SSLProtocolVersion sslpv) throws HttpProcessException {
        if (sslpv.getName().equals(SSLProtocolVersion.TLSv1_1.getName())) {
            if (sslConnFactoryPV1_1 != null)
                return sslConnFactoryPV1_1;
            try {
                SSLContext sc = getSSLContext(sslpv);
                // sc.init(null, new TrustManager[] { simpleVerifier }, null);
                sc.init(null, new TrustManager[] {
                        simpleVerifier
                }, new java.security.SecureRandom());
                sslConnFactoryPV1_1 = new SSLConnectionSocketFactory(sc, simpleVerifier);
            } catch (KeyManagementException e) {
                throw new HttpProcessException(e);
            }
            return sslConnFactoryPV1_1;
        }
        if (sslpv.getName().equals(SSLProtocolVersion.TLSv1_2.getName())) {
            if (sslConnFactory != null)
                return sslConnFactory;
            try {
                SSLContext sc = getSSLContext(sslpv);
                // sc.init(null, new TrustManager[] { simpleVerifier }, null);
                sc.init(null, new TrustManager[] {
                        simpleVerifier
                }, new java.security.SecureRandom());
                sslConnFactory = new SSLConnectionSocketFactory(sc, simpleVerifier);
            } catch (KeyManagementException e) {
                throw new HttpProcessException(e);
            }
            return sslConnFactory;
        }
        return null;
    }

    public SSLContext getSSLContext(SSLProtocolVersion sslpv) throws HttpProcessException {
        try {
            if (sslpv.getName().equals(SSLProtocolVersion.TLSv1_1.getName())) {
                if (sslContextPV1_1 == null) {
                    sslContextPV1_1 = SSLContext.getInstance(sslpv.getName());
                }
                return sslContextPV1_1;
            }
            if (sslpv.getName().equals(SSLProtocolVersion.TLSv1_2.getName())) {
                if (sc == null) {
                    sc = SSLContext.getInstance(sslpv.getName());
                }
                return sc;
            }
            return null;
        } catch (NoSuchAlgorithmException e) {
            throw new HttpProcessException(e);
        }
    }

    /**
     * The SSL protocol version (SSLv3, TLSv1, TLSv1.1, TLSv1.2)
     *
     * @author arron
     * @version 1.0
     */
    public enum SSLProtocolVersion {

        SSL("SSL"), SSLv3("SSLv3"), TLSv1("TLSv1"), TLSv1_1("TLSv1.1"), TLSv1_2("TLSv1.2"),;

        private String name;

        SSLProtocolVersion(String name){
            this.name = name;
        }

        public String getName() {
            return this.name;
        }

        public static SSLProtocolVersion find(String name) {
            for (SSLProtocolVersion pv : SSLProtocolVersion.values()) {
                if (pv.getName().equalsIgnoreCase(name)) {
                    return pv;
                }
            }
            throw new RuntimeException("未支持当前ssl版本号：" + name);
        }
    }
}
