// Copyright 2012 Citrix Systems, Inc. Licensed under the
// Apache License, Version 2.0 (the "License"); you may not use this
// file except in compliance with the License.  Citrix Systems, Inc.
// reserves all rights not expressly granted by 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.
// 
// Automatically generated by addcopyright.py at 04/03/2012
package com.cloud.deploy;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.ejb.Local;

import org.apache.log4j.Logger;

import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.utils.Pair;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachineProfile;

@Local(value=DeploymentPlanner.class)
public class UserConcentratedPodPlanner extends FirstFitPlanner implements DeploymentPlanner {

    private static final Logger s_logger = Logger.getLogger(UserConcentratedPodPlanner.class);
    
    /**
     * This method should reorder the given list of Cluster Ids by applying any necessary heuristic 
     * for this planner
     * For UserConcentratedPodPlanner we need to order the clusters in a zone across pods, by considering those pods first which have more number of VMs for this account
     * This reordering is not done incase the clusters within single pod are passed when the allocation is applied at pod-level.
     * @return List<Long> ordered list of Cluster Ids
     */
    @Override
    protected List<Long> reorderClusters(long id, boolean isZone, Pair<List<Long>, Map<Long, Double>> clusterCapacityInfo, VirtualMachineProfile<? extends VirtualMachine> vmProfile, DeploymentPlan plan){
        List<Long> clusterIdsByCapacity = clusterCapacityInfo.first();
        if(vmProfile.getOwner() == null || !isZone){
            return clusterIdsByCapacity;
        }
        return applyUserConcentrationPodHeuristicToClusters(id, clusterIdsByCapacity, vmProfile.getOwner().getAccountId());
    }
    
    private List<Long> applyUserConcentrationPodHeuristicToClusters(long zoneId, List<Long> prioritizedClusterIds, long accountId){
        //user has VMs in certain pods. - prioritize those pods first
        //UserConcentratedPod strategy
        List<Long> clusterList = new ArrayList<Long>();
        List<Long> podIds = listPodsByUserConcentration(zoneId, accountId);
        if(!podIds.isEmpty()){
            clusterList = reorderClustersByPods(prioritizedClusterIds, podIds);
        }else{
            clusterList = prioritizedClusterIds;
        }
        return clusterList;
    }    
    
    private List<Long> reorderClustersByPods(List<Long> clusterIds, List<Long> podIds) {

        if (s_logger.isDebugEnabled()) {
            s_logger.debug("Reordering cluster list as per pods ordered by user concentration");
        }

        Map<Long, List<Long>> podClusterMap = _clusterDao.getPodClusterIdMap(clusterIds);

        if (s_logger.isTraceEnabled()) {
            s_logger.trace("Pod To cluster Map is: "+podClusterMap );
        }

        List<Long> reorderedClusters = new ArrayList<Long>();
        for (Long pod : podIds){
            if(podClusterMap.containsKey(pod)){
                List<Long> clustersOfThisPod = podClusterMap.get(pod);
                if(clustersOfThisPod != null){
                    for(Long clusterId : clusterIds){
                        if(clustersOfThisPod.contains(clusterId)){
                            reorderedClusters.add(clusterId);
                        }
                    }
                    clusterIds.removeAll(clustersOfThisPod);
                }
            }
        }
        reorderedClusters.addAll(clusterIds);

        if (s_logger.isTraceEnabled()) {
            s_logger.trace("Reordered cluster list: " + reorderedClusters);
        }
        return reorderedClusters;
    }

    protected List<Long> listPodsByUserConcentration(long zoneId, long accountId){

        if (s_logger.isDebugEnabled()) {
            s_logger.debug("Applying UserConcentratedPod heuristic for account: "+ accountId);
        }

        List<Long> prioritizedPods = _vmDao.listPodIdsHavingVmsforAccount(zoneId, accountId);

        if (s_logger.isTraceEnabled()) {
            s_logger.trace("List of pods to be considered, after applying UserConcentratedPod heuristic: "+ prioritizedPods);
        }

        return prioritizedPods;
    }
    
    /**
     * This method should reorder the given list of Pod Ids by applying any necessary heuristic 
     * for this planner
     * For UserConcentratedPodPlanner we need to order the pods by considering those pods first which have more number of VMs for this account 
     * @return List<Long> ordered list of Pod Ids
     */
    @Override
    protected List<Long> reorderPods(Pair<List<Long>, Map<Long, Double>> podCapacityInfo, VirtualMachineProfile<? extends VirtualMachine> vmProfile, DeploymentPlan plan){
        List<Long> podIdsByCapacity = podCapacityInfo.first();
        if(vmProfile.getOwner() == null){
            return podIdsByCapacity;
        }
        long accountId = vmProfile.getOwner().getAccountId(); 

        //user has VMs in certain pods. - prioritize those pods first
        //UserConcentratedPod strategy
        List<Long> podIds = listPodsByUserConcentration(plan.getDataCenterId(), accountId);
        if(!podIds.isEmpty()){
            //remove pods that dont have capacity for this vm
            podIds.retainAll(podIdsByCapacity);
            podIdsByCapacity.removeAll(podIds);
            podIds.addAll(podIdsByCapacity);
            return podIds;
        }else{
            return podIdsByCapacity;
        }
        
    }

    @Override
    public boolean canHandle(VirtualMachineProfile<? extends VirtualMachine> vm, DeploymentPlan plan, ExcludeList avoid) {
        if(vm.getHypervisorType() != HypervisorType.BareMetal){
            //check the allocation strategy
            if (_allocationAlgorithm != null && (_allocationAlgorithm.equals(AllocationAlgorithm.userconcentratedpod_random.toString()) || _allocationAlgorithm.equals(AllocationAlgorithm.userconcentratedpod_firstfit.toString()))){
                return true;
            }
        }
        return false;
    }

}
