package net.onrc.onos.core.hostmanager;

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.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.packet.Ethernet;
import net.onrc.onos.core.topology.ITopologyService;
import net.onrc.onos.core.topology.Port;
import net.onrc.onos.core.topology.MutableTopology;
import net.onrc.onos.core.util.Dpid;
import net.onrc.onos.core.util.PortNumber;
import net.onrc.onos.core.util.PortNumberUtils;

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

public class HostManager implements IFloodlightModule,
IOFMessageListener,
IHostService {

    private static final Logger log = LoggerFactory.getLogger(HostManager.class);
    private static final long HOST_CLEANING_INITIAL_DELAY = 30;
    private int cleanupSecondConfig = 60 * 60;
    private int agingMillisecConfig = 60 * 60 * 1000;

    private CopyOnWriteArrayList<IHostListener> hostListeners;
    private IFloodlightProviderService floodlightProvider;
    private static final ScheduledExecutorService EXECUTOR_SERVICE =
            Executors.newSingleThreadScheduledExecutor();

    private ITopologyService topologyService;
    private MutableTopology mutableTopology;

    public enum HostUpdateType {
        ADD, DELETE, UPDATE;
    }

    private class HostUpdate implements IUpdate {
        private final Host host;
        private final HostUpdateType type;

        public HostUpdate(Host host, HostUpdateType type) {
            this.host = host;
            this.type = type;
        }

        @Override
        public void dispatch() {
            if (type == HostUpdateType.ADD) {
                for (IHostListener listener : hostListeners) {
                    listener.hostAdded(host);
                }
            } else if (type == HostUpdateType.DELETE) {
                for (IHostListener listener : hostListeners) {
                    listener.hostRemoved(host);
                }
            }
        }
    }

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

    @Override
    public boolean isCallbackOrderingPrereq(OFType type, String name) {
        // We want link discovery to consume LLDP first otherwise we'll
        // end up reading bad host 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) &&
                (msg instanceof OFPacketIn)) {
            OFPacketIn pi = (OFPacketIn) msg;

            Ethernet eth = IFloodlightProviderService.bcStore.
                    get(cntx, IFloodlightProviderService.CONTEXT_PI_PAYLOAD);
            short inport = (short) cntx.getStorage()
                    .get(IFloodlightProviderService.CONTEXT_PI_INPORT);

            return processPacketIn(sw, pi, eth, inport);
        }

        return Command.CONTINUE;
    }

    // This "protected" modifier is for unit test.
    // The above "receive" method couldn't be tested
    // because of IFloodlightProviderService static final field.
    protected Command processPacketIn(IOFSwitch sw, OFPacketIn pi, Ethernet eth,
            short inport) {
        if (log.isTraceEnabled()) {
            log.trace("Receive PACKET_IN swId {}, portId {}", sw.getId(), inport);
        }

        final Dpid dpid = new Dpid(sw.getId());
        // FIXME method signature needs to be fixed. losing port number precision
        final PortNumber portNum = PortNumberUtils
                            .openFlow(sw.getOFVersion(), inport);

        Host srcHost =
                getSourceHostFromPacket(eth, dpid.value(), portNum.value());

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

        // If the switch port we try to attach a new host already has a link,
        // then don't add the host
        // TODO We probably don't need to check this here, it should be done in
        // the Topology module.
        mutableTopology.acquireReadLock();
        try {
            if (mutableTopology.getOutgoingLink(dpid, portNum) != null ||
                    mutableTopology.getIncomingLink(dpid, portNum) != null) {
                log.debug("Not adding host {} as " +
                        "there is a link on the port: dpid {} port {}",
                        srcHost.getMacAddress(), dpid, portNum);
                return Command.CONTINUE;
            }
        } finally {
            mutableTopology.releaseReadLock();
        }

        Long mac = eth.getSourceMAC().toLong();
        addHost(mac, srcHost);

        if (log.isTraceEnabled()) {
            log.trace("Add host info: {}", srcHost);
        }
        return Command.CONTINUE;
    }

    // Thread to delete hosts periodically.
    // Remove all hosts from the map first and then finally delete hosts
    // from the DB.

    // TODO This should be sharded based on host 'owner' (i.e. the instance
    // that owns the switch it is attached to). Currently any instance can
    // issue deletes for any host, which permits race conditions and could
    // cause the Topology replicas to diverge.
    private class HostCleaner implements Runnable {
        @Override
        public void run() {
            log.debug("called HostCleaner");
            mutableTopology.acquireReadLock();
            try {
                Set<net.onrc.onos.core.topology.Host> deleteSet = new HashSet<>();
                for (net.onrc.onos.core.topology.Host host : mutableTopology.getHosts()) {
                    long now = System.currentTimeMillis();
                    if ((now - host.getLastSeenTime() > agingMillisecConfig)) {
                        if (log.isTraceEnabled()) {
                            log.trace("Removing host info: mac {}, now {}, lastSeenTime {}, diff {}",
                                    host.getMacAddress(), now, host.getLastSeenTime(), now - host.getLastSeenTime());
                        }
                        deleteSet.add(host);
                    }
                }

                for (net.onrc.onos.core.topology.Host host : deleteSet) {
                    deleteHostByMac(host.getMacAddress());
                }
            } catch (Exception e) {
                // Any exception thrown by the task will prevent the Executor
                // from running the next iteration, so we need to catch and log
                // all exceptions here.
                log.error("Exception in host cleanup thread:", e);
            } finally {
                mutableTopology.releaseReadLock();
            }
        }
    }

    /**
     * Parse a host from an {@link Ethernet} packet.
     *
     * @param eth the packet to parse
     * @param swdpid the switch on which the packet arrived
     * @param port the port on which the packet arrived
     * @return the host from the packet
     */
    protected Host getSourceHostFromPacket(Ethernet eth,
            long swdpid, long port) {
        MACAddress sourceMac = eth.getSourceMAC();

        // Ignore broadcast/multicast source
        if (sourceMac.isBroadcast() || sourceMac.isBroadcast()) {
            return null;
        }

        short vlan = eth.getVlanID();
        return new Host(sourceMac,
                ((vlan >= 0) ? vlan : null),
                swdpid,
                port,
                new Date());
    }

    @Override
    public Collection<Class<? extends IFloodlightService>> getModuleServices() {
        List<Class<? extends IFloodlightService>> services =
                new ArrayList<Class<? extends IFloodlightService>>();
        services.add(IHostService.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(IHostService.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(ITopologyService.class);
        return dependencies;
    }

    @Override
    public void init(FloodlightModuleContext context)
            throws FloodlightModuleException {
        floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class);
        hostListeners = new CopyOnWriteArrayList<IHostListener>();
        topologyService = context.getServiceImpl(ITopologyService.class);
        mutableTopology = topologyService.getTopology();

        setHostManagerProperties(context);
    }

    @Override
    public void startUp(FloodlightModuleContext context) {
        floodlightProvider.addOFMessageListener(OFType.PACKET_IN, this);
        EXECUTOR_SERVICE.scheduleAtFixedRate(new HostCleaner(),
                HOST_CLEANING_INITIAL_DELAY, cleanupSecondConfig, TimeUnit.SECONDS);
    }

    @Override
    public void deleteHost(Host host) {
        floodlightProvider.publishUpdate(
                new HostUpdate(host, HostUpdateType.DELETE));
    }

    @Override
    public void deleteHostByMac(MACAddress mac) {
        Host deleteHost = null;
        mutableTopology.acquireReadLock();
        try {
            net.onrc.onos.core.topology.Host host = mutableTopology.getHostByMac(mac);

            for (Port switchPort : host.getAttachmentPoints()) {
                // We don't handle vlan now and multiple attachment points.
                deleteHost = new Host(host.getMacAddress(),
                        null,
                        switchPort.getDpid().value(),
                        switchPort.getNumber().value(),
                        new Date(host.getLastSeenTime()));
                // FIXME: remove NOPMD flag after multiple attachment points are implemented
                break; // NOPMD
            }
        } finally {
            mutableTopology.releaseReadLock();
        }

        if (deleteHost != null) {
            deleteHost(deleteHost);
        }
    }

    @Override
    public void addHost(Long mac, Host host) {
        floodlightProvider.publishUpdate(
                new HostUpdate(host, HostUpdateType.ADD));
    }

    @Override
    public void addHostListener(IHostListener listener) {
        hostListeners.add(listener);
    }

    @Override
    public void removeHostListener(IHostListener listener) {
        hostListeners.remove(listener);
    }

    private void setHostManagerProperties(FloodlightModuleContext context) {
        Map<String, String> configOptions = context.getConfigParams(this);
        String cleanupsec = configOptions.get("cleanupsec");
        String agingmsec = configOptions.get("agingmsec");
        if (cleanupsec != null) {
            cleanupSecondConfig = Integer.parseInt(cleanupsec);
            log.debug("CLEANUP_SECOND is set to {}", cleanupSecondConfig);
        }

        if (agingmsec != null) {
            agingMillisecConfig = Integer.parseInt(agingmsec);
            log.debug("AGEING_MILLSEC is set to {}", agingMillisecConfig);
        }
    }
}
