package it.integry.integrywmsnative.core.rest;

import com.google.gson.Gson;

import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.util.concurrent.TimeUnit;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import it.integry.integrywmsnative.core.settings.SettingsManager;
import it.integry.integrywmsnative.core.utility.UtilityGson;
import okhttp3.OkHttpClient;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;

/**
 * Created by GiuseppeS on 06/03/2018.
 */

public class RESTBuilder {

    private static final boolean ADD_LOGGER_INTERCEPTOR = false;

    public static <T> T getService(final Class<T> service) {
        return getService(service, SettingsManager.i().getServer().getProtocol(), SettingsManager.i().getServer().getHost(), SettingsManager.i().getServer().getPort(), true);

    }

    public static <T> T getService(final Class<T> service, int timeout) {
        return getService(service, SettingsManager.i().getServer().getProtocol(), SettingsManager.i().getServer().getHost(), SettingsManager.i().getServer().getPort(), true, true, timeout);

    }

    public static <T> T getService(final Class<T> service, String protocol, String host, int port, boolean addInterceptors) {
        return getService(service, protocol, host, port, addInterceptors, true, 60);
    }

    public static <T> T getService(final Class<T> service, String protocol, String host, int port, boolean addInterceptors, boolean addEmsApi) {
        return getService(service, protocol, host, port, addInterceptors, addEmsApi, 60);
    }

    public static <T> T getService(final Class<T> service, String protocol, String host, int port, boolean addInterceptors, boolean addEmsApi, int timeout) {
        OkHttpClient.Builder clientBuilder = getDefaultHttpClient();

        clientBuilder.connectTimeout(timeout, TimeUnit.SECONDS);
        clientBuilder.readTimeout(timeout, TimeUnit.SECONDS);
        clientBuilder.writeTimeout(timeout, TimeUnit.SECONDS);

        clientBuilder.retryOnConnectionFailure(true);

        if (addInterceptors) clientBuilder.addInterceptor(new HttpInterceptor());
        if (ADD_LOGGER_INTERCEPTOR) clientBuilder.addInterceptor(new HttpLoggerInterceptor());

        OkHttpClient client = clientBuilder.build();

        String endpoint = protocol + "://" + host + (port > 0 ? ":" + port : "") + "/" + (addEmsApi ? "ems-api/" : "");


        Gson gson = UtilityGson.createObject();

        Retrofit retrofit = new Retrofit.Builder().addConverterFactory(GsonConverterFactory.create(gson)).baseUrl(endpoint).client(client).build();

        return retrofit.create(service);
    }


    public static String getDefaultHost() {
        return SettingsManager.i().getServer().getHost();
    }

    public static int getDefaultPort() {
        return SettingsManager.i().getServer().getPort();
    }


    public static OkHttpClient.Builder getDefaultHttpClient() {
        TrustManager[] trustAllCerts = new TrustManager[]{
                new X509TrustManager() {
                    @Override
                    public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) {
                    }

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

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

        SSLContext sslContext = null;
        try {
            sslContext = SSLContext.getInstance("SSL");
            sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
        } catch (KeyManagementException | NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        }


        OkHttpClient.Builder client = new OkHttpClient.Builder()
                .sslSocketFactory(sslContext.getSocketFactory(), (X509TrustManager) trustAllCerts[0])
                .hostnameVerifier((hostname, session) -> true);

        return client;
    }
}
