package net.onrc.onos.core.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.core.datagrid.IDatagridService;
import net.onrc.onos.core.datagrid.IEventChannel;
import net.onrc.onos.core.datagrid.IEventChannelListener;
import net.onrc.onos.core.packet.ARP;
import net.onrc.onos.core.packet.DHCP;
import net.onrc.onos.core.packet.Ethernet;
import net.onrc.onos.core.packet.IPv4;
import net.onrc.onos.core.packet.UDP;
import net.onrc.onos.core.topology.INetworkGraphService;
import net.onrc.onos.core.topology.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,
        IEventChannelListener<Long, OnosDevice> {
    private static final 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 static final ScheduledExecutorService EXECUTOR_SERVICE = Executors.newSingleThreadScheduledExecutor();

    private IDatagridService datagrid;
    private IEventChannel<Long, OnosDevice> eventChannel;
    private static final String DEVICE_CHANNEL_NAME = "onos.device";
    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 = mapDevice.get(mac);
        if (exDev != 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_SERVICE.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);
        eventChannel = datagrid.addListener(DEVICE_CHANNEL_NAME, this,
                Long.class,
                OnosDevice.class);
    }

    @Override
    public void deleteOnosDevice(OnosDevice dev) {
        Long mac = dev.getMacAddress().toLong();
        eventChannel.removeEntry(mac);
        floodlightProvider.publishUpdate(new OnosDeviceUpdate(dev, OnosDeviceUpdateType.DELETE));
    }

    @Override
    public void deleteOnosDeviceByMac(MACAddress mac) {
        OnosDevice deleteDevice = mapDevice.get(mac.toLong());
        deleteOnosDevice(deleteDevice);
    }

    @Override
    public void addOnosDevice(Long mac, OnosDevice dev) {
        eventChannel.addEntry(mac, dev);
        floodlightProvider.publishUpdate(new OnosDeviceUpdate(dev, OnosDeviceUpdateType.ADD));
    }

    @Override
    public void entryAdded(OnosDevice dev) {
        Long mac = dev.getMacAddress().toLong();
        mapDevice.put(mac, dev);
        log.debug("Device added: device mac {}", mac);
    }

    @Override
    public void entryRemoved(OnosDevice dev) {
        Long mac = dev.getMacAddress().toLong();
        mapDevice.remove(mac);
        log.debug("Device removed: device mac {}", mac);
    }

    @Override
    public void entryUpdated(OnosDevice dev) {
        Long mac = dev.getMacAddress().toLong();
        mapDevice.put(mac, dev);
        log.debug("Device updated: device mac {}", mac);
    }

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

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