package net.onrc.onos.ofcontroller.floodlightlistener;

import java.net.InetAddress;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import net.floodlightcontroller.core.IFloodlightProviderService;
import net.floodlightcontroller.core.IOFSwitch;
import net.floodlightcontroller.core.module.FloodlightModuleContext;
import net.floodlightcontroller.core.module.FloodlightModuleException;
import net.floodlightcontroller.core.module.IFloodlightModule;
import net.floodlightcontroller.core.module.IFloodlightService;
import net.floodlightcontroller.core.util.SingletonTask;
import net.floodlightcontroller.threadpool.IThreadPoolService;
import net.onrc.onos.datagrid.IDatagridService;
import net.onrc.onos.ofcontroller.core.IOFSwitchPortListener;
import net.onrc.onos.ofcontroller.devicemanager.IOnosDeviceListener;
import net.onrc.onos.ofcontroller.devicemanager.IOnosDeviceService;
import net.onrc.onos.ofcontroller.devicemanager.OnosDevice;
import net.onrc.onos.ofcontroller.linkdiscovery.ILinkDiscoveryListener;
import net.onrc.onos.ofcontroller.linkdiscovery.ILinkDiscoveryService;
import net.onrc.onos.ofcontroller.networkgraph.DeviceEvent;
import net.onrc.onos.ofcontroller.networkgraph.INetworkGraphService;
import net.onrc.onos.ofcontroller.networkgraph.LinkEvent;
import net.onrc.onos.ofcontroller.networkgraph.NetworkGraph;
import net.onrc.onos.ofcontroller.networkgraph.NetworkGraphDiscoveryInterface;
import net.onrc.onos.ofcontroller.networkgraph.PortEvent;
import net.onrc.onos.ofcontroller.networkgraph.Switch;
import net.onrc.onos.ofcontroller.networkgraph.SwitchEvent;
import net.onrc.onos.ofcontroller.networkgraph.PortEvent.SwitchPort;
import net.onrc.onos.registry.controller.IControllerRegistryService;
import net.onrc.onos.registry.controller.IControllerRegistryService.ControlChangeCallback;
import net.onrc.onos.registry.controller.RegistryException;

import org.openflow.protocol.OFPhysicalPort;
import org.openflow.util.HexString;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.net.InetAddresses;

/*
 * I've created a copy of the old NetworkGraphPublisher so I can integrate
 * the new API with ONOS while still having the old NetworkGraphPublisher
 * to reference.
 * TODO Remove old NetworkGraphPublisher once the integration of the new
 * API is complete.
 * For now, we just write to the database and don't worry about sending
 * notifications.
 * TODO Send notification after each database write
 */
public class NetworkGraphPublisher implements /*IOFSwitchListener,*/
												IOFSwitchPortListener,
												ILinkDiscoveryListener,
												IFloodlightModule,
												IOnosDeviceListener {
	private static final Logger log = LoggerFactory.getLogger(NetworkGraphPublisher.class);

	private IFloodlightProviderService floodlightProvider;
	private ILinkDiscoveryService linkDiscovery;
	private IControllerRegistryService registryService;
	private IDatagridService datagridService;
	private INetworkGraphService networkGraphService;

	private IOnosDeviceService onosDeviceService;
	
	private NetworkGraph networkGraph;
	private NetworkGraphDiscoveryInterface networkGraphDiscoveryInterface;
	
	private static final String ENABLE_CLEANUP_PROPERTY = "EnableCleanup";
	private boolean cleanupEnabled = true;
	private static final int CLEANUP_TASK_INTERVAL = 60; // in seconds
	private SingletonTask cleanupTask;

    /**
     *  Cleanup and synch switch state from registry
     */
    private class SwitchCleanup implements ControlChangeCallback, Runnable {
        @Override
        public void run() {
            String old = Thread.currentThread().getName();
            Thread.currentThread().setName("SwitchCleanup@" + old);
            
            try {
            	log.debug("Running cleanup thread");
                switchCleanup();
            }
            catch (Exception e) {
                log.error("Error in cleanup thread", e);
            } finally {
                cleanupTask.reschedule(CLEANUP_TASK_INTERVAL,
                                          TimeUnit.SECONDS);
                Thread.currentThread().setName(old);
            }
        }
        
        private void switchCleanup() {
        	Iterable<Switch> switches = networkGraph.getSwitches();

        	log.debug("Checking for inactive switches");
        	// For each switch check if a controller exists in controller registry
        	for (Switch sw: switches) {
    			try {
    				String controller = 
    						registryService.getControllerForSwitch(sw.getDpid());
    				if (controller == null) {
    					log.debug("Requesting control to set switch {} INACTIVE", 
    							HexString.toHexString(sw.getDpid()));
    					registryService.requestControl(sw.getDpid(), this);
    				}
    			} catch (RegistryException e) {
    				log.error("Caught RegistryException in cleanup thread", e);
    			}
    		}
        }

		@Override
		public void controlChanged(long dpid, boolean hasControl) {
			if (hasControl) {
				log.debug("Got control to set switch {} INACTIVE", HexString.toHexString(dpid));
				/*
				// Get the affected ports
				List<Short> ports = swStore.getPorts(HexString.toHexString(dpid));
				// Get the affected links
				List<Link> links = linkStore.getLinks(HexString.toHexString(dpid));
				// Get the affected reverse links
				List<Link> reverseLinks = linkStore.getReverseLinks(HexString.toHexString(dpid));
				links.addAll(reverseLinks);
				*/
				SwitchEvent switchEvent = new SwitchEvent(dpid);
				networkGraphDiscoveryInterface.removeSwitchDiscoveryEvent(switchEvent);
			    registryService.releaseControl(dpid);

			    // TODO publish UPDATE_SWITCH event here
			    //
			    // NOTE: Here we explicitly send
			    // notification to remove the
			    // switch, because it is inactive
			    //
			    /*
			    TopologyElement topologyElement =
				new TopologyElement(dpid);
			    datagridService.notificationSendTopologyElementRemoved(topologyElement);

			    // Publish: remove the affected ports
			    for (Short port : ports) {
				TopologyElement topologyElementPort =
				    new TopologyElement(dpid, port);
				datagridService.notificationSendTopologyElementRemoved(topologyElementPort);
			    }
			    // Publish: remove the affected links
			    for (Link link : links) {
				TopologyElement topologyElementLink =
				    new TopologyElement(link.getSrc(),
							link.getSrcPort(),
							link.getDst(),
							link.getDstPort());
				datagridService.notificationSendTopologyElementRemoved(topologyElementLink);
			    }
			    */
			}
		}
    }

	@Override
	public void linkDiscoveryUpdate(LDUpdate update) {
		LinkEvent linkEvent = new LinkEvent(update.getSrc(), 
				(long)update.getSrcPort(), update.getDst(), 
				(long)update.getDstPort());
		
		switch (update.getOperation()) {
		case LINK_ADDED:
			networkGraphDiscoveryInterface.putLinkDiscoveryEvent(linkEvent);
			/*
			TopologyElement topologyElement =
					new TopologyElement(update.getSrc(),
							update.getSrcPort(),
							update.getDst(),
							update.getDstPort());
			datagridService.notificationSendTopologyElementAdded(topologyElement);
			*/
			break;
		case LINK_UPDATED:
			// I don't know what a LINK_UPDATED event is.
			// We never use it.
			break;
		case LINK_REMOVED:
			networkGraphDiscoveryInterface.removeLinkDiscoveryEvent(linkEvent);
			/*
			TopologyElement topologyElement =
					new TopologyElement(update.getSrc(),
							update.getSrcPort(),
							update.getDst(),
							update.getDstPort());
			datagridService.notificationSendTopologyElementRemoved(topologyElement);
			*/
			break;
		default:
			break;
		}
	}

	@Override
	public void switchPortAdded(Long switchId, OFPhysicalPort port) {
		PortEvent portEvent = new PortEvent(switchId, (long)port.getPortNumber());
		networkGraphDiscoveryInterface.putPortDiscoveryEvent(portEvent);
		linkDiscovery.RemoveFromSuppressLLDPs(switchId, port.getPortNumber());
	}

	@Override
	public void switchPortRemoved(Long switchId, OFPhysicalPort port) {
		PortEvent portEvent = new PortEvent(switchId, (long)port.getPortNumber());
		networkGraphDiscoveryInterface.removePortDiscoveryEvent(portEvent);
	}

	@Override
	public void addedSwitch(IOFSwitch sw) {
		// TODO Not very robust
		if (!registryService.hasControl(sw.getId())) {
			return;
		}

		SwitchEvent switchEvent = new SwitchEvent(sw.getId());
		
		List<PortEvent> portEvents = new ArrayList<PortEvent>();
		for (OFPhysicalPort port : sw.getPorts()) {
			portEvents.add(new PortEvent(sw.getId(), (long)port.getPortNumber()));
		}
		networkGraphDiscoveryInterface.putSwitchDiscoveryEvent(switchEvent, portEvents);

		/*
		// TODO publish ADD_SWITCH event here
	    TopologyElement topologyElement =
		new TopologyElement(sw.getId());
	    datagridService.notificationSendTopologyElementAdded(topologyElement);
		*/
		
	    // Publish: add the ports
	    // TODO: Add only ports that are UP?
	    for (OFPhysicalPort port : sw.getPorts()) {
			//TopologyElement topologyElementPort =
			    //new TopologyElement(sw.getId(), port.getPortNumber());
			//datagridService.notificationSendTopologyElementAdded(topologyElementPort);

			// Allow links to be discovered on this port now that it's
			// in the database
			linkDiscovery.RemoveFromSuppressLLDPs(sw.getId(), port.getPortNumber());
	    }

	    /*
	    // Add all links that might be connected already
	    List<Link> links = linkStore.getLinks(HexString.toHexString(sw.getId()));
	    // Add all reverse links as well
	    List<Link> reverseLinks = linkStore.getReverseLinks(HexString.toHexString(sw.getId()));
	    links.addAll(reverseLinks);

	    // Publish: add the links
	    for (Link link : links) {
		TopologyElement topologyElementLink =
		    new TopologyElement(link.getSrc(),
					link.getSrcPort(),
					link.getDst(),
					link.getDstPort());
		datagridService.notificationSendTopologyElementAdded(topologyElementLink);
		*/
	}

	@Override
	public void removedSwitch(IOFSwitch sw) {
		// TODO move to cleanup thread
		//SwitchEvent switchEvent = new SwitchEvent(sw.getId());
		//networkGraphDiscoveryInterface.removeSwitchDiscoveryEvent(switchEvent);
	}

	@Override
	public void switchPortChanged(Long switchId) {
		// TODO Auto-generated method stub

	}

	@Override
	public String getName() {
		// TODO Auto-generated method stub
		return null;
	}

	/* *****************
	 * IFloodlightModule
	 * *****************/

	@Override
	public Collection<Class<? extends IFloodlightService>> getModuleServices() {
		return null;
	}

	@Override
	public Map<Class<? extends IFloodlightService>, IFloodlightService>
			getServiceImpls() {
		return null;
	}

	@Override
	public Collection<Class<? extends IFloodlightService>> getModuleDependencies() {
		Collection<Class<? extends IFloodlightService>> l =
	            new ArrayList<Class<? extends IFloodlightService>>();
        l.add(IFloodlightProviderService.class);
        l.add(ILinkDiscoveryService.class);
        l.add(IThreadPoolService.class);
        l.add(IControllerRegistryService.class);
        l.add(IDatagridService.class);
        l.add(INetworkGraphService.class);
        return l;
	}

	@Override
	public void init(FloodlightModuleContext context)
			throws FloodlightModuleException {
		floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class);
		linkDiscovery = context.getServiceImpl(ILinkDiscoveryService.class);
		registryService = context.getServiceImpl(IControllerRegistryService.class);
		datagridService = context.getServiceImpl(IDatagridService.class);
		onosDeviceService = context.getServiceImpl(IOnosDeviceService.class);

		networkGraphService = context.getServiceImpl(INetworkGraphService.class);
	}

	@Override
	public void startUp(FloodlightModuleContext context) {
		// TODO enable cleanup thread
		floodlightProvider.addOFSwitchListener(this);
		linkDiscovery.addListener(this);
		onosDeviceService.addOnosDeviceListener(this);

		networkGraph = networkGraphService.getNetworkGraph();
		networkGraphDiscoveryInterface = 
				networkGraphService.getNetworkGraphDiscoveryInterface();
		
		// Run the cleanup thread
		String enableCleanup = 
				context.getConfigParams(this).get(ENABLE_CLEANUP_PROPERTY);
		if (enableCleanup != null && enableCleanup.toLowerCase().equals("false")) {
			cleanupEnabled = false;
		}
		
		log.debug("Cleanup thread is {}enabled", (cleanupEnabled)? "" : "not ");
		
		if (cleanupEnabled) {
			IThreadPoolService threadPool = 
					context.getServiceImpl(IThreadPoolService.class);
			cleanupTask = new SingletonTask(threadPool.getScheduledExecutor(), 
					new SwitchCleanup());
			// Run the cleanup task immediately on startup
			cleanupTask.reschedule(0, TimeUnit.SECONDS);
		}
	}
	
	@Override
	public void onosDeviceAdded(OnosDevice device) {
		log.debug("Called onosDeviceAdded mac {}", device.getMacAddress());

		SwitchPort sp = new SwitchPort(device.getSwitchDPID(), (long)device.getSwitchPort());
		List<SwitchPort> spLists = new ArrayList<SwitchPort>();
		spLists.add(sp);
		DeviceEvent event = new DeviceEvent(device.getMacAddress());
		event.setAttachmentPoints(spLists);	
		event.setLastSeenTime(device.getLastSeenTimestamp().getTime());
		if(device.getIpv4Address() != null) {
			InetAddress ip = InetAddresses.fromInteger(device.getIpv4Address());	
			event.addIpAddress(ip);
		}
		//Does not use Vlan info now.
		
		networkGraphDiscoveryInterface.putDeviceDiscoveryEvent(event);	
	}

	@Override
	public void onosDeviceRemoved(OnosDevice device) {	
		log.debug("Called onosDeviceRemoved");
		DeviceEvent event = new DeviceEvent(device.getMacAddress());
		networkGraphDiscoveryInterface.removeDeviceDiscoveryEvent(event);
	}
}
