package net.floodlightcontroller.virtualnetwork;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import org.openflow.protocol.OFFlowMod;
import org.openflow.protocol.OFMatch;
import org.openflow.protocol.OFMessage;
import org.openflow.protocol.OFPacketIn;
import org.openflow.protocol.OFPacketOut;
import org.openflow.protocol.OFType;
import org.openflow.protocol.action.OFAction;
import org.openflow.util.HexString;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

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.floodlightcontroller.core.util.AppCookie;
import net.floodlightcontroller.devicemanager.IDevice;
import net.floodlightcontroller.devicemanager.IDeviceListener;
import net.floodlightcontroller.devicemanager.IDeviceService;
import net.floodlightcontroller.packet.DHCP;
import net.floodlightcontroller.packet.Ethernet;
import net.floodlightcontroller.packet.IPacket;
import net.floodlightcontroller.packet.IPv4;
import net.floodlightcontroller.restserver.IRestApiService;
import net.floodlightcontroller.routing.ForwardingBase;
import net.floodlightcontroller.util.MACAddress;

/**
 * A simple Layer 2 (MAC based) network virtualization module. This module allows
 * you to create simple L2 networks (host + gateway) and will drop traffic if
 * they are not on the same virtual network.
 * 
 * LIMITATIONS
 * - This module does not allow overlapping of IPs or MACs
 * - You can only have 1 gateway per virtual network (can be shared)
 * - There is filtering of multicast/broadcast traffic
 * - All DHCP traffic will be allowed, regardless of unicast/broadcast
 * 
 * @author alexreimers
 */
public class VirtualNetworkFilter 
    implements IFloodlightModule, IVirtualNetworkService, IOFMessageListener, IDeviceListener {
    protected static Logger log = LoggerFactory.getLogger(VirtualNetworkFilter.class);
    
    private final short APP_ID = 20;
    
    // Our dependencies
    IFloodlightProviderService floodlightProvider;
    IRestApiService restApi;
    IDeviceService deviceService;
    
    // Our internal state
    protected Map<String, VirtualNetwork> vNetsByGuid; // List of all created virtual networks 
    protected Map<String, String> nameToGuid; // Logical name -> Network ID
    protected Map<String, Integer> guidToGateway; // Network ID -> Gateway IP
    protected Map<Integer, Set<String>> gatewayToGuid; // Gateway IP -> Network ID
    protected Map<MACAddress, Integer> macToGateway; // Gateway MAC -> Gateway IP
    protected Map<MACAddress, String> macToGuid; // Host MAC -> Network ID
    protected Map<String, MACAddress> portToMac; // Host MAC -> logical port name
    
    /**
     * Adds a gateway to a virtual network.
     * @param guid The ID (not name) of the network.
     * @param ip The IP addresses of the gateway.
     */
    protected void addGateway(String guid, Integer ip) {
        if (ip.intValue() != 0) {
        	if (log.isDebugEnabled())
        		log.debug("Adding {} as gateway for GUID {}",
        				IPv4.fromIPv4Address(ip), guid);
        	
            guidToGateway.put(guid, ip);
            if (vNetsByGuid.get(guid) != null)
                vNetsByGuid.get(guid).setGateway(IPv4.fromIPv4Address(ip));
            if (gatewayToGuid.containsKey(ip)) {
                Set<String> gSet = gatewayToGuid.get(ip);
                gSet.add(guid);
            } else {
                Set<String> gSet = Collections.synchronizedSet(new HashSet<String>());
                gSet.add(guid);
                gatewayToGuid.put(ip, gSet);
            }
        }
    }
    
    /**
     * Deletes a gateway for a virtual network.
     * @param guid The ID (not name) of the network to delete
     * the gateway for.
     */
    protected void deleteGateway(String guid) {
        Integer gwIp = guidToGateway.remove(guid);
        if (gwIp == null) return;
        Set<String> gSet = gatewayToGuid.get(gwIp);
        gSet.remove(guid);
        if(vNetsByGuid.get(guid)!=null)
            vNetsByGuid.get(guid).setGateway(null);
    }
    
    // IVirtualNetworkService
    
    @Override
    public void createNetwork(String guid, String network, Integer gateway) {
        if (log.isDebugEnabled()) {
            String gw = null;
            try {
                gw = IPv4.fromIPv4Address(gateway);
            } catch (Exception e) {
                // fail silently
            }
            log.debug("Creating network {} with ID {} and gateway {}", 
                      new Object[] {network, guid, gw});
        }
        
        if (!nameToGuid.isEmpty()) {
            // We have to iterate all the networks to handle name/gateway changes
            for (Entry<String, String> entry : nameToGuid.entrySet()) {
                if (entry.getValue().equals(guid)) {
                    nameToGuid.remove(entry.getKey());
                    break;
                }
            }
        }
        nameToGuid.put(network, guid);
        if (vNetsByGuid.containsKey(guid))
            vNetsByGuid.get(guid).setName(network); //network already exists, just updating name
        else
            vNetsByGuid.put(guid, new VirtualNetwork(network, guid)); //new network
        
        // If they don't specify a new gateway the old one will be preserved
        if ((gateway != null) && (gateway != 0)) {
            addGateway(guid, gateway);
            if(vNetsByGuid.get(guid)!=null)
                vNetsByGuid.get(guid).setGateway(IPv4.fromIPv4Address(gateway));
        }
    }

    @Override
    public void deleteNetwork(String guid) {
        String name = null;
        if (nameToGuid.isEmpty()) {
            log.warn("Could not delete network with ID {}, network doesn't exist",
                     guid);
            return;
        }
        for (Entry<String, String> entry : nameToGuid.entrySet()) {
            if (entry.getValue().equals(guid)) {
                name = entry.getKey();
                break;
            }
            log.warn("Could not delete network with ID {}, network doesn't exist",
                     guid);
        }
        
        if (log.isDebugEnabled()) 
            log.debug("Deleting network with name {} ID {}", name, guid);
        
        nameToGuid.remove(name);
        deleteGateway(guid);
        if(vNetsByGuid.get(guid)!=null){
            vNetsByGuid.get(guid).clearHosts();
            vNetsByGuid.remove(guid);
        }
        Collection<MACAddress> deleteList = new ArrayList<MACAddress>();
        for (MACAddress host : macToGuid.keySet()) {
            if (macToGuid.get(host).equals(guid)) {
                deleteList.add(host);
            }
        }
        for (MACAddress mac : deleteList) {
            if (log.isDebugEnabled()) {
                log.debug("Removing host {} from network {}", 
                          HexString.toHexString(mac.toBytes()), guid);
            }
            macToGuid.remove(mac);
            for (Entry<String, MACAddress> entry : portToMac.entrySet()) {
                if (entry.getValue().equals(mac)) {
                    portToMac.remove(entry.getKey());
                    break;
                }
            }
        }
    }

    @Override
    public void addHost(MACAddress mac, String guid, String port) {
        if (guid != null) {
            if (log.isDebugEnabled()) {
                log.debug("Adding {} to network ID {} on port {}",
                          new Object[] {mac, guid, port});
            }
            // We ignore old mappings
            macToGuid.put(mac, guid);
            portToMac.put(port, mac);
            if(vNetsByGuid.get(guid)!=null)
                vNetsByGuid.get(guid).addHost(new MACAddress(mac.toBytes()));
        } else {
            log.warn("Could not add MAC {} to network ID {} on port {}, the network does not exist",
                     new Object[] {mac, guid, port});
        }
    }

    @Override
    public void deleteHost(MACAddress mac, String port) {
        if (log.isDebugEnabled()) {
            log.debug("Removing host {} from port {}", mac, port);
        }
        if (mac == null && port == null) return;
        if (port != null) {
            MACAddress host = portToMac.remove(port);
            if(vNetsByGuid.get(macToGuid.get(host)) != null)
                vNetsByGuid.get(macToGuid.get(host)).removeHost(host);
            macToGuid.remove(host);
        } else if (mac != null) {
            if (!portToMac.isEmpty()) {
                for (Entry<String, MACAddress> entry : portToMac.entrySet()) {
                    if (entry.getValue().equals(mac)) {
                        if(vNetsByGuid.get(macToGuid.get(entry.getValue())) != null)
                            vNetsByGuid.get(macToGuid.get(entry.getValue())).removeHost(entry.getValue());
                        portToMac.remove(entry.getKey());
                        macToGuid.remove(entry.getValue());
                        return;
                    }
                }
            }
        }
    }
    
    // IFloodlightModule
    
    @Override
    public Collection<Class<? extends IFloodlightService>> getModuleServices() {
        Collection<Class<? extends IFloodlightService>> l = 
                new ArrayList<Class<? extends IFloodlightService>>();
        l.add(IVirtualNetworkService.class);
        return l;
    }

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

    @Override
    public Collection<Class<? extends IFloodlightService>> getModuleDependencies() {
        Collection<Class<? extends IFloodlightService>> l = 
                new ArrayList<Class<? extends IFloodlightService>>();
        l.add(IFloodlightProviderService.class);
        l.add(IRestApiService.class);
        l.add(IDeviceService.class);
        return l;
    }

    @Override
    public void init(FloodlightModuleContext context)  
                                 throws FloodlightModuleException {
        floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class);
        restApi = context.getServiceImpl(IRestApiService.class);
        deviceService = context.getServiceImpl(IDeviceService.class);
        
        vNetsByGuid = new ConcurrentHashMap<String, VirtualNetwork>();
        nameToGuid = new ConcurrentHashMap<String, String>();
        guidToGateway = new ConcurrentHashMap<String, Integer>();
        gatewayToGuid = new ConcurrentHashMap<Integer, Set<String>>();
        macToGuid = new ConcurrentHashMap<MACAddress, String>();
        portToMac = new ConcurrentHashMap<String, MACAddress>();
        macToGateway = new ConcurrentHashMap<MACAddress, Integer>();
    }

    @Override
    public void startUp(FloodlightModuleContext context) {
        floodlightProvider.addOFMessageListener(OFType.PACKET_IN, this);
        restApi.addRestletRoutable(new VirtualNetworkWebRoutable());
        deviceService.addListener(this);
    }

    // IOFMessageListener
    
    @Override
    public String getName() {
        return "virtualizer";
    }

    @Override
    public boolean isCallbackOrderingPrereq(OFType type, String name) {
        // Link discovery should go before us so we don't block LLDPs
        return (type.equals(OFType.PACKET_IN) && 
        		(name.equals("linkdiscovery") || (name.equals("devicemanager"))));
    }

    @Override
    public boolean isCallbackOrderingPostreq(OFType type, String name) {
        // We need to go before forwarding
        return (type.equals(OFType.PACKET_IN) && name.equals("forwarding"));
    }

    @Override
    public Command receive(IOFSwitch sw, OFMessage msg, FloodlightContext cntx) {
        switch (msg.getType()) {
            case PACKET_IN:
                return processPacketIn(sw, (OFPacketIn)msg, cntx);
            default:
            	break;
        }
        log.warn("Received unexpected message {}", msg);
        return Command.CONTINUE;
    }
    
    /**
     * Checks whether the frame is destined to or from a gateway.
     * @param frame The ethernet frame to check.
     * @return True if it is to/from a gateway, false otherwise.
     */
    protected boolean isDefaultGateway(Ethernet frame) {
    	if (macToGateway.containsKey(frame.getSourceMAC()))
    		return true;
    	
    	Integer gwIp = macToGateway.get(frame.getDestinationMAC());
    	if (gwIp != null) {
    		MACAddress host = frame.getSourceMAC();
    		String srcNet = macToGuid.get(host);
    		if (srcNet != null) {
	    		Integer gwIpSrcNet = guidToGateway.get(srcNet);
	    		if ((gwIpSrcNet != null) && (gwIp.equals(gwIpSrcNet)))
	    			return true;
    		}
    	}

    	return false;
    }
    
    /**
     * Checks to see if two MAC Addresses are on the same network.
     * @param m1 The first MAC.
     * @param m2 The second MAC.
     * @return True if they are on the same virtual network,
     * 		   false otherwise.
     */
    protected boolean oneSameNetwork(MACAddress m1, MACAddress m2) {
        String net1 = macToGuid.get(m1);
        String net2 = macToGuid.get(m2);
        if (net1 == null) return false;
        if (net2 == null) return false;
        return net1.equals(net2);
    }
    
    /**
     * Checks to see if an Ethernet frame is a DHCP packet.
     * @param frame The Ethernet frame.
     * @return True if it is a DHCP frame, false otherwise.
     */
    protected boolean isDhcpPacket(Ethernet frame) {
        IPacket payload = frame.getPayload(); // IP
        if (payload == null) return false;
        IPacket p2 = payload.getPayload(); // TCP or UDP
        if (p2 == null) return false;
        IPacket p3 = p2.getPayload(); // Application
        if ((p3 != null) && (p3 instanceof DHCP)) return true;
        return false;
    }
    
    /**
     * Processes an OFPacketIn message and decides if the OFPacketIn should be dropped
     * or the processing should continue.
     * @param sw The switch the PacketIn came from.
     * @param msg The OFPacketIn message from the switch.
     * @param cntx The FloodlightContext for this message.
     * @return Command.CONTINUE if processing should be continued, Command.STOP otherwise.
     */
    protected Command processPacketIn(IOFSwitch sw, OFPacketIn msg, FloodlightContext cntx) {
        Ethernet eth = IFloodlightProviderService.bcStore.get(cntx, 
                                              IFloodlightProviderService.CONTEXT_PI_PAYLOAD);
        Command ret = Command.STOP;
        String srcNetwork = macToGuid.get(eth.getSourceMAC());
        // If the host is on an unknown network we deny it.
        // We make exceptions for ARP and DHCP.
        if (eth.isBroadcast() || eth.isMulticast() || isDefaultGateway(eth) || isDhcpPacket(eth)) {
        	ret = Command.CONTINUE;
        } else if (srcNetwork == null) {
            log.trace("Blocking traffic from host {} because it is not attached to any network.",
                      HexString.toHexString(eth.getSourceMACAddress()));
            ret = Command.STOP;
        } else if (oneSameNetwork(eth.getSourceMAC(), eth.getDestinationMAC())) {
            // if they are on the same network continue
            ret = Command.CONTINUE;
        }
        
        if (log.isTraceEnabled())
        	log.trace("Results for flow between {} and {} is {}",
        			new Object[] {eth.getSourceMAC(), eth.getDestinationMAC(), ret});
        /*
         * TODO - figure out how to still detect gateways while using
         * drop mods 
        if (ret == Command.STOP) {
            if (!(eth.getPayload() instanceof ARP))
            	doDropFlow(sw, msg, cntx);
        }
        */
        return ret;
    }
    
    /**
     * Writes a FlowMod to a switch that inserts a drop flow.
     * @param sw The switch to write the FlowMod to.
     * @param pi The corresponding OFPacketIn. Used to create the OFMatch structure.
     * @param cntx The FloodlightContext that gets passed to the switch.
     */
    protected void doDropFlow(IOFSwitch sw, OFPacketIn pi, FloodlightContext cntx) {
        if (log.isTraceEnabled()) {
            log.trace("doDropFlow pi={} srcSwitch={}",
                    new Object[] { pi, sw });
        }

        if (sw == null) {
            log.warn("Switch is null, not installing drop flowmod for PacketIn {}", pi);
            return;
        }

        // Create flow-mod based on packet-in and src-switch
        OFFlowMod fm = 
            (OFFlowMod) floodlightProvider.getOFMessageFactory().getMessage(OFType.FLOW_MOD);
        OFMatch match = new OFMatch();
        match.loadFromPacket(pi.getPacketData(), pi.getInPort());
        List<OFAction> actions = new ArrayList<OFAction>(); // no actions = drop
        long cookie = AppCookie.makeCookie(APP_ID, 0);
        fm.setCookie(cookie)
        .setIdleTimeout(ForwardingBase.FLOWMOD_DEFAULT_IDLE_TIMEOUT)
        .setHardTimeout(ForwardingBase.FLOWMOD_DEFAULT_HARD_TIMEOUT)
        .setBufferId(OFPacketOut.BUFFER_ID_NONE)
        .setMatch(match)
        .setActions(actions)
        .setLengthU(OFFlowMod.MINIMUM_LENGTH);
        fm.setFlags(OFFlowMod.OFPFF_SEND_FLOW_REM);
        try {
            if (log.isTraceEnabled()) {
                log.trace("write drop flow-mod srcSwitch={} match={} " + 
                          "pi={} flow-mod={}",
                          new Object[] {sw, match, pi, fm});
            }
            sw.write(fm, cntx);
        } catch (IOException e) {
            log.error("Failure writing drop flow mod", e);
        }
        return;
    }

    // IDeviceListener
    
	@Override
	public void deviceAdded(IDevice device) {
		if (device.getIPv4Addresses() == null) return;
		for (Integer i : device.getIPv4Addresses()) {
			if (gatewayToGuid.containsKey(i)) {
				MACAddress mac = MACAddress.valueOf(device.getMACAddress());
				if (log.isDebugEnabled())
					log.debug("Adding MAC {} with IP {} a a gateway",
							HexString.toHexString(mac.toBytes()),
							IPv4.fromIPv4Address(i));
				macToGateway.put(mac, i);
			}
		}
	}

	@Override
	public void deviceRemoved(IDevice device) {
		// if device is a gateway remove
		MACAddress mac = MACAddress.valueOf(device.getMACAddress());
		if (macToGateway.containsKey(mac)) {
			if (log.isDebugEnabled())
				log.debug("Removing MAC {} as a gateway",
						HexString.toHexString(mac.toBytes()));
			macToGateway.remove(mac);
		}
	}

	@Override
	public void deviceIPV4AddrChanged(IDevice device) {
		// add or remove entry as gateway
		deviceAdded(device);
	}

	@Override
	public void deviceMoved(IDevice device) {
		// ignore
	}
	
	@Override
	public void deviceVlanChanged(IDevice device) {
		// ignore
	}

    @Override
    public Collection <VirtualNetwork> listNetworks() {
        return vNetsByGuid.values();
        
    }
}
