// 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.List;

import javax.ejb.Local;

import org.apache.log4j.Logger;

import com.cloud.host.Host;
import com.cloud.host.HostVO;
import com.cloud.info.ConsoleProxyInfo;
import com.cloud.vm.UserVmVO;

@Local(value = {ConsoleProxyManager.class})
public class AgentBasedStandaloneConsoleProxyManager extends AgentBasedConsoleProxyManager {
    private static final Logger s_logger = Logger.getLogger(AgentBasedStandaloneConsoleProxyManager.class);

    @Override
    public ConsoleProxyInfo assignProxy(long dataCenterId, long userVmId) {
        UserVmVO userVm = _userVmDao.findById(userVmId);
        if (userVm == null) {
            s_logger.warn("User VM " + userVmId + " no longer exists, return a null proxy for user vm:" + userVmId);
            return null;
        }

        HostVO host = findHost(userVm);
        if (host != null) {
            HostVO allocatedHost = null;
            /*Is there a consoleproxy agent running on the same machine?*/
            List<HostVO> hosts = _hostDao.listAllIncludingRemoved();
            for (HostVO hv : hosts) {
                if (hv.getType() == Host.Type.ConsoleProxy && hv.getPublicIpAddress().equalsIgnoreCase(host.getPublicIpAddress())) {
                    allocatedHost = hv;
                    break;
                }
            }
            if (allocatedHost == null) {
                /*Is there a consoleproxy agent running in the same pod?*/
                for (HostVO hv : hosts) {
                    if (hv.getType() == Host.Type.ConsoleProxy && hv.getPodId().equals(host.getPodId())) {
                        allocatedHost = hv;
                        break;
                    }
                }
            }
            if (allocatedHost == null) {
                if (s_logger.isDebugEnabled())
                    s_logger.debug("Failed to find a console proxy at host: " + host.getName() + " and in the pod: " + host.getPodId() + " to user vm " + userVmId);
                return null;
            }
            if (s_logger.isDebugEnabled())
                s_logger.debug("Assign standalone console proxy running at " + allocatedHost.getName() + " to user vm " + userVmId + " with public IP " +
                    allocatedHost.getPublicIpAddress());

            // only private IP, public IP, host id have meaningful values, rest of all are place-holder values
            String publicIp = allocatedHost.getPublicIpAddress();
            if (publicIp == null) {
                if (s_logger.isDebugEnabled())
                    s_logger.debug("Host " + allocatedHost.getName() + "/" + allocatedHost.getPrivateIpAddress() +
                        " does not have public interface, we will return its private IP for cosole proxy.");
                publicIp = allocatedHost.getPrivateIpAddress();
            }

            int urlPort = _consoleProxyUrlPort;
            if (allocatedHost.getProxyPort() != null && allocatedHost.getProxyPort().intValue() > 0)
                urlPort = allocatedHost.getProxyPort().intValue();

            return new ConsoleProxyInfo(_sslEnabled, publicIp, _consoleProxyPort, urlPort, _consoleProxyUrlDomain);
        } else {
            s_logger.warn("Host that VM is running is no longer available, console access to VM " + userVmId + " will be temporarily unavailable.");
        }
        return null;
    }
}
