// 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.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

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

import com.cloud.utils.Pair;

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

import com.cloud.agent.api.Command;
import com.cloud.host.Host;
import com.cloud.host.HostVO;
import com.cloud.host.dao.HostDao;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.utils.component.ManagerBase;

@Component
@Local(value = { HypervisorGuruManager.class } )
public class HypervisorGuruManagerImpl extends ManagerBase implements HypervisorGuruManager {
    public static final Logger s_logger = Logger.getLogger(HypervisorGuruManagerImpl.class.getName());

    @Inject HostDao _hostDao;

    List<HypervisorGuru> _hvGuruList;
    Map<HypervisorType, HypervisorGuru> _hvGurus = new ConcurrentHashMap<HypervisorType, HypervisorGuru>();

    @PostConstruct
    public void init() {
        for(HypervisorGuru guru : _hvGuruList) {
            _hvGurus.put(guru.getHypervisorType(), guru);
        }
    }

    @Override
    public HypervisorGuru getGuru(HypervisorType hypervisorType) {
        if (hypervisorType == null) {
            return null;
        }

        HypervisorGuru result = _hvGurus.get(hypervisorType);

        if ( result == null ) {
            for ( HypervisorGuru guru : _hvGuruList ) {
                if ( guru.getHypervisorType() == hypervisorType ) {
                    _hvGurus.put(hypervisorType, guru);
                    result = guru;
                    break;
                }
            }
        }

        return result;
    }

    @Override
    public long getGuruProcessedCommandTargetHost(long hostId, Command cmd) {
        for(HypervisorGuru guru : _hvGuruList) {
            Pair<Boolean, Long> result = guru.getCommandHostDelegation(hostId, cmd);
            if (result.first()) {
                return result.second();
            }
        }
        return hostId;
    }

    public List<HypervisorGuru> getHvGuruList() {
        return _hvGuruList;
    }

    @Inject
    public void setHvGuruList(List<HypervisorGuru> hvGuruList) {
        this._hvGuruList = hvGuruList;
    }

}
