// 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.util.Hashtable;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.Executor;

import org.apache.log4j.xml.DOMConfigurator;

import com.cloud.consoleproxy.util.Logger;
import com.cloud.utils.PropertiesUtil;
import com.cloud.utils.ReflectUtil;
import com.google.gson.Gson;
import com.sun.net.httpserver.HttpServer;

/**
 *
 * 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 = "Dummy";

    private static void configLog4j() {
        final ClassLoader loader = ReflectUtil.getClassLoaderForName("conf");
        URL configUrl = loader.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, String password) {
        setEncryptorPassword(password);
        configLog4j();
        Logger.setFactory(new ConsoleProxyLoggerFactory());
        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));
            }
        }

        // Using reflection to setup private/secure communication channel towards management server
        ConsoleProxy.context = context;
        ConsoleProxy.ksBits = ksBits;
        ConsoleProxy.ksPassword = ksPassword;
        try {
            final ClassLoader loader = ReflectUtil.getClassLoaderForName("agent");
            Class<?> contextClazz = loader.loadClass("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);
            }
        }
        try {
            confs.close();
        } catch (IOException e) {
            s_logger.error("Failed to close consolepropxy.properties : " + 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() {
        synchronized (connectionMap) {
            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();
        }
    }
}
