/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.ignite.console.agent;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.ProtectionDomain;
import java.security.cert.X509Certificate;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLParameters;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsonorg.JsonOrgModule;
import io.socket.client.Ack;
import okhttp3.ConnectionSpec;
import org.apache.ignite.internal.util.typedef.F;
import org.apache.ignite.ssl.SSLContextWrapper;
import org.apache.log4j.Logger;
import org.json.JSONArray;
import org.json.JSONObject;

/**
 * Utility methods.
 */
public class AgentUtils {
    /** */
    private static final Logger log = Logger.getLogger(AgentUtils.class.getName());

    /** */
    private static final char[] EMPTY_PWD = new char[0];

    /** JSON object mapper. */
    private static final ObjectMapper MAPPER = new ObjectMapper();

    static {
        // Register special module with basic serializers.
        MAPPER.registerModule(new JsonOrgModule());
    }

    /** */
    private static final Ack NOOP_CB = args -> {
        if (args != null && args.length > 0 && args[0] instanceof Throwable)
            log.error("Failed to execute request on agent.", (Throwable)args[0]);
        else
            log.info("Request on agent successfully executed " + Arrays.toString(args));
    };

    /**
     * Default constructor.
     */
    private AgentUtils() {
        // No-op.
    }

    /**
     * @param path Path to normalize.
     * @return Normalized file path.
     */
    public static String normalizePath(String path) {
        return path != null ? path.replace('\\', '/') : null;
    }

    /**
     * @return App folder.
     */
    public static File getAgentHome() {
        try {
            ProtectionDomain domain = AgentLauncher.class.getProtectionDomain();

            // Should not happen, but to make sure our code is not broken.
            if (domain == null || domain.getCodeSource() == null || domain.getCodeSource().getLocation() == null) {
                log.warn("Failed to resolve agent jar location!");

                return null;
            }

            // Resolve path to class-file.
            URI classesUri = domain.getCodeSource().getLocation().toURI();

            boolean win = System.getProperty("os.name").toLowerCase().contains("win");

            // Overcome UNC path problem on Windows (http://www.tomergabel.com/JavaMishandlesUNCPathsOnWindows.aspx)
            if (win && classesUri.getAuthority() != null)
                classesUri = new URI(classesUri.toString().replace("file://", "file:/"));

            return new File(classesUri).getParentFile();
        }
        catch (URISyntaxException | SecurityException ignored) {
            log.warn("Failed to resolve agent jar location!");

            return null;
        }
    }

    /**
     * Gets file associated with path.
     * <p>
     * First check if path is relative to agent home.
     * If not, check if path is absolute.
     * If all checks fail, then {@code null} is returned.
     * <p>
     *
     * @param path Path to resolve.
     * @return Resolved path as file, or {@code null} if path cannot be resolved.
     */
    public static File resolvePath(String path) {
        assert path != null;

        File home = getAgentHome();

        if (home != null) {
            File file = new File(home, normalizePath(path));

            if (file.exists())
                return file;
        }

        // 2. Check given path as absolute.
        File file = new File(path);

        if (file.exists())
            return file;

        return null;
    }

    /**
     * Get callback from handler arguments.
     *
     * @param args Arguments.
     * @return Callback or noop callback.
     */
    public static Ack safeCallback(Object[] args) {
        boolean hasCb = args != null && args.length > 0 && args[args.length - 1] instanceof Ack;

        return hasCb ? (Ack)args[args.length - 1] : NOOP_CB;
    }

    /**
     * Remove callback from handler arguments.
     *
     * @param args Arguments.
     * @return Arguments without callback.
     */
    public static Object[] removeCallback(Object[] args) {
        boolean hasCb = args != null && args.length > 0 && args[args.length - 1] instanceof Ack;

        return hasCb ? Arrays.copyOf(args, args.length - 1) : args;
    }

    /**
     * Map java object to JSON object.
     *
     * @param obj Java object.
     * @return {@link JSONObject} or {@link JSONArray}.
     * @throws IllegalArgumentException If conversion fails due to incompatible type.
     */
    public static Object toJSON(Object obj) {
        if (obj instanceof Iterable)
            return MAPPER.convertValue(obj, JSONArray.class);

        return MAPPER.convertValue(obj, JSONObject.class);
    }

    /**
     * Map JSON object to java object.
     *
     * @param obj {@link JSONObject} or {@link JSONArray}.
     * @param toValType Expected value type.
     * @return Mapped object type of {@link T}.
     * @throws IllegalArgumentException If conversion fails due to incompatible type.
     */
    public static <T> T fromJSON(Object obj, Class<T> toValType) throws IllegalArgumentException {
        return MAPPER.convertValue(obj, toValType);
    }

    /**
     * @param pathToJks Path to java key store file.
     * @param pwd Key store password.
     * @return Key store.
     * @throws GeneralSecurityException If failed to load key store.
     * @throws IOException If failed to load key store file content.
     */
    private static KeyStore keyStore(String pathToJks, char[] pwd) throws GeneralSecurityException, IOException {
        KeyStore keyStore = KeyStore.getInstance("JKS");
        keyStore.load(new FileInputStream(pathToJks), pwd);

        return keyStore;
    }

    /**
     * @param keyStorePath Path to key store.
     * @param keyStorePwd Key store password.
     * @return Key managers.
     * @throws GeneralSecurityException If failed to load key store.
     * @throws IOException If failed to load key store file content.
     */
    private static KeyManager[] keyManagers(String keyStorePath, String keyStorePwd)
        throws GeneralSecurityException, IOException {
        if (keyStorePath == null)
            return null;

        char[] keyPwd = keyStorePwd != null ? keyStorePwd.toCharArray() : EMPTY_PWD;

        KeyStore keyStore = keyStore(keyStorePath, keyPwd);

        KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
        kmf.init(keyStore, keyPwd);

        return kmf.getKeyManagers();
    }

    /**
     * @param trustAll {@code true} If we trust to self-signed sertificates.
     * @param trustStorePath Path to trust store file.
     * @param trustStorePwd Trust store password.
     * @return Trust manager
     * @throws GeneralSecurityException If failed to load trust store.
     * @throws IOException If failed to load trust store file content.
     */
    public static X509TrustManager trustManager(boolean trustAll, String trustStorePath, String trustStorePwd)
        throws GeneralSecurityException, IOException {
        if (trustAll)
            return disabledTrustManager();

        if (trustStorePath == null)
            return null;

        char[] trustPwd = trustStorePwd != null ? trustStorePwd.toCharArray() : EMPTY_PWD;
        KeyStore trustKeyStore = keyStore(trustStorePath, trustPwd);

        TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
        tmf.init(trustKeyStore);

        TrustManager[] trustMgrs = tmf.getTrustManagers();

        return (X509TrustManager)Arrays.stream(trustMgrs)
            .filter(tm -> tm instanceof X509TrustManager)
            .findFirst()
            .orElseThrow(() -> new IllegalStateException("X509TrustManager manager not found"));
    }

    /**
     * Create SSL socket factory.
     *
     * @param keyStorePath Path to key store.
     * @param keyStorePwd Key store password.
     * @param trustMgr Trust manager.
     * @param cipherSuites Optional cipher suites.
     * @throws GeneralSecurityException If failed to load trust store.
     * @throws IOException If failed to load store file content.
     */
    public static SSLSocketFactory sslSocketFactory(
        String keyStorePath, String keyStorePwd,
        X509TrustManager trustMgr,
        List<String> cipherSuites
    ) throws GeneralSecurityException, IOException {
        KeyManager[] keyMgrs = keyManagers(keyStorePath, keyStorePwd);

        if (keyMgrs == null && trustMgr == null)
            return null;

        SSLContext ctx = SSLContext.getInstance("TLS");

        if (!F.isEmpty(cipherSuites))
            ctx = new SSLContextWrapper(ctx, new SSLParameters(cipherSuites.toArray(new String[0])));

        ctx.init(keyMgrs, new TrustManager[] {trustMgr}, null);

        return ctx.getSocketFactory();
    }

    /**
     * Create SSL configuration.
     *
     * @param cipherSuites SSL cipher suites.
     */
    public static List<ConnectionSpec> sslConnectionSpec(List<String> cipherSuites) {
        return Collections.singletonList(new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS)
            .cipherSuites(cipherSuites.toArray(new String[0]))
            .build());
    }

    /**
     * Create a trust manager that trusts all certificates.
     */
    private static X509TrustManager disabledTrustManager() {
        return new X509TrustManager() {
            /** {@inheritDoc} */
            @Override public X509Certificate[] getAcceptedIssuers() {
                return new X509Certificate[0];
            }

            /** {@inheritDoc} */
            @Override public void checkClientTrusted(X509Certificate[] certs, String authType) {
                // No-op.
            }

            /** {@inheritDoc} */
            @Override public void checkServerTrusted(X509Certificate[] certs, String authType) {
                // No-op.
            }
        };
    }
}
