// 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.agent.manager;

import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.regex.PatternSyntaxException;

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

import org.apache.log4j.Logger;

import com.cloud.agent.AgentManager;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.CheckHealthCommand;
import com.cloud.agent.api.CheckNetworkAnswer;
import com.cloud.agent.api.CheckNetworkCommand;
import com.cloud.agent.api.GetHostStatsAnswer;
import com.cloud.agent.api.GetHostStatsCommand;
import com.cloud.agent.api.HostStatsEntry;
import com.cloud.agent.api.MaintainAnswer;
import com.cloud.agent.api.PingTestCommand;
import com.cloud.agent.api.PrepareForMigrationAnswer;
import com.cloud.agent.api.PrepareForMigrationCommand;
import com.cloud.agent.api.to.VirtualMachineTO;
import com.cloud.dc.dao.HostPodDao;
import com.cloud.host.Host;
import com.cloud.resource.AgentResourceBase;
import com.cloud.resource.AgentRoutingResource;
import com.cloud.resource.AgentStorageResource;
import com.cloud.resource.ResourceManager;
import com.cloud.simulator.MockHost;
import com.cloud.simulator.MockHostVO;
import com.cloud.simulator.MockVMVO;
import com.cloud.simulator.dao.MockHostDao;
import com.cloud.simulator.dao.MockVMDao;
import com.cloud.utils.Pair;
import com.cloud.utils.component.Inject;
import com.cloud.utils.concurrency.NamedThreadFactory;
import com.cloud.utils.db.DB;
import com.cloud.utils.net.NetUtils;

@Local(value = { MockAgentManager.class })
public class MockAgentManagerImpl implements MockAgentManager {
    private static final Logger s_logger = Logger.getLogger(MockAgentManagerImpl.class);
    @Inject HostPodDao _podDao = null;   
    @Inject MockHostDao _mockHostDao = null;
    @Inject MockVMDao _mockVmDao = null;
    @Inject SimulatorManager _simulatorMgr = null;
    @Inject AgentManager _agentMgr = null;
    @Inject MockStorageManager _storageMgr = null;
	@Inject ResourceManager _resourceMgr;
    private SecureRandom random;
    private Map<String, AgentResourceBase> _resources = new ConcurrentHashMap<String, AgentResourceBase>();
    private ThreadPoolExecutor _executor;

    private Pair<String, Long> getPodCidr(long podId, long dcId) {
        try {
     
            HashMap<Long, List<Object>> podMap = _podDao
                    .getCurrentPodCidrSubnets(dcId, 0);
            List<Object> cidrPair = podMap.get(podId);
            String cidrAddress = (String) cidrPair.get(0);
            Long cidrSize = (Long)cidrPair.get(1);
            return new Pair<String, Long>(cidrAddress, cidrSize);
        } catch (PatternSyntaxException e) {
            s_logger.error("Exception while splitting pod cidr");
            return null;
        } catch(IndexOutOfBoundsException e) {
            s_logger.error("Invalid pod cidr. Please check");
            return null;
        }
    }
    

    private String getIpAddress(long instanceId, long dcId, long podId) {
        Pair<String, Long> cidr = this.getPodCidr(podId, dcId);
        return NetUtils.long2Ip(NetUtils.ip2Long(cidr.first()) + instanceId);
    }
    
    private String getMacAddress(long dcId, long podId, long clusterId, int instanceId) {
        return NetUtils.long2Mac((dcId << 40 + podId << 32 + clusterId << 24 + instanceId));
    }
    public synchronized int getNextAgentId(long cidrSize) {
        return random.nextInt((int)cidrSize);
    }
    
    @Override
    @DB
    public Map<AgentResourceBase, Map<String, String>> createServerResources(
            Map<String, Object> params) {
      
        Map<String, String> args = new HashMap<String, String>();
        Map<AgentResourceBase, Map<String,String>> newResources = new HashMap<AgentResourceBase, Map<String,String>>();
        AgentResourceBase agentResource;
        long cpuCore = Long.parseLong((String)params.get("cpucore"));
        long cpuSpeed = Long.parseLong((String)params.get("cpuspeed"));
        long memory = Long.parseLong((String)params.get("memory"));
        long localStorageSize = Long.parseLong((String)params.get("localstorage"));
        synchronized (this) {
            long dataCenterId = Long.parseLong((String)params.get("zone"));
            long podId = Long.parseLong((String)params.get("pod"));
            long clusterId = Long.parseLong((String)params.get("cluster"));
            long cidrSize = getPodCidr(podId, dataCenterId).second();

            int agentId = getNextAgentId(cidrSize);
            String ipAddress = getIpAddress(agentId, dataCenterId, podId);
            String macAddress = getMacAddress(dataCenterId, podId, clusterId, agentId);
            MockHostVO mockHost = new MockHostVO();
            mockHost.setDataCenterId(dataCenterId);
            mockHost.setPodId(podId);
            mockHost.setClusterId(clusterId);
            mockHost.setCapabilities("hvm");
            mockHost.setCpuCount(cpuCore);
            mockHost.setCpuSpeed(cpuSpeed);
            mockHost.setMemorySize(memory);
            String guid = UUID.randomUUID().toString();
            mockHost.setGuid(guid);
            mockHost.setName("SimulatedAgent." + guid);
            mockHost.setPrivateIpAddress(ipAddress);
            mockHost.setPublicIpAddress(ipAddress);
            mockHost.setStorageIpAddress(ipAddress);
            mockHost.setPrivateMacAddress(macAddress);
            mockHost.setPublicMacAddress(macAddress);
            mockHost.setStorageMacAddress(macAddress);
            mockHost.setVersion(this.getClass().getPackage().getImplementationVersion());
            mockHost.setResource("com.cloud.agent.AgentRoutingResource");
            mockHost = _mockHostDao.persist(mockHost);
            
            _storageMgr.getLocalStorage(guid, localStorageSize);

            agentResource = new AgentRoutingResource();
            if (agentResource != null) {
                try {
                    params.put("guid", mockHost.getGuid());
                    agentResource.start();
                    agentResource.configure(mockHost.getName(),
                            params);

                    newResources.put(agentResource, args);
                } catch (ConfigurationException e) {
                    s_logger
                    .error("error while configuring server resource"
                            + e.getMessage());
                }
            }
        }
        return newResources;
    }
    
    
    @Override
    public boolean configure(String name, Map<String, Object> params)
            throws ConfigurationException {
        try {
            random = SecureRandom.getInstance("SHA1PRNG");
            _executor = new ThreadPoolExecutor(1, 5, 1, TimeUnit.DAYS, new LinkedBlockingQueue<Runnable>(), new NamedThreadFactory("Simulator-Agent-Mgr"));
            //ComponentLocator locator = ComponentLocator.getCurrentLocator();
            //_simulatorMgr = (SimulatorManager) locator.getComponent(SimulatorManager.Name);
        } catch (NoSuchAlgorithmException e) {
            s_logger.debug("Failed to initialize random:" + e.toString());
            return false;
        }
        return true;
    }
    
    @Override
    public boolean handleSystemVMStart(long vmId, String privateIpAddress, String privateMacAddress, String privateNetMask, long dcId, long podId, String name, String vmType, String url) {
        _executor.execute(new SystemVMHandler(vmId, privateIpAddress, privateMacAddress, privateNetMask, dcId, podId, name, vmType, _simulatorMgr, url));
        return true;
    }
    
    @Override
    public boolean handleSystemVMStop(long vmId) {
        _executor.execute(new SystemVMHandler(vmId));
        return true;
    }
    
    private class SystemVMHandler implements Runnable {
        private long vmId;
        private String privateIpAddress;
        private String privateMacAddress;
        private String privateNetMask;
        private long dcId;
        private long podId;
        private String guid;
        private String name;
        private String vmType;
        private SimulatorManager mgr;
        private String mode;
        private String url;
        public SystemVMHandler(long vmId, String privateIpAddress, String privateMacAddress, String privateNetMask, long dcId, long podId, String name, String vmType, 
                SimulatorManager mgr, String url) {
            this.vmId = vmId;
            this.privateIpAddress = privateIpAddress;
            this.privateMacAddress = privateMacAddress;
            this.privateNetMask = privateNetMask;
            this.dcId = dcId;
            this.guid = "SystemVM-" + UUID.randomUUID().toString();
            this.name = name;
            this.vmType = vmType;
            this.mgr = mgr;
            this.mode = "Start";
            this.url = url;
            this.podId = podId;
        }
        
        public SystemVMHandler(long vmId) {
            this.vmId = vmId;
            this.mode = "Stop";
        }
        
        @Override
        @DB
        public void run() {
            if (this.mode.equalsIgnoreCase("Stop")) {
                MockHost host = _mockHostDao.findByVmId(this.vmId);
                if (host != null) {
                    String guid = host.getGuid();
                    if (guid != null) {
                        AgentResourceBase res = _resources.get(guid);
                        if (res != null) {
                            res.stop();
                            _resources.remove(guid);
                        }
                    }
                }
                return;
            }
            
            String resource = null;
            if (vmType.equalsIgnoreCase("secstorage")) {
                resource = "com.cloud.agent.AgentStorageResource";
            }
            MockHostVO mockHost = new MockHostVO();
            mockHost.setDataCenterId(this.dcId);
            mockHost.setPodId(this.podId);
            mockHost.setCpuCount(DEFAULT_HOST_CPU_CORES);
            mockHost.setCpuSpeed(DEFAULT_HOST_SPEED_MHZ);
            mockHost.setMemorySize(DEFAULT_HOST_MEM_SIZE);
            mockHost.setGuid(this.guid);
            mockHost.setName(name);
            mockHost.setPrivateIpAddress(this.privateIpAddress);
            mockHost.setPublicIpAddress(this.privateIpAddress);
            mockHost.setStorageIpAddress(this.privateIpAddress);
            mockHost.setPrivateMacAddress(this.privateMacAddress);
            mockHost.setPublicMacAddress(this.privateMacAddress);
            mockHost.setStorageMacAddress(this.privateMacAddress);
            mockHost.setVersion(this.getClass().getPackage().getImplementationVersion());
            mockHost.setResource(resource);
            mockHost.setVmId(vmId);
            mockHost = _mockHostDao.persist(mockHost);
           
            if (vmType.equalsIgnoreCase("secstorage")) {
                AgentStorageResource storageResource = new AgentStorageResource();
                try {
                    Map<String, Object> params =  new HashMap<String, Object>();
                    Map<String, String> details = new HashMap<String, String>();
                    params.put("guid", this.guid);
                    details.put("guid", this.guid);
                    storageResource.configure("secondaryStorage", params);
                    storageResource.start();
                    //on the simulator the ssvm is as good as a direct agent
                    _resourceMgr.addHost(mockHost.getDataCenterId(), storageResource, Host.Type.SecondaryStorageVM, details);
                    _resources.put(this.guid, storageResource);
                } catch (ConfigurationException e) {
                    s_logger.debug("Failed to load secondary storage resource: " + e.toString());
                    return;
                }
            }            
        }
    }

    @Override
    public MockHost getHost(String guid) {
        return _mockHostDao.findByGuid(guid);
    }

    @Override
    public GetHostStatsAnswer getHostStatistic(GetHostStatsCommand cmd) {
        String hostGuid = cmd.getHostGuid();
        MockHost host = _mockHostDao.findByGuid(hostGuid);
        if (host == null) {
            return null;
        }
        List<MockVMVO> vms = _mockVmDao.findByHostId(host.getId());
        double usedMem = 0.0;
        double usedCpu = 0.0;
        for (MockVMVO vm : vms) {
            usedMem += vm.getMemory();
            usedCpu += vm.getCpu();
        }
        
        HostStatsEntry hostStats = new HostStatsEntry();
        hostStats.setTotalMemoryKBs(host.getMemorySize());
        hostStats.setFreeMemoryKBs(host.getMemorySize() - usedMem);
        hostStats.setNetworkReadKBs(32768);
        hostStats.setNetworkWriteKBs(16384);
        hostStats.setCpuUtilization(usedCpu/(host.getCpuCount() * host.getCpuSpeed()));
        hostStats.setEntityType("simulator-host");
        hostStats.setHostId(cmd.getHostId());
        return new GetHostStatsAnswer(cmd, hostStats);
    }


    @Override
    public Answer checkHealth(CheckHealthCommand cmd) {
        return new Answer(cmd);
    }


    @Override
    public Answer pingTest(PingTestCommand cmd) {
        return new Answer(cmd);
    }


    @Override
    public PrepareForMigrationAnswer prepareForMigrate(PrepareForMigrationCommand cmd) {
    	VirtualMachineTO vm = cmd.getVirtualMachine();
        if (s_logger.isDebugEnabled()) {
            s_logger.debug("Preparing host for migrating " + vm);
        }
        return new PrepareForMigrationAnswer(cmd);
    }


    @Override
    public boolean start() {
        return true;
    }


    @Override
    public boolean stop() {
        return true;
    }


    @Override
    public String getName() {
        return this.getClass().getSimpleName();
    }


    @Override
    public MaintainAnswer maintain(com.cloud.agent.api.MaintainCommand cmd) {
        return new MaintainAnswer(cmd);
    }

	@Override
	public Answer checkNetworkCommand(CheckNetworkCommand cmd) {
		if (s_logger.isDebugEnabled()) {
            s_logger.debug("Checking if network name setup is done on the resource");
        }
		return new CheckNetworkAnswer(cmd, true , "Network Setup check by names is done");
	}
}
