package net.onrc.onos.ofcontroller.devicemanager;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

import net.floodlightcontroller.core.FloodlightContext;
import net.floodlightcontroller.core.IFloodlightProviderService;
import net.floodlightcontroller.core.IOFMessageListener;
import net.floodlightcontroller.core.IOFSwitch;
import net.floodlightcontroller.core.IUpdate;
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.util.MACAddress;
import net.onrc.onos.datagrid.IDatagridService;
import net.onrc.onos.packet.ARP;
import net.onrc.onos.packet.DHCP;
import net.onrc.onos.packet.Ethernet;
import net.onrc.onos.packet.IPv4;
import net.onrc.onos.packet.UDP;
import net.onrc.onos.ofcontroller.networkgraph.INetworkGraphService;
import net.onrc.onos.ofcontroller.networkgraph.NetworkGraph;

import org.openflow.protocol.OFMessage;
import org.openflow.protocol.OFPacketIn;
import org.openflow.protocol.OFType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class OnosDeviceManager implements IFloodlightModule, IOFMessageListener,
										IOnosDeviceService {
	protected final static Logger log = LoggerFactory.getLogger(OnosDeviceManager.class);
	private static final int CLEANUP_SECOND = 60*60;
	private static final int AGEING_MILLSEC = 60*60*1000;

	private CopyOnWriteArrayList<IOnosDeviceListener> deviceListeners;
	private IFloodlightProviderService floodlightProvider;
	private final static ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();

	private IDatagridService datagrid;
	private Map<Long, OnosDevice> mapDevice = new ConcurrentHashMap<Long, OnosDevice>();
	private INetworkGraphService networkGraphService;
	private NetworkGraph networkGraph;

    public enum OnosDeviceUpdateType {
        ADD, DELETE, UPDATE;
    }

	private class OnosDeviceUpdate implements IUpdate {
		private OnosDevice device;
		private OnosDeviceUpdateType type;

		public OnosDeviceUpdate(OnosDevice device, OnosDeviceUpdateType type) {
			this.device = device;
			this.type = type;
		}

		@Override
		public void dispatch() {
			if(type == OnosDeviceUpdateType.ADD) {
				for(IOnosDeviceListener listener: deviceListeners) {
					listener.onosDeviceAdded(device);
				}
			} else if (type == OnosDeviceUpdateType.DELETE){
				for(IOnosDeviceListener listener: deviceListeners) {
					listener.onosDeviceRemoved(device);
				}
			}
		}
	}

	@Override
	public String getName() {
		return "onosdevicemanager";
	}

	@Override
	public boolean isCallbackOrderingPrereq(OFType type, String name) {
		// We want link discovery to consume LLDP first otherwise we'll
		// end up reading bad device info from LLDP packets
		return type == OFType.PACKET_IN && "linkdiscovery".equals(name);
	}

	@Override
	public boolean isCallbackOrderingPostreq(OFType type, String name) {
		return type == OFType.PACKET_IN &&
				("proxyarpmanager".equals(name) || "onosforwarding".equals(name));
	}

	@Override
	public Command receive(IOFSwitch sw, OFMessage msg, FloodlightContext cntx) {
		if (msg.getType().equals(OFType.PACKET_IN)) {
			OFPacketIn pi = (OFPacketIn) msg;

			Ethernet eth = IFloodlightProviderService.bcStore.
					get(cntx, IFloodlightProviderService.CONTEXT_PI_PAYLOAD);

			return processPacketIn(sw, pi, eth);
		}

		return Command.CONTINUE;
	}

	private Command processPacketIn(IOFSwitch sw, OFPacketIn pi, Ethernet eth) {
        long dpid =sw.getId();
        short portId = pi.getInPort();
        Long mac = eth.getSourceMAC().toLong();

        OnosDevice srcDevice =
                getSourceDeviceFromPacket(eth, dpid, portId);

        if (srcDevice == null){
        	return Command.STOP;
        }

        //We check if it is the same device in datagrid to suppress the device update
        OnosDevice exDev = null;
        if((exDev = mapDevice.get(mac)) != null ){
	    	if(exDev.equals(srcDevice)) {
	    		//There is the same existing device. Update only ActiveSince time.
	        	exDev.setLastSeenTimestamp(new Date());
	        	if(log.isTraceEnabled()) {
			        log.debug("In the datagrid, there is the same device."
							+ "Only update last seen time. dpid {}, port {}, mac {}, ip {}, lastSeenTime {}",
			        		dpid, portId, srcDevice.getMacAddress(), srcDevice.getIpv4Address(), srcDevice.getLastSeenTimestamp().getTime());
	        	}
		        return Command.CONTINUE;
	    	} else if (srcDevice.getIpv4Address() == null &&
	    			exDev.getSwitchDPID().equals(srcDevice.getSwitchDPID()) &&
	    			exDev.getSwitchPort() == srcDevice.getSwitchPort()) {
	    			//Vlan should be handled based on the Onos spec. Until then, don't handle it.
		    		//Device attachment point and mac address are the same
		    		//but the packet does not have an ip address.
		        	exDev.setLastSeenTimestamp(new Date());
		        	if(log.isTraceEnabled()) {
			        	log.debug("In the datagrid, there is the same device with no ip."
								+ "Keep ip and update last seen time. dpid {}, port {}, mac {}, ip {} lastSeenTime {}",
								dpid, portId, srcDevice.getMacAddress(), exDev.getIpv4Address(), srcDevice.getLastSeenTimestamp().getTime());
		        	}
		        	return Command.CONTINUE;
	    		}
	    	}

        //If the switch port we try to attach a new device already has a link, then stop adding device
        if(networkGraph.getLink(dpid, (long)portId) != null) {
			if(log.isTraceEnabled()) {
    			log.debug("Stop adding OnosDevice {} due to there is a link to: dpid {} port {}",
						srcDevice.getMacAddress(), dpid, portId);
			}
			return Command.CONTINUE;
        }

        addOnosDevice(mac, srcDevice);

        if(log.isTraceEnabled()) {
	        log.debug("Add device info in the set. dpid {}, port {}, mac {}, ip {}, lastSeenTime {}",
	       		dpid, portId, srcDevice.getMacAddress(), srcDevice.getIpv4Address(), srcDevice.getLastSeenTimestamp().getTime());
        }
        return Command.CONTINUE;
	}

     //Thread to delete devices periodically.
	 //Remove all devices from the map first and then finally delete devices from the DB.
	private class CleanDevice implements Runnable {
		@Override
		public void run() {
			log.debug("called CleanDevice");
			try{
		        	Set<OnosDevice> deleteSet = new HashSet<OnosDevice>();
			        for (OnosDevice dev : mapDevice.values() ) {
			        	long now = new Date().getTime();
			        	if((now - dev.getLastSeenTimestamp().getTime() > AGEING_MILLSEC)) {
			        		if(log.isTraceEnabled()) {
			        			log.debug("Remove device info in the datagrid. dpid {}, port {}, mac {}, ip {}, lastSeenTime {}, diff {}",
				        				dev.getSwitchDPID(), dev.getSwitchPort(), dev.getMacAddress(), dev.getIpv4Address(),
				        				dev.getLastSeenTimestamp().getTime(), now - dev.getLastSeenTimestamp().getTime());
			        		}
			        		deleteSet.add(dev);
			        	}
			        }

			        for(OnosDevice dev : deleteSet) {
			        	deleteOnosDevice(dev);
			        }
			 } catch(Exception e) {
		    	 log.error("Error:", e);
		     }
		}
	}

    /**
     * Get IP address from packet if the packet is either an ARP
     * or a DHCP packet
     * @param eth
     * @param dlAddr
     * @return
     */
    private int getSrcNwAddr(Ethernet eth, long dlAddr) {
        if (eth.getPayload() instanceof ARP) {
            ARP arp = (ARP) eth.getPayload();
            if ((arp.getProtocolType() == ARP.PROTO_TYPE_IP) &&
                    (Ethernet.toLong(arp.getSenderHardwareAddress()) == dlAddr)) {
                return IPv4.toIPv4Address(arp.getSenderProtocolAddress());
            }
        } else if (eth.getPayload() instanceof IPv4) {
            IPv4 ipv4 = (IPv4) eth.getPayload();
            if (ipv4.getPayload() instanceof UDP) {
                UDP udp = (UDP)ipv4.getPayload();
                if (udp.getPayload() instanceof DHCP) {
                    DHCP dhcp = (DHCP)udp.getPayload();
                    if (dhcp.getOpCode() == DHCP.OPCODE_REPLY) {
                        return ipv4.getSourceAddress();
                    }
                }
            }
        }
        return 0;
    }

    /**
     * Parse an entity from an {@link Ethernet} packet.
     * @param eth the packet to parse
     * @param sw the switch on which the packet arrived
     * @param pi the original packetin
     * @return the entity from the packet
     */
    private OnosDevice getSourceDeviceFromPacket(Ethernet eth,
                                             long swdpid,
                                             short port) {
        byte[] dlAddrArr = eth.getSourceMACAddress();
        long dlAddr = Ethernet.toLong(dlAddrArr);

        // Ignore broadcast/multicast source
        if ((dlAddrArr[0] & 0x1) != 0)
            return null;

        short vlan = eth.getVlanID();
        int nwSrc = getSrcNwAddr(eth, dlAddr);
        return new OnosDevice(MACAddress.valueOf(dlAddr),
                          ((vlan >= 0) ? vlan : null),
                          ((nwSrc != 0) ? nwSrc : null),
                          swdpid,
                          port,
                          new Date());
    }

	@Override
	public Collection<Class<? extends IFloodlightService>> getModuleServices() {
		List<Class<? extends IFloodlightService>> services =
				new ArrayList<Class<? extends IFloodlightService>>();
		services.add(IOnosDeviceService.class);
		return services;
	}

	@Override
	public Map<Class<? extends IFloodlightService>, IFloodlightService> getServiceImpls() {
		Map<Class<? extends IFloodlightService>, IFloodlightService> impls =
				new HashMap<Class<? extends IFloodlightService>, IFloodlightService>();
		impls.put(IOnosDeviceService.class, this);
		return impls;
	}

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

	@Override
	public void init(FloodlightModuleContext context)
			throws FloodlightModuleException {
		floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class);
		executor.scheduleAtFixedRate(new CleanDevice(), 30 ,CLEANUP_SECOND, TimeUnit.SECONDS);

		deviceListeners = new CopyOnWriteArrayList<IOnosDeviceListener>();
		datagrid = context.getServiceImpl(IDatagridService.class);
		networkGraphService = context.getServiceImpl(INetworkGraphService.class);
		networkGraph = networkGraphService.getNetworkGraph();
	}

	@Override
	public void startUp(FloodlightModuleContext context) {
		floodlightProvider.addOFMessageListener(OFType.PACKET_IN, this);
		datagrid.registerMapDeviceEventHandler(new MapDevListener());
	}

    @Override
	public void deleteOnosDevice(OnosDevice dev) {
		datagrid.sendNotificationDeviceDeleted(dev);
		floodlightProvider.publishUpdate(new OnosDeviceUpdate(dev, OnosDeviceUpdateType.DELETE));
	}
    
    @Override
	public void deleteOnosDeviceByMac(MACAddress mac) {
    	OnosDevice deleteDevice = mapDevice.get(mac);
    	deleteOnosDevice(deleteDevice);
	}
	
	@Override
	public void addOnosDevice(Long mac, OnosDevice dev) {
        datagrid.sendNotificationDeviceAdded(mac, dev);
        floodlightProvider.publishUpdate(new OnosDeviceUpdate(dev, OnosDeviceUpdateType.ADD));
	}

	//This is listener for datagrid mapDevice change.
    class MapDevListener implements IDeviceEventHandler {

		@Override
		public void addDeviceEvent(Long mac, OnosDevice dev) {
			mapDevice.put(mac, dev);
			log.debug("addDeviceMap: device mac {}", mac);
		}

		@Override
		public void deleteDeviceEvent(Long mac, OnosDevice dev) {
			mapDevice.remove(mac);
			log.debug("deleteDeviceMap: device mac {}", mac);
		}

		@Override
		public void updateDeviceEvent(Long mac, OnosDevice dev) {
			mapDevice.put(mac, dev);
			log.debug("updateDeviceMap: device mac {}", mac);
		}
    }

	@Override
	public void addOnosDeviceListener(IOnosDeviceListener listener) {
		deviceListeners.add(listener);
	}

	@Override
	public void deleteOnosDeviceListener(IOnosDeviceListener listener) {
		deviceListeners.remove(listener);
	}
}
