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

import java.net.InetAddress;
import java.net.URI;
import java.net.UnknownHostException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

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

import org.apache.log4j.Logger;

import com.cloud.agent.api.Command;
import com.cloud.agent.api.StartupVMMAgentCommand;
import com.cloud.agent.transport.Request;
import com.cloud.alert.AlertManager;
import com.cloud.dc.ClusterDetailsDao;
import com.cloud.dc.ClusterVO;
import com.cloud.dc.dao.ClusterDao;
import com.cloud.exception.DiscoveryException;
import com.cloud.host.Host;
import com.cloud.host.HostVO;
import com.cloud.host.dao.HostDao;
import com.cloud.hypervisor.Hypervisor;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.hypervisor.hyperv.resource.HypervDummyResourceBase;
import com.cloud.resource.Discoverer;
import com.cloud.resource.DiscovererBase;
import com.cloud.resource.ResourceManager;
import com.cloud.resource.ServerResource;
import com.cloud.utils.nio.HandlerFactory;
import com.cloud.utils.nio.Link;
import com.cloud.utils.nio.NioClient;
import com.cloud.utils.nio.Task;
import com.cloud.utils.nio.Task.Type;

@Local(value=Discoverer.class)
public class HypervServerDiscoverer extends DiscovererBase implements Discoverer, HandlerFactory{
    private static final Logger s_logger = Logger.getLogger(HypervServerDiscoverer.class);
    private int _waitTime = 1;

    @Inject ClusterDao _clusterDao;
    @Inject AlertManager _alertMgr;
    @Inject ClusterDetailsDao _clusterDetailsDao;
    @Inject HostDao _hostDao = null;
    @Inject ResourceManager _resourceMgr;
    Link _link;

    @SuppressWarnings("static-access")
    @Override
    public Map<? extends ServerResource, Map<String, String>> find(long dcId, Long podId, Long clusterId, URI url,
            String username, String password, List<String> hostTags) throws DiscoveryException {

        if(s_logger.isInfoEnabled()) {
            s_logger.info("Discover host. dc: " + dcId + ", pod: " + podId + ", cluster: " + clusterId + ", uri host: " + url.getHost());
        }

        if(podId == null) {
            if(s_logger.isInfoEnabled()) {
                s_logger.info("No pod is assigned, skipping the discovery in Hyperv discoverer");
            }
            return null;
        }

        if (!url.getScheme().equals("http")) {
            String msg = "urlString is not http so HypervServerDiscoverer taking care of the discovery for this: " + url;
            s_logger.debug(msg);
            return null;
        }

        ClusterVO cluster = _clusterDao.findById(clusterId);
        if(cluster == null || cluster.getHypervisorType() != HypervisorType.Hyperv) {
            if(s_logger.isInfoEnabled()) {
                s_logger.info("invalid cluster id or cluster is not for Hyperv hypervisors");
            }
            return null;
        }
        String clusterName = cluster.getName();

        try {
        	
    		String hostname = url.getHost();
    		InetAddress ia = InetAddress.getByName(hostname);
    		String agentIp = ia.getHostAddress();
    		String guid = UUID.nameUUIDFromBytes(agentIp.getBytes()).toString();
    		String guidWithTail = guid + "-HypervResource";/*tail added by agent.java*/
    		if (_resourceMgr.findHostByGuid(guidWithTail) != null) {
    			s_logger.debug("Skipping " + agentIp + " because " + guidWithTail + " is already in the database.");
    			return null;
    		}
        	
	        // bootstrap SCVMM agent to connect back to management server
	        NioClient _connection = new NioClient("HypervAgentClient", url.getHost(), 9000, 1, this);  
	        _connection.start();

	        StartupVMMAgentCommand cmd = new StartupVMMAgentCommand(
	        		dcId,
	        		podId,
	        		clusterName,
	        		guid,
	        		InetAddress.getLocalHost().getHostAddress(),
	        		"8250",
	        		HypervServerDiscoverer.class.getPackage().getImplementationVersion());
	        
	        // send bootstrap command to agent running on SCVMM host	
        	s_logger.info("sending bootstrap request to SCVMM agent on host "+ url.getHost());
	        Request request = new Request(0, 0, cmd, false);

	        // :FIXME without sleep link.send failing why??????
	        Thread.currentThread().sleep(5000);
        	_link.send(request.toBytes());

	        //wait for SCVMM agent to connect back
			HostVO connectedHost = waitForHostConnect(dcId, podId, clusterId, guidWithTail);
			if (connectedHost == null)
			{
				s_logger.info("SCVMM agent did not connect back after sending bootstrap request"); 
				return null;
			}

	        //disconnect
			s_logger.info("SCVMM agent connected back after sending bootstrap request"); 
	        _connection.stop();        
	
	        Map<HypervDummyResourceBase, Map<String, String>> resources = new HashMap<HypervDummyResourceBase, Map<String, String>>();
	        Map<String, String> details = new HashMap<String, String>();
	        Map<String, Object> params = new HashMap<String, Object>();
	        HypervDummyResourceBase resource = new HypervDummyResourceBase(); 
	
	        details.put("url", url.getHost());
	        details.put("username", username);
	        details.put("password", password);
			resources.put(resource, details);
	
	        params.put("zone", Long.toString(dcId));
	        params.put("pod", Long.toString(podId));
	        params.put("cluster", Long.toString(clusterId));

            resource.configure("Hyperv", params);
            return resources;
        } catch (ConfigurationException e) {
            _alertMgr.sendAlert(AlertManager.ALERT_TYPE_HOST, dcId, podId, "Unable to add " + url.getHost(), "Error is " + e.getMessage());
            s_logger.warn("Unable to instantiate " + url.getHost(), e);
        } catch (UnknownHostException e) {
            _alertMgr.sendAlert(AlertManager.ALERT_TYPE_HOST, dcId, podId, "Unable to add " + url.getHost(), "Error is " + e.getMessage());
            s_logger.warn("Unable to instantiate " + url.getHost(), e);
        } catch (Exception e) {
            s_logger.info("exception " + e.toString());
        }
        return null;
    }

    @Override
    public void postDiscovery(List<HostVO> hosts, long msId) {
        // do nothing
    }

    @Override
    public boolean matchHypervisor(String hypervisor) {
        if(hypervisor == null) {
            return true;
        }

        return Hypervisor.HypervisorType.VMware.toString().equalsIgnoreCase(hypervisor);
    }

    @Override
    public Hypervisor.HypervisorType getHypervisorType() {
        return Hypervisor.HypervisorType.Hyperv;
    }

    @Override
    public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
        super.configure(name, params);
        return true;
    }

    @Override
    public Task create(Type type, Link link, byte[] data) {
        _link = link;
        return new BootStrapTakHandler(type, link, data);
    }

    private HostVO waitForHostConnect(long dcId, long podId, long clusterId, String guid) {
        for (int i = 0; i < _waitTime *2; i++) {
            List<HostVO> hosts = _resourceMgr.listAllUpAndEnabledHosts(Host.Type.Routing, clusterId, podId, dcId);
            for (HostVO host : hosts) {
                if (host.getGuid().equalsIgnoreCase(guid)) {
                    return host;
                }
            }
            try {
                Thread.sleep(30000);
            } catch (InterruptedException e) {
                s_logger.debug("Failed to sleep: " + e.toString());
            }
        }
        s_logger.debug("Timeout, to wait for the host connecting to mgt svr, assuming it is failed");
        return null;
    }

    // class to handle the bootstrap command from the management server
    public class BootStrapTakHandler extends Task {

        public BootStrapTakHandler(Task.Type type, Link link, byte[] data) {
            super(type, link, data);
            s_logger.info("created new BootStrapTakHandler");
        }

        protected void processRequest(final Link link, final Request request) {
            final Command[] cmds = request.getCommands();
            Command cmd = cmds[0];
        }

        @Override
        protected void doTask(Task task) throws Exception {
            final Type type = task.getType();
            s_logger.info("recieved task of type "+type.toString() +" in BootStrapTakHandler");
        }
    }
}


