// 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 com.cloud.consoleproxy;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.InetSocketAddress;
import java.net.URISyntaxException;
import java.net.URL;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Hashtable;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.Executor;

import org.apache.commons.codec.binary.Base64;
import org.apache.log4j.xml.DOMConfigurator;

import com.google.gson.Gson;
import com.sun.net.httpserver.HttpServer;

import com.cloud.consoleproxy.util.Logger;
import com.cloud.utils.PropertiesUtil;

/**
 *
 * ConsoleProxy, singleton class that manages overall activities in console proxy process. To make legacy code work, we still
 */
public class ConsoleProxy {
    private static final Logger s_logger = Logger.getLogger(ConsoleProxy.class);

    public static final int KEYBOARD_RAW = 0;
    public static final int KEYBOARD_COOKED = 1;

    public static final int VIEWER_LINGER_SECONDS = 180;

    public static Object context;

    // this has become more ugly, to store keystore info passed from management server (we now use management server managed keystore to support
    // dynamically changing to customer supplied certificate)
    public static byte[] ksBits;
    public static String ksPassword;

    public static Method authMethod;
    public static Method reportMethod;
    public static Method ensureRouteMethod;

    static Hashtable<String, ConsoleProxyClient> connectionMap = new Hashtable<String, ConsoleProxyClient>();
    static int httpListenPort = 80;
    static int httpCmdListenPort = 8001;
    static int reconnectMaxRetry = 5;
    static int readTimeoutSeconds = 90;
    static int keyboardType = KEYBOARD_RAW;
    static String factoryClzName;
    static boolean standaloneStart = false;

    static String encryptorPassword = genDefaultEncryptorPassword();

    private static String genDefaultEncryptorPassword() {
        try {
            SecureRandom random = SecureRandom.getInstance("SHA1PRNG");

            byte[] randomBytes = new byte[16];
            random.nextBytes(randomBytes);
            return Base64.encodeBase64String(randomBytes);
        } catch (NoSuchAlgorithmException e) {
            s_logger.error("Unexpected exception ", e);
            assert (false);
        }

        return "Dummy";
    }

    private static void configLog4j() {
        URL configUrl = System.class.getResource("/conf/log4j-cloud.xml");
        if (configUrl == null)
            configUrl = ClassLoader.getSystemResource("log4j-cloud.xml");

        if (configUrl == null)
            configUrl = ClassLoader.getSystemResource("conf/log4j-cloud.xml");

        if (configUrl != null) {
            try {
                System.out.println("Configure log4j using " + configUrl.toURI().toString());
            } catch (URISyntaxException e1) {
                e1.printStackTrace();
            }

            try {
                File file = new File(configUrl.toURI());

                System.out.println("Log4j configuration from : " + file.getAbsolutePath());
                DOMConfigurator.configureAndWatch(file.getAbsolutePath(), 10000);
            } catch (URISyntaxException e) {
                System.out.println("Unable to convert log4j configuration Url to URI");
            }
            // DOMConfigurator.configure(configUrl);
        } else {
            System.out.println("Configure log4j with default properties");
        }
    }

    private static void configProxy(Properties conf) {
        s_logger.info("Configure console proxy...");
        for (Object key : conf.keySet()) {
            s_logger.info("Property " + (String)key + ": " + conf.getProperty((String)key));
        }

        String s = conf.getProperty("consoleproxy.httpListenPort");
        if (s != null) {
            httpListenPort = Integer.parseInt(s);
            s_logger.info("Setting httpListenPort=" + s);
        }

        s = conf.getProperty("premium");
        if (s != null && s.equalsIgnoreCase("true")) {
            s_logger.info("Premium setting will override settings from consoleproxy.properties, listen at port 443");
            httpListenPort = 443;
            factoryClzName = "com.cloud.consoleproxy.ConsoleProxySecureServerFactoryImpl";
        } else {
            factoryClzName = ConsoleProxyBaseServerFactoryImpl.class.getName();
        }

        s = conf.getProperty("consoleproxy.httpCmdListenPort");
        if (s != null) {
            httpCmdListenPort = Integer.parseInt(s);
            s_logger.info("Setting httpCmdListenPort=" + s);
        }

        s = conf.getProperty("consoleproxy.reconnectMaxRetry");
        if (s != null) {
            reconnectMaxRetry = Integer.parseInt(s);
            s_logger.info("Setting reconnectMaxRetry=" + reconnectMaxRetry);
        }

        s = conf.getProperty("consoleproxy.readTimeoutSeconds");
        if (s != null) {
            readTimeoutSeconds = Integer.parseInt(s);
            s_logger.info("Setting readTimeoutSeconds=" + readTimeoutSeconds);
        }
    }

    public static ConsoleProxyServerFactory getHttpServerFactory() {
        try {
            Class<?> clz = Class.forName(factoryClzName);
            try {
                ConsoleProxyServerFactory factory = (ConsoleProxyServerFactory)clz.newInstance();
                factory.init(ConsoleProxy.ksBits, ConsoleProxy.ksPassword);
                return factory;
            } catch (InstantiationException e) {
                s_logger.error(e.getMessage(), e);
                return null;
            } catch (IllegalAccessException e) {
                s_logger.error(e.getMessage(), e);
                return null;
            }
        } catch (ClassNotFoundException e) {
            s_logger.warn("Unable to find http server factory class: " + factoryClzName);
            return new ConsoleProxyBaseServerFactoryImpl();
        }
    }

    public static ConsoleProxyAuthenticationResult authenticateConsoleAccess(ConsoleProxyClientParam param, boolean reauthentication) {

        ConsoleProxyAuthenticationResult authResult = new ConsoleProxyAuthenticationResult();
        authResult.setSuccess(true);
        authResult.setReauthentication(reauthentication);
        authResult.setHost(param.getClientHostAddress());
        authResult.setPort(param.getClientHostPort());

        if (standaloneStart) {
            return authResult;
        }

        if (authMethod != null) {
            Object result;
            try {
                result =
                        authMethod.invoke(ConsoleProxy.context, param.getClientHostAddress(), String.valueOf(param.getClientHostPort()), param.getClientTag(),
                                param.getClientHostPassword(), param.getTicket(), new Boolean(reauthentication));
            } catch (IllegalAccessException e) {
                s_logger.error("Unable to invoke authenticateConsoleAccess due to IllegalAccessException" + " for vm: " + param.getClientTag(), e);
                authResult.setSuccess(false);
                return authResult;
            } catch (InvocationTargetException e) {
                s_logger.error("Unable to invoke authenticateConsoleAccess due to InvocationTargetException " + " for vm: " + param.getClientTag(), e);
                authResult.setSuccess(false);
                return authResult;
            }

            if (result != null && result instanceof String) {
                authResult = new Gson().fromJson((String)result, ConsoleProxyAuthenticationResult.class);
            } else {
                s_logger.error("Invalid authentication return object " + result + " for vm: " + param.getClientTag() + ", decline the access");
                authResult.setSuccess(false);
            }
        } else {
            s_logger.warn("Private channel towards management server is not setup. Switch to offline mode and allow access to vm: " + param.getClientTag());
        }

        return authResult;
    }

    public static void reportLoadInfo(String gsonLoadInfo) {
        if (reportMethod != null) {
            try {
                reportMethod.invoke(ConsoleProxy.context, gsonLoadInfo);
            } catch (IllegalAccessException e) {
                s_logger.error("Unable to invoke reportLoadInfo due to " + e.getMessage());
            } catch (InvocationTargetException e) {
                s_logger.error("Unable to invoke reportLoadInfo due to " + e.getMessage());
            }
        } else {
            s_logger.warn("Private channel towards management server is not setup. Switch to offline mode and ignore load report");
        }
    }

    public static void ensureRoute(String address) {
        if (ensureRouteMethod != null) {
            try {
                ensureRouteMethod.invoke(ConsoleProxy.context, address);
            } catch (IllegalAccessException e) {
                s_logger.error("Unable to invoke ensureRoute due to " + e.getMessage());
            } catch (InvocationTargetException e) {
                s_logger.error("Unable to invoke ensureRoute due to " + e.getMessage());
            }
        } else {
            s_logger.warn("Unable to find ensureRoute method, console proxy agent is not up to date");
        }
    }

    public static void startWithContext(Properties conf, Object context, byte[] ksBits, String ksPassword) {
        s_logger.info("Start console proxy with context");
        if (conf != null) {
            for (Object key : conf.keySet()) {
                s_logger.info("Context property " + (String)key + ": " + conf.getProperty((String)key));
            }
        }

        configLog4j();
        Logger.setFactory(new ConsoleProxyLoggerFactory());

        // Using reflection to setup private/secure communication channel towards management server
        ConsoleProxy.context = context;
        ConsoleProxy.ksBits = ksBits;
        ConsoleProxy.ksPassword = ksPassword;
        try {
            Class<?> contextClazz = Class.forName("com.cloud.agent.resource.consoleproxy.ConsoleProxyResource");
            authMethod = contextClazz.getDeclaredMethod("authenticateConsoleAccess", String.class, String.class, String.class, String.class, String.class, Boolean.class);
            reportMethod = contextClazz.getDeclaredMethod("reportLoadInfo", String.class);
            ensureRouteMethod = contextClazz.getDeclaredMethod("ensureRoute", String.class);
        } catch (SecurityException e) {
            s_logger.error("Unable to setup private channel due to SecurityException", e);
        } catch (NoSuchMethodException e) {
            s_logger.error("Unable to setup private channel due to NoSuchMethodException", e);
        } catch (IllegalArgumentException e) {
            s_logger.error("Unable to setup private channel due to IllegalArgumentException", e);
        } catch (ClassNotFoundException e) {
            s_logger.error("Unable to setup private channel due to ClassNotFoundException", e);
        }

        // merge properties from conf file
        InputStream confs = ConsoleProxy.class.getResourceAsStream("/conf/consoleproxy.properties");
        Properties props = new Properties();
        if (confs == null) {
            final File file = PropertiesUtil.findConfigFile("consoleproxy.properties");
            if (file == null)
                s_logger.info("Can't load consoleproxy.properties from classpath, will use default configuration");
            else
                try {
                    confs = new FileInputStream(file);
                } catch (FileNotFoundException e) {
                    s_logger.info("Ignoring file not found exception and using defaults");
                }
        }
        if (confs != null) {
            try {
                props.load(confs);

                for (Object key : props.keySet()) {
                    // give properties passed via context high priority, treat properties from consoleproxy.properties
                    // as default values
                    if (conf.get(key) == null)
                        conf.put(key, props.get(key));
                }
            } catch (Exception e) {
                s_logger.error(e.toString(), e);
            }
        }

        start(conf);
    }

    public static void start(Properties conf) {
        System.setProperty("java.awt.headless", "true");

        configProxy(conf);

        ConsoleProxyServerFactory factory = getHttpServerFactory();
        if (factory == null) {
            s_logger.error("Unable to load console proxy server factory");
            System.exit(1);
        }

        if (httpListenPort != 0) {
            startupHttpMain();
        } else {
            s_logger.error("A valid HTTP server port is required to be specified, please check your consoleproxy.httpListenPort settings");
            System.exit(1);
        }

        if (httpCmdListenPort > 0) {
            startupHttpCmdPort();
        } else {
            s_logger.info("HTTP command port is disabled");
        }

        ConsoleProxyGCThread cthread = new ConsoleProxyGCThread(connectionMap);
        cthread.setName("Console Proxy GC Thread");
        cthread.start();
    }

    private static void startupHttpMain() {
        try {
            ConsoleProxyServerFactory factory = getHttpServerFactory();
            if (factory == null) {
                s_logger.error("Unable to load HTTP server factory");
                System.exit(1);
            }

            HttpServer server = factory.createHttpServerInstance(httpListenPort);
            server.createContext("/getscreen", new ConsoleProxyThumbnailHandler());
            server.createContext("/resource/", new ConsoleProxyResourceHandler());
            server.createContext("/ajax", new ConsoleProxyAjaxHandler());
            server.createContext("/ajaximg", new ConsoleProxyAjaxImageHandler());
            server.setExecutor(new ThreadExecutor()); // creates a default executor
            server.start();
        } catch (Exception e) {
            s_logger.error(e.getMessage(), e);
            System.exit(1);
        }
    }

    private static void startupHttpCmdPort() {
        try {
            s_logger.info("Listening for HTTP CMDs on port " + httpCmdListenPort);
            HttpServer cmdServer = HttpServer.create(new InetSocketAddress(httpCmdListenPort), 2);
            cmdServer.createContext("/cmd", new ConsoleProxyCmdHandler());
            cmdServer.setExecutor(new ThreadExecutor()); // creates a default executor
            cmdServer.start();
        } catch (Exception e) {
            s_logger.error(e.getMessage(), e);
            System.exit(1);
        }
    }

    public static void main(String[] argv) {
        standaloneStart = true;
        configLog4j();
        Logger.setFactory(new ConsoleProxyLoggerFactory());

        InputStream confs = ConsoleProxy.class.getResourceAsStream("/conf/consoleproxy.properties");
        Properties conf = new Properties();
        if (confs == null) {
            s_logger.info("Can't load consoleproxy.properties from classpath, will use default configuration");
        } else {
            try {
                conf.load(confs);
            } catch (Exception e) {
                s_logger.error(e.toString(), e);
            } finally {
                try {
                    confs.close();
                } catch (IOException ioex) {
                    s_logger.error(ioex.toString(), ioex);
                }
            }
        }
        start(conf);
    }

    public static ConsoleProxyClient getVncViewer(ConsoleProxyClientParam param) throws Exception {
        ConsoleProxyClient viewer = null;

        boolean reportLoadChange = false;
        String clientKey = param.getClientMapKey();
        synchronized (connectionMap) {
            viewer = connectionMap.get(clientKey);
            if (viewer == null) {
                viewer = getClient(param);
                viewer.initClient(param);
                connectionMap.put(clientKey, viewer);
                s_logger.info("Added viewer object " + viewer);

                reportLoadChange = true;
            } else if (!viewer.isFrontEndAlive()) {
                s_logger.info("The rfb thread died, reinitializing the viewer " + viewer);
                viewer.initClient(param);
            } else if (!param.getClientHostPassword().equals(viewer.getClientHostPassword())) {
                s_logger.warn("Bad sid detected(VNC port may be reused). sid in session: " + viewer.getClientHostPassword() + ", sid in request: " +
                        param.getClientHostPassword());
                viewer.initClient(param);
            }
        }

        if (reportLoadChange) {
            ConsoleProxyClientStatsCollector statsCollector = getStatsCollector();
            String loadInfo = statsCollector.getStatsReport();
            reportLoadInfo(loadInfo);
            if (s_logger.isDebugEnabled())
                s_logger.debug("Report load change : " + loadInfo);
        }

        return viewer;
    }

    public static ConsoleProxyClient getAjaxVncViewer(ConsoleProxyClientParam param, String ajaxSession) throws Exception {

        boolean reportLoadChange = false;
        String clientKey = param.getClientMapKey();
        synchronized (connectionMap) {
            ConsoleProxyClient viewer = connectionMap.get(clientKey);
            if (viewer == null) {
                authenticationExternally(param);
                viewer = getClient(param);
                viewer.initClient(param);

                connectionMap.put(clientKey, viewer);
                s_logger.info("Added viewer object " + viewer);
                reportLoadChange = true;
            } else {
                // protected against malicous attack by modifying URL content
                if (ajaxSession != null) {
                    long ajaxSessionIdFromUrl = Long.parseLong(ajaxSession);
                    if (ajaxSessionIdFromUrl != viewer.getAjaxSessionId())
                        throw new AuthenticationException("Cannot use the existing viewer " + viewer + ": modified AJAX session id");
                }

                if (param.getClientHostPassword() == null || param.getClientHostPassword().isEmpty() ||
                        !param.getClientHostPassword().equals(viewer.getClientHostPassword()))
                    throw new AuthenticationException("Cannot use the existing viewer " + viewer + ": bad sid");

                if (!viewer.isFrontEndAlive()) {

                    authenticationExternally(param);
                    viewer.initClient(param);
                    reportLoadChange = true;
                }
            }

            if (reportLoadChange) {
                ConsoleProxyClientStatsCollector statsCollector = getStatsCollector();
                String loadInfo = statsCollector.getStatsReport();
                reportLoadInfo(loadInfo);
                if (s_logger.isDebugEnabled())
                    s_logger.debug("Report load change : " + loadInfo);
            }
            return viewer;
        }
    }

    private static ConsoleProxyClient getClient(ConsoleProxyClientParam param) {
        if (param.getHypervHost() != null) {
            return new ConsoleProxyRdpClient();
        } else {
            return new ConsoleProxyVncClient();
        }
    }

    public static void removeViewer(ConsoleProxyClient viewer) {
        synchronized (connectionMap) {
            for (Map.Entry<String, ConsoleProxyClient> entry : connectionMap.entrySet()) {
                if (entry.getValue() == viewer) {
                    connectionMap.remove(entry.getKey());
                    return;
                }
            }
        }
    }

    public static ConsoleProxyClientStatsCollector getStatsCollector() {
        return new ConsoleProxyClientStatsCollector(connectionMap);
    }

    public static void authenticationExternally(ConsoleProxyClientParam param) throws AuthenticationException {
        ConsoleProxyAuthenticationResult authResult = authenticateConsoleAccess(param, false);

        if (authResult == null || !authResult.isSuccess()) {
            s_logger.warn("External authenticator failed authencation request for vm " + param.getClientTag() + " with sid " + param.getClientHostPassword());

            throw new AuthenticationException("External authenticator failed request for vm " + param.getClientTag() + " with sid " + param.getClientHostPassword());
        }
    }

    public static ConsoleProxyAuthenticationResult reAuthenticationExternally(ConsoleProxyClientParam param) {
        return authenticateConsoleAccess(param, true);
    }

    public static String getEncryptorPassword() {
        return encryptorPassword;
    }

    public static void setEncryptorPassword(String password) {
        encryptorPassword = password;
    }

    static class ThreadExecutor implements Executor {
        @Override
        public void execute(Runnable r) {
            new Thread(r).start();
        }
    }
}
