package net.onrc.onos.core.packetservice;

import java.util.ArrayList;
import java.util.Collection;
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 net.floodlightcontroller.core.FloodlightContext;
import net.floodlightcontroller.core.IFloodlightProviderService;
import net.floodlightcontroller.core.IOFMessageListener;
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.onrc.onos.api.packet.IPacketListener;
import net.onrc.onos.api.packet.IPacketService;
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.flowprogrammer.IFlowPusherService;
import net.onrc.onos.core.main.config.IConfigInfoService;
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.Switch;
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.SwitchPort;

import org.projectfloodlight.openflow.protocol.OFFactory;
import org.projectfloodlight.openflow.protocol.OFMessage;
import org.projectfloodlight.openflow.protocol.OFPacketIn;
import org.projectfloodlight.openflow.protocol.OFPacketOut;
import org.projectfloodlight.openflow.protocol.OFPortDesc;
import org.projectfloodlight.openflow.protocol.OFType;
import org.projectfloodlight.openflow.protocol.action.OFAction;
import org.projectfloodlight.openflow.types.OFPort;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;

public class PacketModule implements IOFMessageListener, IPacketService,
        IFloodlightModule {
    private static final Logger log = LoggerFactory.getLogger(PacketModule.class);

    private final CopyOnWriteArrayList<IPacketListener> listeners;

    private IFloodlightProviderService floodlightProvider;
    private MutableTopology mutableTopology;
    private IDatagridService datagrid;
    private IFlowPusherService flowPusher;
    private IConfigInfoService configService;

    private IEventChannel<Long, PacketOutNotification> packetOutEventChannel;

    private static final String PACKET_OUT_CHANNEL_NAME =
            "onos.packet_out";

    private PacketOutEventHandler packetOutEventHandler =
            new PacketOutEventHandler();

    private class PacketOutEventHandler implements
            IEventChannelListener<Long, PacketOutNotification> {

        @Override
        public void entryAdded(PacketOutNotification value) {
            Multimap<Long, Short> localPorts = HashMultimap.create();

            for (IOFSwitch sw : floodlightProvider.getSwitches().values()) {
                for (OFPortDesc port : sw.getEnabledPorts()) {
                    // XXX S fix this to int
                    localPorts.put(sw.getId(), port.getPortNo().getShortPortNumber());
                }
            }

            Multimap<Long, Short> outPorts = value.calculateOutPorts(
                    localPorts, mutableTopology);
            sendPacketToSwitches(outPorts, value.getPacketData());
        }

        @Override
        public void entryUpdated(PacketOutNotification value) {
            entryAdded(value);
        }

        @Override
        public void entryRemoved(PacketOutNotification value) {
            // Not used
        }
    }

    public PacketModule() {
        listeners = new CopyOnWriteArrayList<>();
    }

    @Override
    public void registerPacketListener(IPacketListener listener) {
        listeners.addIfAbsent(listener);
    }

    @Override
    public void sendPacket(Ethernet eth, SwitchPort switchPort) {
        SinglePacketOutNotification notification =
                new SinglePacketOutNotification(eth.serialize(), 0,
                        switchPort.getDpid().value(), switchPort.getPortNumber().shortValue());

        // TODO We shouldn't care what the destination MAC is
        long dstMac = eth.getDestinationMAC().toLong();
        packetOutEventChannel.addTransientEntry(dstMac, notification);
    }

    @Override
    public void sendPacket(Ethernet eth, List<SwitchPort> switchPorts) {
        // TODO Auto-generated method stub
        throw new UnsupportedOperationException("Not yet implemented");
    }

    @Override
    public void broadcastPacketOutInternalEdge(Ethernet eth) {
        // TODO Auto-generated method stub
        throw new UnsupportedOperationException("Not yet implemented");
    }

    @Override
    public void broadcastPacketOutInternalEdge(Ethernet eth, SwitchPort inSwitchPort) {

        Set<SwitchPort> blacklistSwitchPorts = new HashSet<SwitchPort>(configService
                .getExternalSwitchPorts());
        blacklistSwitchPorts.add(inSwitchPort);

        BroadcastPacketOutNotification notification =
                new BroadcastPacketOutNotification(eth.serialize(), 0,
                        blacklistSwitchPorts);

        long dstMac = eth.getDestinationMAC().toLong();
        packetOutEventChannel.addTransientEntry(dstMac, notification);
    }

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

    @Override
    public boolean isCallbackOrderingPrereq(OFType type, String name) {
        return false;
    }

    @Override
    public boolean isCallbackOrderingPostreq(OFType type, String name) {
        return false;
    }

    @Override
    public Command receive(IOFSwitch sw, OFMessage msg,
            FloodlightContext cntx) {
        if (!(msg instanceof OFPacketIn)) {
            return Command.CONTINUE;
        }

        Ethernet eth = IFloodlightProviderService.bcStore.
                get(cntx, IFloodlightProviderService.CONTEXT_PI_PAYLOAD);
        // FIXME losing port number precision
        short inport = (short) cntx.getStorage()
                .get(IFloodlightProviderService.CONTEXT_PI_INPORT);

        Switch topologySwitch;
        Port inPort;
        try {
            mutableTopology.acquireReadLock();
            Dpid dpid = new Dpid(sw.getId());
            PortNumber p = PortNumber.uint16(inport);
            topologySwitch = mutableTopology.getSwitch(dpid);
            inPort = mutableTopology.getPort(dpid, p);
        } finally {
            mutableTopology.releaseReadLock();
        }

        if (topologySwitch == null || inPort == null) {
            // We can't send packets for switches or ports that aren't in the
            // topology yet
            return Command.CONTINUE;
        }

        for (IPacketListener listener : listeners) {
            listener.receive(topologySwitch, inPort, eth);
        }

        return Command.CONTINUE;
    }

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

    @Override
    public Map<Class<? extends IFloodlightService>, IFloodlightService>
            getServiceImpls() {

        Map<Class<? extends IFloodlightService>, IFloodlightService> serviceImpls = new HashMap<>();
        serviceImpls.put(IPacketService.class, this);
        return serviceImpls;
    }

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

    @Override
    public void init(FloodlightModuleContext context)
            throws FloodlightModuleException {
        floodlightProvider =
                context.getServiceImpl(IFloodlightProviderService.class);
        mutableTopology = context.getServiceImpl(ITopologyService.class)
                .getTopology();
        datagrid = context.getServiceImpl(IDatagridService.class);
        flowPusher = context.getServiceImpl(IFlowPusherService.class);
        configService = context.getServiceImpl(IConfigInfoService.class);
    }

    @Override
    public void startUp(FloodlightModuleContext context) {
        floodlightProvider.addOFMessageListener(OFType.PACKET_IN, this);
        packetOutEventChannel = datagrid.addListener(PACKET_OUT_CHANNEL_NAME,
                packetOutEventHandler,
                Long.class,
                PacketOutNotification.class);
    }

    private void sendPacketToSwitches(Multimap<Long, Short> outPorts,
            byte[] packetData) {
        for (Long dpid : outPorts.keySet()) {
            IOFSwitch sw = floodlightProvider.getSwitches().get(dpid);

            if (sw == null) {
                log.warn("Switch {} not found when sending packet", dpid);
                continue;
            }

            OFFactory factory = sw.getFactory();

            List<OFAction> actions = new ArrayList<>();
            for (Short port : outPorts.get(dpid)) {
                actions.add(factory.actions().output(OFPort.of(port), Short.MAX_VALUE));
            }

            OFPacketOut po = factory.buildPacketOut()
                    .setData(packetData)
                    .setActions(actions)
                    .build();

            flowPusher.add(new Dpid(sw.getId()), po);
        }
    }

}
