package net.floodlightcontroller.bgproute;

import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;
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 net.floodlightcontroller.core.IFloodlightProviderService;
import net.floodlightcontroller.core.INetMapTopologyService.ITopoRouteService;
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.devicemanager.IDeviceService;
import net.floodlightcontroller.packet.Ethernet;
import net.floodlightcontroller.restserver.IRestApiService;
import net.floodlightcontroller.topology.ITopologyListener;
import net.floodlightcontroller.topology.ITopologyService;
import net.floodlightcontroller.util.DataPath;
import net.floodlightcontroller.util.Dpid;
import net.floodlightcontroller.util.FlowEntry;
import net.floodlightcontroller.util.IPv4;
import net.floodlightcontroller.util.MACAddress;
import net.floodlightcontroller.util.Port;
import net.floodlightcontroller.util.SwitchPort;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import net.sf.json.JSONSerializer;

import org.openflow.protocol.OFFlowMod;
import org.openflow.protocol.OFMatch;
import org.openflow.protocol.OFMessage;
import org.openflow.protocol.OFPacketOut;
import org.openflow.protocol.OFType;
import org.openflow.protocol.action.OFAction;
import org.openflow.protocol.action.OFActionDataLayerDestination;
import org.openflow.protocol.action.OFActionOutput;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.net.InetAddresses;

public class BgpRoute implements IFloodlightModule, IBgpRouteService, ITopologyListener {
	
	protected static Logger log = LoggerFactory.getLogger(BgpRoute.class);

	protected IFloodlightProviderService floodlightProvider;
	protected ITopologyService topology;
	protected ITopoRouteService topoRouteService;
	protected IDeviceService devices;
	protected IRestApiService restApi;
	
	
	protected static Ptree ptree;
	protected String bgpdRestIp;
	protected String routerId;
	
	protected Set<InetAddress> routerIpAddresses;
	
	//We need to identify our flows somehow. But like it says in LearningSwitch.java,
	//the controller/OS should hand out cookie IDs to prevent conflicts.
	protected final long APP_COOKIE = 0xa0000000000000L;
	//Cookie for flows that do L2 forwarding within SDN domain to egress routers
	protected final long L2_FWD_COOKIE = APP_COOKIE + 1;
	//Cookie for flows in ingress switches that rewrite the MAC address
	protected final long MAC_RW_COOKIE = APP_COOKIE + 2;
	
	//TODO temporary
	protected List<GatewayRouter> gatewayRouters;
	
	private void initGateways(){
		gatewayRouters = new ArrayList<GatewayRouter>();
		//00:00:00:00:00:00:0s0:a3 port 1
		gatewayRouters.add(
				new GatewayRouter(new SwitchPort(new Dpid(163L), new Port((short)1)),
				new MACAddress(new byte[] {0x00, 0x00, 0x00, 0x00, 0x02, 0x01}),
				new IPv4("192.168.10.1")));
		//00:00:00:00:00:00:00:a5 port 1
		//gatewayRouters.add(new SwitchPort(new Dpid(165L), new Port((short)1)));
		gatewayRouters.add(
				new GatewayRouter(new SwitchPort(new Dpid(165L), new Port((short)1)),
				new MACAddress(new byte[] {0x00, 0x00, 0x00, 0x00, 0x02, 0x02}),
				new IPv4("192.168.20.1")));
		//00:00:00:00:00:00:00:a2 port 1
		//gatewayRouters.add(new SwitchPort(new Dpid(162L), new Port((short)1)));
		gatewayRouters.add(
				new GatewayRouter(new SwitchPort(new Dpid(162L), new Port((short)1)),
				new MACAddress(new byte[] {0x00, 0x00, 0x00, 0x00, 0x03, 0x01}),
				new IPv4("192.168.30.1")));
		//00:00:00:00:00:00:00:a6
		//gatewayRouters.add(new SwitchPort(new Dpid(166L), new Port((short)1)));
		gatewayRouters.add(
				new GatewayRouter(new SwitchPort(new Dpid(166L), new Port((short)1)),
				new MACAddress(new byte[] {0x00, 0x00, 0x00, 0x00, 0x04, 0x01}),
				new IPv4("192.168.40.1")));
		
	}
	
	@Override
	public Collection<Class<? extends IFloodlightService>> getModuleServices() {
		Collection<Class<? extends IFloodlightService>> l 
			= new ArrayList<Class<? extends IFloodlightService>>();
		l.add(IBgpRouteService.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(IBgpRouteService.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(ITopologyService.class);
		l.add(ITopoRouteService.class);
		l.add(IDeviceService.class);
		l.add(IRestApiService.class);
		//l.add(IBgpRouteService.class);
		return l;
	}
	
	@Override
	public void init(FloodlightModuleContext context)
			throws FloodlightModuleException {
	    
		initGateways();
		
	    ptree = new Ptree(32);
	    
	    routerIpAddresses = new HashSet<InetAddress>();
		
		// Register floodlight provider and REST handler.
		floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class);
		topology = context.getServiceImpl(ITopologyService.class);
		topoRouteService = context.getServiceImpl(ITopoRouteService.class);
		devices = context.getServiceImpl(IDeviceService.class);
		restApi = context.getServiceImpl(IRestApiService.class);		
		
		//Read in config values
		bgpdRestIp = context.getConfigParams(this).get("BgpdRestIp");
		if (bgpdRestIp == null){
			log.error("BgpdRestIp property not found in config file");
			System.exit(1);
		}
		else {
			log.info("BgpdRestIp set to {}", bgpdRestIp);
		}
		
		routerId = context.getConfigParams(this).get("RouterId");
		if (routerId == null){
			log.error("RouterId property not found in config file");
			System.exit(1);
		}
		else {
			log.info("RouterId set to {}", routerId);
		}
		// Test.
		//test();
	}

	public Ptree getPtree() {
		return ptree;
	}
	
	public void clearPtree() {
		//ptree = null;
		ptree = new Ptree(32);	
	}
	
	public String getBGPdRestIp() {
		return bgpdRestIp;
	}
	
	public String getRouterId() {
		return routerId;
	}
	
	// Return nexthop address as byte array.
	public Rib lookupRib(byte[] dest) {
		if (ptree == null) {
		    log.debug("lookupRib: ptree null");
		    return null;
		}
		
		PtreeNode node = ptree.match(dest, 32);
		if (node == null) {
            log.debug("lookupRib: ptree node null");
			return null;
		}
		
		if (node.rib == null) {
            log.debug("lookupRib: ptree rib null");
			return null;
		}
		
		ptree.delReference(node);
		
		return node.rib;
	}
	
	//TODO looks like this should be a unit test
	@SuppressWarnings("unused")
    private void test() throws UnknownHostException {
		System.out.println("Here it is");
		Prefix p = new Prefix("128.0.0.0", 8);
		Prefix q = new Prefix("8.0.0.0", 8);
		Prefix r = new Prefix("10.0.0.0", 24);
		Prefix a = new Prefix("10.0.0.1", 32);
	
		ptree.acquire(p.getAddress(), p.masklen);
		ptree.acquire(q.getAddress(), q.masklen);
		ptree.acquire(r.getAddress(), r.masklen);
	
		System.out.println("Traverse start");
		for (PtreeNode node = ptree.begin(); node != null; node = ptree.next(node)) {
			Prefix p_result = new Prefix(node.key, node.keyBits);
		}
	
		PtreeNode n = ptree.match(a.getAddress(), a.masklen);
		if (n != null) {
			System.out.println("Matched prefix for 10.0.0.1:");
			Prefix x = new Prefix(n.key, n.keyBits);
			ptree.delReference(n);
		}
		
		n = ptree.lookup(p.getAddress(), p.masklen);
		if (n != null) {
			ptree.delReference(n);
			ptree.delReference(n);
		}
		System.out.println("Traverse start");
		for (PtreeNode node = ptree.begin(); node != null; node = ptree.next(node)) {
			Prefix p_result = new Prefix(node.key, node.keyBits);
		}
		
		n = ptree.lookup(q.getAddress(), q.masklen);
		if (n != null) {
			ptree.delReference(n);
			ptree.delReference(n);
		}
		System.out.println("Traverse start");
		for (PtreeNode node = ptree.begin(); node != null; node = ptree.next(node)) {
			Prefix p_result = new Prefix(node.key, node.keyBits);
		}
		
		n = ptree.lookup(r.getAddress(), r.masklen);
		if (n != null) {
			ptree.delReference(n);
			ptree.delReference(n);
		}
		System.out.println("Traverse start");
		for (PtreeNode node = ptree.begin(); node != null; node = ptree.next(node)) {
			Prefix p_result = new Prefix(node.key, node.keyBits);
		}

	}
	
	private void retrieveRib(){
		String url = "http://" + bgpdRestIp + "/wm/bgp/" + routerId;
		String response = RestClient.get(url);
		
		if (response.equals("")){
			return;
		}
		
		response = response.replaceAll("\"", "'");
		JSONObject jsonObj = (JSONObject) JSONSerializer.toJSON(response);  
		JSONArray rib_json_array = jsonObj.getJSONArray("rib");
		String router_id = jsonObj.getString("router-id");

		int size = rib_json_array.size();

		log.info("Retrived RIB of {} entries from BGPd", size);
		
		for (int j = 0; j < size; j++) {
			JSONObject second_json_object = rib_json_array.getJSONObject(j);
			String prefix = second_json_object.getString("prefix");
			String nexthop = second_json_object.getString("nexthop");

			//insert each rib entry into the local rib;
			String[] substring = prefix.split("/");
			String prefix1 = substring[0];
			String mask1 = substring[1];

			Prefix p;
			try {
				p = new Prefix(prefix1, Integer.valueOf(mask1));
			} catch (NumberFormatException e) {
				log.warn("Wrong mask format in RIB JSON: {}", mask1);
				continue;
			} catch (UnknownHostException e1) {
				log.warn("Wrong prefix format in RIB JSON: {}", prefix1);
				continue;
			}
			
			PtreeNode node = ptree.acquire(p.getAddress(), p.masklen);
			Rib rib = new Rib(router_id, nexthop, p.masklen);
			
			if (node.rib != null) {
				node.rib = null;
				ptree.delReference(node);
			}
			
			node.rib = rib;
			
			newPrefix(node);
		} 
	}
	
	private void newPrefix(PtreeNode node) {
		//Add a flow to rewrite mac for this prefix to all border switches
		GatewayRouter thisRouter = null;
		for (GatewayRouter router : gatewayRouters){
			log.debug("Matching router ip {} with RIB routerId {}",
					router.getRouterIp().value(), InetAddresses.coerceToInteger(node.rib.routerId));
			
			if (router.getRouterIp().value() == InetAddresses.coerceToInteger(node.rib.routerId)){
				thisRouter = router;
				break;
			}
		}
		
		if (thisRouter == null){
			log.error("Couldn't find advertising router in router list for prefix {}", node.rib);
			return; //just quit out here? This is probably a configuration error
		}
		
		for (GatewayRouter ingressRouter : gatewayRouters){
			if (ingressRouter == thisRouter) {
				continue;
			}
			
			DataPath shortestPath = topoRouteService.getShortestPath(
					ingressRouter.getAttachmentPoint(), thisRouter.getAttachmentPoint());
			
			if (shortestPath == null){
				log.debug("Shortest path between {} and {} not found",
						ingressRouter.getAttachmentPoint(), thisRouter.getAttachmentPoint());
				return; // just quit here?
			}
			
			//TODO check the shortest path against the cached version we
			//calculated before. If they don't match up that's a problem
			
			//Set up the flow mod
			OFFlowMod fm =
	                (OFFlowMod) floodlightProvider.getOFMessageFactory()
	                                              .getMessage(OFType.FLOW_MOD);
			
	        fm.setIdleTimeout((short)0)
	        .setHardTimeout((short)0)
	        .setBufferId(OFPacketOut.BUFFER_ID_NONE)
	        .setCookie(MAC_RW_COOKIE)
	        .setCommand(OFFlowMod.OFPFC_ADD)
	        //.setMatch(match)
	        //.setActions(actions)
	        .setLengthU(OFFlowMod.MINIMUM_LENGTH
	        		+ OFActionDataLayerDestination.MINIMUM_LENGTH
	        		+ OFActionOutput.MINIMUM_LENGTH);
	        
	        OFMatch match = new OFMatch();
	        match.setDataLayerType(Ethernet.TYPE_IPv4);
	        //match.setNetworkDestination(InetAddresses.coerceToInteger(node.rib.getNextHop()));
	        //TODO set mask length
	        
	        log.debug("finding prefix, {}", InetAddresses.fromInteger(node.keyBits).toString());
	        //match.setFromCIDR(node.keyBits, which)
	        //match.setw
	        //fm.setMatch(match);
	        
	        //Set up MAC rewrite action
	        OFActionDataLayerDestination macRewriteAction = new OFActionDataLayerDestination();
	        macRewriteAction.setDataLayerAddress(thisRouter.getRouterMac().toBytes());
	        
	        //Set up output action
	        OFActionOutput outputAction = new OFActionOutput();
	        outputAction.setMaxLength((short)0xffff); //TODO check what this is (and if needed for mac rewrite)
	        
	        List<OFAction> actions = new ArrayList<OFAction>();
	        actions.add(macRewriteAction);
	        actions.add(outputAction);
	        fm.setActions(actions);
	        
	        //Write to switch
	        IOFSwitch sw = floodlightProvider.getSwitches()
	        		.get(ingressRouter.getAttachmentPoint().dpid().value());
	        
            if (sw == null){
            	log.warn("Switch not found when pushing flow mod");
            	continue;
            }
            
            List<OFMessage> msglist = new ArrayList<OFMessage>();
            msglist.add(fm);
            try {
				sw.write(msglist, null);
				sw.flush();
			} catch (IOException e) {
				log.error("Failure writing flow mod", e);
			}
		}
	}
	
	private void prefixDelete(PtreeNode node) {
		//Remove MAC rewriting flows from other border switches
	}
	
	/*
	 * On startup we need to calculate a full mesh of paths between all gateway
	 * switches
	 */
	private void calculateFullMesh(){
		Map<IOFSwitch, SwitchPort> gatewaySwitches = new HashMap<IOFSwitch, SwitchPort>();
		
		//have to account for switches not being there, paths not being found.
		
		//for (SwitchPort switchPort : gatewayRouters){
		for (GatewayRouter router : gatewayRouters){
			SwitchPort switchPort = router.getAttachmentPoint();
			
			IOFSwitch sw = floodlightProvider.getSwitches().get(switchPort.dpid().value());
			
			if (sw == null){
				log.debug("Gateway switch {} not here yet", switchPort.dpid().value());
				return; // just quit here?
			}
			
			//Only need to know 1 external-facing port from each gateway switch
			//which we can feed into shortest path calculation
			if (!gatewaySwitches.containsKey(sw)){
				gatewaySwitches.put(sw, switchPort);
			}
			
		}
		log.debug("size {}", gatewaySwitches.size());
		
		//For each border router, calculate and install a path from every other
		//border switch to said border router. However, don't install the entry
		//in to the first hop switch, as we need to install an entry to rewrite
		//for each prefix received. This will be done later when prefixes have 
		//actually been received.
		
		//for (Map.Entry<IOFSwitch, SwitchPort> src : gatewaySwitches.entrySet()){
		for (GatewayRouter dstRouter : gatewayRouters){
			SwitchPort routerAttachmentPoint = dstRouter.getAttachmentPoint();
			for (Map.Entry<IOFSwitch, SwitchPort> src : gatewaySwitches.entrySet()) {
		//List<IOFSwitch> switches = new ArrayList<IOFSwitch>(gatewaySwitches.keySet());
		
				if (routerAttachmentPoint.dpid().value() == 
						src.getKey().getId()){
					continue;
				}
				
				DataPath shortestPath = topoRouteService.getShortestPath(
						src.getValue(), routerAttachmentPoint);
				
				if (shortestPath == null){
					log.debug("Shortest path between {} and {} not found",
							src.getValue(), routerAttachmentPoint);
					return; // just quit here?
				}
				
				/*
				List<FlowEntry> flowEntries = shortestPath.flowEntries();

				for (FlowEntry e : shortestPath.flowEntries()){
					log.debug("fish: {}" , e.dpid().toString());
				}*/
				
				//install flows
				installPath(shortestPath.flowEntries(), dstRouter);
			}
		}
	}
	
	private void installPath(List<FlowEntry> flowEntries, GatewayRouter router){

		//Set up the flow mod
		OFFlowMod fm =
                (OFFlowMod) floodlightProvider.getOFMessageFactory()
                                              .getMessage(OFType.FLOW_MOD);
		
        OFActionOutput action = new OFActionOutput();
        action.setMaxLength((short)0xffff);
        List<OFAction> actions = new ArrayList<OFAction>();
        actions.add(action);
        
        fm.setIdleTimeout((short)0)
        .setHardTimeout((short)0)
        .setBufferId(OFPacketOut.BUFFER_ID_NONE)
        .setCookie(L2_FWD_COOKIE)
        .setCommand(OFFlowMod.OFPFC_ADD)
        //.setMatch(match)
        .setActions(actions)
        .setLengthU(OFFlowMod.MINIMUM_LENGTH+OFActionOutput.MINIMUM_LENGTH);
        
        //Don't push the first flow entry. We need to push entries in the
		//first switch based on IP prefix which we don't know yet.
        for (int i = 1; i < flowEntries.size(); i++){        	
        	FlowEntry flowEntry = flowEntries.get(i);
           
            OFMatch match = new OFMatch();
            match.setDataLayerDestination(router.getRouterMac().toBytes());
            match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_DL_DST);
            ((OFActionOutput) fm.getActions().get(0)).setPort(flowEntry.outPort().value());
            
            fm.setMatch(match);
            
            IOFSwitch sw = floodlightProvider.getSwitches().get(flowEntry.dpid().value());
            
            if (sw == null){
            	log.warn("Switch not found when pushing flow mod");
            	continue;
            }
            
            List<OFMessage> msglist = new ArrayList<OFMessage>();
            msglist.add(fm);
            try {
				sw.write(msglist, null);
				sw.flush();
			} catch (IOException e) {
				log.error("Failure writing flow mod", e);
			}
            
            try {
                fm = fm.clone();
            } catch (CloneNotSupportedException e1) {
                log.error("Failure cloning flow mod", e1);
            }
		}
	}
	
	@Override
	public void startUp(FloodlightModuleContext context) {
		restApi.addRestletRoutable(new BgpRouteWebRoutable());
		topology.addListener(this);
		
		//Retrieve the RIB from BGPd during startup
		retrieveRib();
		
		//Don't have to do this as we'll never have switches connected here
		//calculateFullMesh();
	}

	@Override
	public void topologyChanged() {
		//Probably need to look at all changes, not just port changes
		/*
		boolean change = false;
		String changelog = "";
		
		for (LDUpdate ldu : topology.getLastLinkUpdates()) {
			if (ldu.getOperation().equals(ILinkDiscovery.UpdateOperation.PORT_DOWN)) {
				change = true;
				changelog = changelog + " down ";
			} else if (ldu.getOperation().equals(ILinkDiscovery.UpdateOperation.PORT_UP)) {
				change = true;
				changelog = changelog + " up ";
			}
		}
		log.info ("received topo change" + changelog);

		if (change) {
			//RestClient.get ("http://localhost:5000/topo_change");
		}
		*/
		calculateFullMesh();
	}
}
