package com.inspect.ivs.util;

import io.netty.handler.ssl.SslContext;
import io.netty.handler.ssl.SslContextBuilder;
import io.netty.handler.ssl.util.InsecureTrustManagerFactory;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.security.KeyStore;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SNIMatcher;
import javax.net.ssl.SNIServerName;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLParameters;
import javax.net.ssl.TrustManagerFactory;

import org.springframework.http.client.reactive.ClientHttpConnector;
import org.springframework.http.client.reactive.ReactorClientHttpConnector;
import org.springframework.web.reactive.function.client.ExchangeStrategies;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.netty.http.client.HttpClient;

public class WebClientUtils {
    public static List<String> domains = new ArrayList();

    public static void refreshDomains() throws IOException {
        domains.clear();
        BufferedReader reader = null;

        try {
            InputStream resourceAsStream = WebClientUtils.class.getClassLoader().getResourceAsStream("domains");
            if(resourceAsStream != null) {
                reader = new BufferedReader(new InputStreamReader(resourceAsStream));

                String domain;
                while ((domain = reader.readLine()) != null) {
                    domains.add(domain);
                }
            }

        } finally {
            if (reader != null)
                reader.close();
        }

    }

    public static WebClient create() {
        try {
            return WebClient.builder().exchangeStrategies(ExchangeStrategies.builder().codecs((conf) -> {
                conf.defaultCodecs().maxInMemorySize(10485760);
            }).build()).clientConnector(getClientHttpConnector((KeyStore) null, (String) null, (KeyStore) null)).build();
        } catch (Throwable var1) {
//         throw var1;
            return null;
        }
    }

    private static ClientHttpConnector getClientHttpConnector(KeyStore keyStore, String keyStorePassword, KeyStore trustStore) throws Exception {
        SslContextBuilder builder = SslContextBuilder.forClient();
        if (keyStore != null) {
            KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("SunX509");
            keyManagerFactory.init(keyStore, keyStorePassword.toCharArray());
            builder.keyManager(keyManagerFactory);
        }

        if (trustStore != null) {
            TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance("SunX509");
            trustManagerFactory.init(trustStore);
            builder.trustManager(trustManagerFactory);
        } else {
            builder.trustManager(InsecureTrustManagerFactory.INSTANCE);
        }

        SslContext sslContext = builder.build();
        HttpClient httpClient = HttpClient.create().secure((sslContextSpec) -> {
            sslContextSpec.sslContext(sslContext).handlerConfigurator((handler) -> {
                SSLEngine engine = handler.engine();
                List<SNIMatcher> matchers = new LinkedList();
                SNIMatcher matcher = new SNIMatcher(0) {
                    public boolean matches(SNIServerName serverName) {
                        return WebClientUtils.domains.size() == 0 ? true : WebClientUtils.domains.contains(serverName);
                    }
                };
                matchers.add(matcher);
                SSLParameters params = new SSLParameters();
                params.setSNIMatchers(matchers);
                engine.setSSLParameters(params);
            });
        });
        ClientHttpConnector connector = new ReactorClientHttpConnector(httpClient);
        return connector;
    }

    private static KeyStore getkeyStore(String type, String filePath, String password) {
        KeyStore keySotre = null;
        FileInputStream in = null;

        try {
            keySotre = KeyStore.getInstance(type);
            in = new FileInputStream(filePath);
            keySotre.load(in, password.toCharArray());
        } catch (Exception var14) {
            var14.printStackTrace();
        } finally {
            try {
                in.close();
            } catch (IOException var13) {
                var13.printStackTrace();
            }

        }

        return keySotre;
    }
}
