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

import java.util.List;
import java.util.Map;

import javax.ejb.Local;
import javax.inject.Inject;
import javax.naming.ConfigurationException;

import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;

import com.cloud.agent.AgentManager;
import com.cloud.agent.StartupCommandProcessor;
import com.cloud.agent.api.StartupCommand;
import com.cloud.agent.api.StartupRoutingCommand;
import com.cloud.agent.api.StartupStorageCommand;
import com.cloud.agent.manager.authn.AgentAuthnException;
import com.cloud.configuration.ConfigurationManager;
import com.cloud.configuration.ZoneConfig;
import com.cloud.configuration.dao.ConfigurationDao;
import com.cloud.dc.ClusterVO;
import com.cloud.dc.DataCenterVO;
import com.cloud.dc.DcDetailVO;
import com.cloud.dc.HostPodVO;
import com.cloud.dc.dao.ClusterDao;
import com.cloud.dc.dao.DataCenterDao;
import com.cloud.dc.dao.DcDetailsDao;
import com.cloud.dc.dao.HostPodDao;
import com.cloud.exception.ConnectionException;
import com.cloud.host.Host;
import com.cloud.host.Host.Type;
import com.cloud.host.HostVO;
import com.cloud.host.dao.HostDao;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.storage.Storage;
import com.cloud.utils.component.AdapterBase;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.net.MacAddress;
import com.cloud.utils.net.NetUtils;

/**
 * Creates a host record and supporting records such as pod and ip address
 *
 */
@Component
@Local(value=StartupCommandProcessor.class)
public class CloudZonesStartupProcessor extends AdapterBase implements StartupCommandProcessor {
    private static final Logger s_logger = Logger.getLogger(CloudZonesStartupProcessor.class);
    @Inject ClusterDao _clusterDao = null;
    @Inject ConfigurationDao _configDao = null;
    @Inject DataCenterDao _zoneDao = null;
    @Inject HostDao _hostDao = null;
    @Inject HostPodDao _podDao = null;
    @Inject DcDetailsDao _zoneDetailsDao = null;
    
    @Inject AgentManager _agentManager = null;
    @Inject ConfigurationManager _configurationManager = null;
    
    long _nodeId = -1;
   

    @Override
    public boolean configure(String name, Map<String, Object> params)
            throws ConfigurationException {
        _agentManager.registerForInitialConnects(this, false);
        if (_nodeId == -1) {
            // FIXME: We really should not do this like this. It should be done
            // at config time and is stored as a config variable.
            _nodeId = MacAddress.getMacAddress().toLong();
        }
        return true;
    }

    @Override
    public boolean processInitialConnect(StartupCommand[] cmd)
            throws ConnectionException {
        StartupCommand startup = cmd[0];
        if (startup instanceof StartupRoutingCommand) {
            return processHostStartup((StartupRoutingCommand)startup);
        } else if (startup instanceof StartupStorageCommand ){
            return processStorageStartup((StartupStorageCommand)startup);
        }

        return false;
    }
    
    protected boolean processHostStartup(StartupRoutingCommand startup) throws ConnectionException{
    	/*
        boolean found = false;
        Type type = Host.Type.Routing;
        final Map<String, String> hostDetails = startup.getHostDetails();
        HostVO server = _hostDao.findByGuid(startup.getGuid());
        if (server == null) {
            server = _hostDao.findByGuid(startup.getGuidWithoutResource());
        }
        if (server != null && server.getRemoved() == null) {
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Found the host " + server.getId() + " by guid: "
                        + startup.getGuid());
            }
            found = true;

        } else {
            server = new HostVO(startup.getGuid());
        }
        server.setDetails(hostDetails);

        try {
            updateComputeHost(server, startup, type);
        } catch (AgentAuthnException e) {
            throw new ConnectionException(true, "Failed to authorize host, invalid configuration", e);
        }
        if (!found) {
            server.setHostAllocationState(Host.HostAllocationState.Enabled);
            server = _hostDao.persist(server);
        } else {
            if (!_hostDao.connect(server, _nodeId)) {
                throw new CloudRuntimeException(
                        "Agent cannot connect because the current state is "
                        + server.getStatus().toString());
            }
            s_logger.info("Old " + server.getType().toString()
                    + " host reconnected w/ id =" + server.getId());
        }
        */
        return true;
   
        
    }
    
    protected void updateComputeHost(final HostVO host, final StartupCommand startup,
            final Host.Type type) throws AgentAuthnException {

        String zoneToken = startup.getDataCenter();
        if(zoneToken == null){
        	s_logger.warn("No Zone Token passed in, cannot not find zone for the agent");
        	throw new AgentAuthnException("No Zone Token passed in, cannot not find zone for agent");
        }
        
        DataCenterVO zone = _zoneDao.findByToken(zoneToken);
        if (zone == null) {
        	zone = _zoneDao.findByName(zoneToken);
        	if(zone == null){
	            try {
	                long zoneId = Long.parseLong(zoneToken);
	                zone = _zoneDao.findById(zoneId);
	        		if (zone == null) {
	        			throw new AgentAuthnException("Could not find zone for agent with token " + zoneToken);
	        		}
	            } catch (NumberFormatException nfe) {
	                throw new AgentAuthnException("Could not find zone for agent with token " + zoneToken);
	            }
        	}
        }
    	if(s_logger.isDebugEnabled()){
    		s_logger.debug("Successfully loaded the DataCenter from the zone token passed in ");
    	}
        
        long zoneId = zone.getId();
        DcDetailVO maxHostsInZone = _zoneDetailsDao.findDetail(zoneId, ZoneConfig.MaxHosts.key());
        if(maxHostsInZone != null){
        	long maxHosts = new Long(maxHostsInZone.getValue()).longValue();
        	long currentCountOfHosts = _hostDao.countRoutingHostsByDataCenter(zoneId);
        	if(s_logger.isDebugEnabled()){
        		s_logger.debug("Number of hosts in Zone:"+ currentCountOfHosts + ", max hosts limit: "+ maxHosts);
        	}
        	if(currentCountOfHosts >= maxHosts){
        		throw new AgentAuthnException("Number of running Routing hosts in the Zone:"+ zone.getName() +" is already at the max limit:"+maxHosts+", cannot start one more host");
        	}
        }
        
        HostPodVO pod = null;
        
    	if(startup.getPrivateIpAddress() == null){
       		s_logger.warn("No private IP address passed in for the agent, cannot not find pod for agent");
    		throw new AgentAuthnException("No private IP address passed in for the agent, cannot not find pod for agent");
    	}
    	
    	if(startup.getPrivateNetmask() == null){
       		s_logger.warn("No netmask passed in for the agent, cannot not find pod for agent");
    		throw new AgentAuthnException("No netmask passed in for the agent, cannot not find pod for agent");
    	}
    	        
        if(host.getPodId() != null){
        	if(s_logger.isDebugEnabled()){
        		s_logger.debug("Pod is already created for this agent, looks like agent is reconnecting...");
        	}
        	pod = _podDao.findById(host.getPodId());
        	if(!checkCIDR(type, pod, startup.getPrivateIpAddress(),
					startup.getPrivateNetmask())){
        		pod = null;
            	if(s_logger.isDebugEnabled()){
            		s_logger.debug("Subnet of Pod does not match the subnet of the agent, not using this Pod: "+host.getPodId());
            	}        		
        	}else{
        		updatePodNetmaskIfNeeded(pod, startup.getPrivateNetmask());
        	}
        }
        
        if(pod == null){
	    	if(s_logger.isDebugEnabled()){
	    		s_logger.debug("Trying to detect the Pod to use from the agent's ip address and netmask passed in ");
	    	}
	    	
	        //deduce pod
	    	boolean podFound = false;
	        List<HostPodVO> podsInZone = _podDao.listByDataCenterId(zoneId);
			for (HostPodVO hostPod : podsInZone) {
				if (checkCIDR(type, hostPod, startup.getPrivateIpAddress(),
						startup.getPrivateNetmask())) {
					pod = hostPod;
					
					//found the default POD having the same subnet.
					updatePodNetmaskIfNeeded(pod, startup.getPrivateNetmask());
					podFound = true;
					break;
				}
			}

        
	        if (!podFound) {
	        	if(s_logger.isDebugEnabled()){
	        		s_logger.debug("Creating a new Pod since no default Pod found that matches the agent's ip address and netmask passed in ");
	        	}
	        	
	        	if(startup.getGatewayIpAddress() == null){
	           		s_logger.warn("No Gateway IP address passed in for the agent, cannot create a new pod for the agent");
	        		throw new AgentAuthnException("No Gateway IP address passed in for the agent, cannot create a new pod for the agent");
	        	}
	        	//auto-create a new pod, since pod matching the agent's ip is not found
	        	String podName = "POD-"+ (podsInZone.size()+1);
	        	try{
		        	String gateway = startup.getGatewayIpAddress();
		        	String cidr = NetUtils.getCidrFromGatewayAndNetmask(gateway, startup.getPrivateNetmask());
		            String[] cidrPair = cidr.split("\\/");
		            String cidrAddress = cidrPair[0];
		            long cidrSize = Long.parseLong(cidrPair[1]);
		        	String startIp = NetUtils.getIpRangeStartIpFromCidr(cidrAddress, cidrSize);
		        	String endIp = NetUtils.getIpRangeEndIpFromCidr(cidrAddress, cidrSize);
	        		pod = _configurationManager.createPod(-1, podName, zoneId, gateway, cidr, startIp, endIp, null, true);
	        	}catch (Exception e) {
					// no longer tolerate exception during the cluster creation phase
					throw new CloudRuntimeException("Unable to create new Pod "
							+ podName + " in Zone: "
							+ zoneId, e);
				}
	        	
	        }
        }
        final StartupRoutingCommand scc = (StartupRoutingCommand) startup;

        ClusterVO cluster = null;
        if(host.getClusterId() != null){
        	if(s_logger.isDebugEnabled()){
        		s_logger.debug("Cluster is already created for this agent, looks like agent is reconnecting...");
        	}        	
        	cluster = _clusterDao.findById(host.getClusterId());
        }
        if(cluster == null){
            //auto-create cluster - assume one host per cluster
            String clusterName = "Cluster-" + startup.getPrivateIpAddress();
            ClusterVO existingCluster = _clusterDao.findBy(clusterName, pod.getId());
            if (existingCluster != null) {
                cluster = existingCluster;
            } else {
                if(s_logger.isDebugEnabled()){
                    s_logger.debug("Creating a new Cluster for this agent with name: "+clusterName + " in Pod: " +pod.getId() +", in Zone:"+zoneId);
                }

                cluster = new ClusterVO(zoneId, pod.getId(), clusterName);
                cluster.setHypervisorType(scc.getHypervisorType().toString());
                try {
                    cluster = _clusterDao.persist(cluster);
                } catch (Exception e) {
                    // no longer tolerate exception during the cluster creation phase
                    throw new CloudRuntimeException("Unable to create cluster "
                            + clusterName + " in pod " + pod.getId() + " and data center "
                            + zoneId, e);
                }
            }
        }

    	if(s_logger.isDebugEnabled()){
    		s_logger.debug("Detected Zone: "+zoneId+", Pod: " +pod.getId() +", Cluster:" +cluster.getId());
    	}        
		host.setDataCenterId(zone.getId());
        host.setPodId(pod.getId());
        host.setClusterId(cluster.getId());
        host.setPrivateIpAddress(startup.getPrivateIpAddress());
        host.setPrivateNetmask(startup.getPrivateNetmask());
        host.setPrivateMacAddress(startup.getPrivateMacAddress());
        host.setPublicIpAddress(startup.getPublicIpAddress());
        host.setPublicMacAddress(startup.getPublicMacAddress());
        host.setPublicNetmask(startup.getPublicNetmask());
        host.setStorageIpAddress(startup.getStorageIpAddress());
        host.setStorageMacAddress(startup.getStorageMacAddress());
        host.setStorageNetmask(startup.getStorageNetmask());
        host.setVersion(startup.getVersion());
        host.setName(startup.getName());
        host.setType(type);
        host.setStorageUrl(startup.getIqn());
        host.setLastPinged(System.currentTimeMillis() >> 10);
        host.setCaps(scc.getCapabilities());
        host.setCpus(scc.getCpus());
        host.setTotalMemory(scc.getMemory());
        host.setSpeed(scc.getSpeed());
        HypervisorType hyType = scc.getHypervisorType();
        host.setHypervisorType(hyType);
        host.setHypervisorVersion(scc.getHypervisorVersion());
        
    }
    
	private boolean checkCIDR(Host.Type type, HostPodVO pod,
			String serverPrivateIP, String serverPrivateNetmask) {
		if (serverPrivateIP == null) {
			return true;
		}
		// Get the CIDR address and CIDR size
		String cidrAddress = pod.getCidrAddress();
		long cidrSize = pod.getCidrSize();

		// If the server's private IP address is not in the same subnet as the
		// pod's CIDR, return false
		String cidrSubnet = NetUtils.getCidrSubNet(cidrAddress, cidrSize);
		String serverSubnet = NetUtils.getSubNet(serverPrivateIP,
				serverPrivateNetmask);
		if (!cidrSubnet.equals(serverSubnet)) {
			return false;
		}
		return true;
	}
	
	private void updatePodNetmaskIfNeeded(HostPodVO pod, String agentNetmask){
		// If the server's private netmask is less inclusive than the pod's CIDR
		// netmask, update cidrSize of the default POD 
		//(reason: we are maintaining pods only for internal accounting.)
		long cidrSize = pod.getCidrSize();
		String cidrNetmask = NetUtils
				.getCidrSubNet("255.255.255.255", cidrSize);
		long cidrNetmaskNumeric = NetUtils.ip2Long(cidrNetmask);
		long serverNetmaskNumeric = NetUtils.ip2Long(agentNetmask);//
		if (serverNetmaskNumeric > cidrNetmaskNumeric) {
			//update pod's cidrsize
			int newCidrSize = new Long(NetUtils.getCidrSize(agentNetmask)).intValue();
			pod.setCidrSize(newCidrSize);
			_podDao.update(pod.getId(), pod);
		}		
	}
	
	
	protected boolean processStorageStartup(StartupStorageCommand startup) throws ConnectionException{
		/*
	    if (startup.getResourceType() != Storage.StorageResourceType.LOCAL_SECONDARY_STORAGE) {
            return false;
        }
	    boolean found = false;
        Type type = Host.Type.LocalSecondaryStorage;
        final Map<String, String> hostDetails = startup.getHostDetails();
        HostVO server = _hostDao.findByGuid(startup.getGuid());
        if (server == null) {
            server = _hostDao.findByGuid(startup.getGuidWithoutResource());
        }
        if (server != null && server.getRemoved() == null) {
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Found the host " + server.getId() + " by guid: "
                        + startup.getGuid());
            }
            found = true;

        } else {
            server = new HostVO(startup.getGuid());
        }
        server.setDetails(hostDetails);

        try {
            updateSecondaryHost(server, startup, type);
        } catch (AgentAuthnException e) {
            throw new ConnectionException(true, "Failed to authorize host, invalid configuration", e);
        }
        if (!found) {
            server.setHostAllocationState(Host.HostAllocationState.Enabled);
            server = _hostDao.persist(server);
        } else {
            if (!_hostDao.connect(server, _nodeId)) {
                throw new CloudRuntimeException(
                        "Agent cannot connect because the current state is "
                        + server.getStatus().toString());
            }
            s_logger.info("Old " + server.getType().toString()
                    + " host reconnected w/ id =" + server.getId());
        }
        */
        return true;
   
        
    }
	protected void updateSecondaryHost(final HostVO host, final StartupStorageCommand startup,
            final Host.Type type) throws AgentAuthnException {
	  
        String zoneToken = startup.getDataCenter();
        if(zoneToken == null){
            s_logger.warn("No Zone Token passed in, cannot not find zone for the agent");
            throw new AgentAuthnException("No Zone Token passed in, cannot not find zone for agent");
        }
        
        DataCenterVO zone = _zoneDao.findByToken(zoneToken);
        if (zone == null) {
            zone = _zoneDao.findByName(zoneToken);
            if(zone == null){
                try {
                    long zoneId = Long.parseLong(zoneToken);
                    zone = _zoneDao.findById(zoneId);
                    if (zone == null) {
                        throw new AgentAuthnException("Could not find zone for agent with token " + zoneToken);
                    }
                } catch (NumberFormatException nfe) {
                    throw new AgentAuthnException("Could not find zone for agent with token " + zoneToken);
                }
            }
        }
        if(s_logger.isDebugEnabled()){
            s_logger.debug("Successfully loaded the DataCenter from the zone token passed in ");
        }
        
        HostPodVO pod = findPod(startup, zone.getId(), Host.Type.Routing); //yes, routing
        Long podId = null;
        if (pod != null) {
            s_logger.debug("Found pod " + pod.getName() + " for the secondary storage host " + startup.getName());
            podId = pod.getId();
        }
        host.setDataCenterId(zone.getId());
        host.setPodId(podId);
        host.setClusterId(null);
        host.setPrivateIpAddress(startup.getPrivateIpAddress());
        host.setPrivateNetmask(startup.getPrivateNetmask());
        host.setPrivateMacAddress(startup.getPrivateMacAddress());
        host.setPublicIpAddress(startup.getPublicIpAddress());
        host.setPublicMacAddress(startup.getPublicMacAddress());
        host.setPublicNetmask(startup.getPublicNetmask());
        host.setStorageIpAddress(startup.getStorageIpAddress());
        host.setStorageMacAddress(startup.getStorageMacAddress());
        host.setStorageNetmask(startup.getStorageNetmask());
        host.setVersion(startup.getVersion());
        host.setName(startup.getName());
        host.setType(type);
        host.setStorageUrl(startup.getIqn());
        host.setLastPinged(System.currentTimeMillis() >> 10);
        host.setCaps(null);
        host.setCpus(null);
        host.setTotalMemory(0);
        host.setSpeed(null);
        host.setParent(startup.getParent());
        host.setTotalSize(startup.getTotalSize());
        host.setHypervisorType(HypervisorType.None);
        if (startup.getNfsShare() != null) {
            host.setStorageUrl(startup.getNfsShare());
        }

    }
	
	private HostPodVO findPod(StartupCommand startup, long zoneId, Host.Type type) {
	    HostPodVO pod = null;
	    List<HostPodVO> podsInZone = _podDao.listByDataCenterId(zoneId);
        for (HostPodVO hostPod : podsInZone) {
            if (checkCIDR(type, hostPod, startup.getPrivateIpAddress(),
                    startup.getPrivateNetmask())) {
                pod = hostPod;
                
                //found the default POD having the same subnet.
                updatePodNetmaskIfNeeded(pod, startup.getPrivateNetmask());
                
                break;
            }
        }
        return pod;

	}

}
