// 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.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.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.component.Inject;
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");
        }
    }
}


