// 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.util.Date;
import java.util.Random;
import java.util.UUID;

import org.apache.log4j.Logger;

import com.cloud.agent.AgentManager;
import com.cloud.agent.api.AgentControlAnswer;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.ConsoleAccessAuthenticationAnswer;
import com.cloud.agent.api.ConsoleAccessAuthenticationCommand;
import com.cloud.agent.api.ConsoleProxyLoadReportCommand;
import com.cloud.agent.api.GetVncPortAnswer;
import com.cloud.agent.api.GetVncPortCommand;
import com.cloud.agent.api.StartupCommand;
import com.cloud.agent.api.StartupProxyCommand;
import com.cloud.agent.api.proxy.StartConsoleProxyAgentHttpHandlerCommand;
import com.cloud.configuration.Config;
import com.cloud.configuration.dao.ConfigurationDao;
import com.cloud.exception.AgentUnavailableException;
import com.cloud.exception.OperationTimedoutException;
import com.cloud.host.HostVO;
import com.cloud.host.Status;
import com.cloud.host.dao.HostDao;
import com.cloud.keystore.KeystoreManager;
import com.cloud.servlet.ConsoleProxyServlet;
import com.cloud.utils.Ternary;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.dao.VMInstanceDao;

/**
 * Utility class to manage interactions with agent-based console access
 * Extracted from ConsoleProxyManagerImpl so that other console proxy managers
 * can reuse
 */
public abstract class AgentHookBase implements AgentHook {
    private static final Logger s_logger = Logger.getLogger(AgentHookBase.class);

    VMInstanceDao _instanceDao;
    HostDao _hostDao;
    ConfigurationDao _configDao;
    AgentManager _agentMgr;
    KeystoreManager _ksMgr;
    final Random _random = new Random(System.currentTimeMillis());
    private String _hashKey;


    public AgentHookBase(VMInstanceDao instanceDao, HostDao hostDao, ConfigurationDao cfgDao, KeystoreManager ksMgr,
            AgentManager agentMgr) {
        this._instanceDao = instanceDao;
        this._hostDao = hostDao;
        this._agentMgr = agentMgr;
        this._configDao = cfgDao;
        this._ksMgr = ksMgr;
    }

    public String getHashKey() {
        // although we may have race condition here, database transaction
        // serialization should give us the same key
        if (_hashKey == null) {
            _hashKey =
                    _configDao.getValueAndInitIfNotExist(Config.HashKey.key(), Config.HashKey.getCategory(), UUID
                            .randomUUID().toString());
        }
        return _hashKey;
    }

    public AgentControlAnswer onConsoleAccessAuthentication(ConsoleAccessAuthenticationCommand cmd) {
        Long vmId = null;

        String ticketInUrl = cmd.getTicket();
        if (ticketInUrl == null) {
            s_logger.error("Access ticket could not be found, you could be running an old version of console proxy. vmId: "
                    + cmd.getVmId());
            return new ConsoleAccessAuthenticationAnswer(cmd, false);
        }

        if (s_logger.isDebugEnabled()) {
            s_logger.debug("Console authentication. Ticket in url for " + cmd.getHost() + ":" + cmd.getPort() + "-"
                    + cmd.getVmId() + " is " + ticketInUrl);
        }

        if (!cmd.isReauthenticating()) {
            String ticket =
                    ConsoleProxyServlet.genAccessTicket(cmd.getHost(), cmd.getPort(), cmd.getSid(), cmd.getVmId());
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Console authentication. Ticket in 1 minute boundary for " + cmd.getHost() + ":"
                        + cmd.getPort() + "-" + cmd.getVmId() + " is " + ticket);
            }

            if (!ticket.equals(ticketInUrl)) {
                Date now = new Date();
                // considering of minute round-up
                String minuteEarlyTicket =
                        ConsoleProxyServlet.genAccessTicket(cmd.getHost(), cmd.getPort(), cmd.getSid(), cmd.getVmId(),
                                new Date(now.getTime() - 60 * 1000));

                if (s_logger.isDebugEnabled()) {
                    s_logger.debug("Console authentication. Ticket in 2-minute boundary for " + cmd.getHost() + ":"
                            + cmd.getPort() + "-" + cmd.getVmId() + " is " + minuteEarlyTicket);
                }

                if (!minuteEarlyTicket.equals(ticketInUrl)) {
                    s_logger.error("Access ticket expired or has been modified. vmId: " + cmd.getVmId()
                            + "ticket in URL: " + ticketInUrl + ", tickets to check against: " + ticket + ","
                            + minuteEarlyTicket);
                    return new ConsoleAccessAuthenticationAnswer(cmd, false);
                }
            }
        }

        if (cmd.getVmId() != null && cmd.getVmId().isEmpty()) {
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Invalid vm id sent from proxy(happens when proxy session has terminated)");
            }
            return new ConsoleAccessAuthenticationAnswer(cmd, false);
        }

        VirtualMachine vm = _instanceDao.findByUuid(cmd.getVmId());
        if (vm == null) {
            vm = _instanceDao.findById(Long.parseLong(cmd.getVmId()));
        }
        if (vm == null) {
            s_logger.error("Invalid vm id " + cmd.getVmId() + " sent from console access authentication");
            return new ConsoleAccessAuthenticationAnswer(cmd, false);
        }

        if (vm.getHostId() == null) {
            s_logger.warn("VM " + vmId + " lost host info, failed authentication request");
            return new ConsoleAccessAuthenticationAnswer(cmd, false);
        }

        HostVO host = _hostDao.findById(vm.getHostId());
        if (host == null) {
            s_logger.warn("VM " + vmId + "'s host does not exist, fail authentication request");
            return new ConsoleAccessAuthenticationAnswer(cmd, false);
        }

        String sid = cmd.getSid();
        if (sid == null || !sid.equals(vm.getVncPassword())) {
            s_logger.warn("sid " + sid + " in url does not match stored sid " + vm.getVncPassword());
            return new ConsoleAccessAuthenticationAnswer(cmd, false);
        }

        if (cmd.isReauthenticating()) {
            ConsoleAccessAuthenticationAnswer authenticationAnswer = new ConsoleAccessAuthenticationAnswer(cmd, true);
            authenticationAnswer.setReauthenticating(true);

            s_logger.info("Re-authentication request, ask host " + vm.getHostId() + " for new console info");
            GetVncPortAnswer answer =
                    (GetVncPortAnswer) _agentMgr.easySend(vm.getHostId(),
                            new GetVncPortCommand(vm.getId(), vm.getInstanceName()));

            if (answer != null && answer.getResult()) {
                Ternary<String, String, String> parsedHostInfo = ConsoleProxyServlet.parseHostInfo(answer.getAddress());

                if (parsedHostInfo.second() != null && parsedHostInfo.third() != null) {

                    s_logger.info("Re-authentication result. vm: " + vm.getId() + ", tunnel url: "
                            + parsedHostInfo.second() + ", tunnel session: " + parsedHostInfo.third());

                    authenticationAnswer.setTunnelUrl(parsedHostInfo.second());
                    authenticationAnswer.setTunnelSession(parsedHostInfo.third());
                } else {
                    s_logger.info("Re-authentication result. vm: " + vm.getId() + ", host address: "
                            + parsedHostInfo.first() + ", port: " + answer.getPort());

                    authenticationAnswer.setHost(parsedHostInfo.first());
                    authenticationAnswer.setPort(answer.getPort());
                }
            } else {
                s_logger.warn("Re-authentication request failed");

                authenticationAnswer.setSuccess(false);
            }

            return authenticationAnswer;
        }

        return new ConsoleAccessAuthenticationAnswer(cmd, true);
    }

    public void startAgentHttpHandlerInVM(StartupProxyCommand startupCmd) {
        StartConsoleProxyAgentHttpHandlerCommand cmd = null;
        if (_configDao.isPremium()) {
            String storePassword = String.valueOf(_random.nextLong());
            byte[] ksBits =
                    _ksMgr.getKeystoreBits(ConsoleProxyManager.CERTIFICATE_NAME, ConsoleProxyManager.CERTIFICATE_NAME,
                            storePassword);

            assert (ksBits != null);
            if (ksBits == null) {
                s_logger.error("Could not find and construct a valid SSL certificate");
            }
            cmd = new StartConsoleProxyAgentHttpHandlerCommand(ksBits, storePassword);
            cmd.setEncryptorPassword(getHashKey());
        } else {
            cmd = new StartConsoleProxyAgentHttpHandlerCommand();
            cmd.setEncryptorPassword(getHashKey());
        }

        try {

            HostVO consoleProxyHost = findConsoleProxyHost(startupCmd);

            assert (consoleProxyHost != null);

            Answer answer = _agentMgr.send(consoleProxyHost.getId(), cmd);
            if (answer == null || !answer.getResult()) {
                s_logger.error("Console proxy agent reported that it failed to execute http handling startup command");
            } else {
                s_logger.info("Successfully sent out command to start HTTP handling in console proxy agent");
            }
        } catch (AgentUnavailableException e) {
            s_logger.error("Unable to send http handling startup command to the console proxy resource for proxy:"
                    + startupCmd.getProxyVmId(), e);
        } catch (OperationTimedoutException e) {
            s_logger.error(
                    "Unable to send http handling startup command(time out) to the console proxy resource for proxy:"
                            + startupCmd.getProxyVmId(), e);
        } catch (OutOfMemoryError e) {
            s_logger.error("Unrecoverable OutOfMemory Error, exit and let it be re-launched");
            System.exit(1);
        } catch (Exception e) {
            s_logger.error(
                    "Unexpected exception when sending http handling startup command(time out) to the console proxy resource for proxy:"
                            + startupCmd.getProxyVmId(), e);
        }
    }

    protected abstract HostVO findConsoleProxyHost(StartupProxyCommand cmd);

    @Override
    public void onLoadReport(ConsoleProxyLoadReportCommand cmd) {
        // no-op since we do not auto-scale
    }

    @Override
    public void onAgentConnect(HostVO host, StartupCommand cmd) {
        // no-op
    }

    @Override
    public void onAgentDisconnect(long agentId, Status state) {
        // no-op since we do not autoscale
    }
}
