package net.onrc.onos.flow;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.Set;

import org.openflow.util.HexString;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.tinkerpop.blueprints.Direction;
import com.tinkerpop.blueprints.Vertex;

import net.floodlightcontroller.core.INetMapTopologyObjects.IFlowEntry;
import net.floodlightcontroller.core.INetMapTopologyObjects.IFlowPath;
import net.floodlightcontroller.core.INetMapTopologyObjects.IPortObject;
import net.floodlightcontroller.core.ISwitchStorage.SwitchState;
import net.floodlightcontroller.core.IOFSwitch;
import net.floodlightcontroller.util.DataPath;
import net.floodlightcontroller.util.Dpid;
import net.floodlightcontroller.util.FlowEntry;
import net.floodlightcontroller.util.FlowEntryAction;
import net.floodlightcontroller.util.FlowEntryMatch;
import net.floodlightcontroller.util.FlowPath;
import net.floodlightcontroller.util.Port;
import net.floodlightcontroller.util.SwitchPort;
import net.onrc.onos.util.GraphDBConnection;
import net.onrc.onos.util.GraphDBOperation;
import net.onrc.onos.util.LocalTopologyEventListener;
import net.onrc.onos.util.GraphDBConnection.Transaction;

public class FlowManagerImpl implements IFlowManager {
	
	protected static Logger log = LoggerFactory.getLogger(LocalTopologyEventListener.class);
	protected GraphDBOperation op;

	@Override
	public void createFlow(IPortObject src_port, IPortObject dest_port) {
		// TODO Auto-generated method stub

	}

	@Override
	public Iterable<FlowPath> getFlows(IPortObject src_port,
			IPortObject dest_port) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public Iterable<FlowPath> getOutFlows(IPortObject port) {
		// TODO Auto-generated method stub
		List<FlowPath> flowPaths = new ArrayList<FlowPath> ();
		Iterable<IFlowEntry> flowEntries = port.getOutFlowEntries();

		for(IFlowEntry fe: flowEntries) {
			IFlowPath flow = fe.getFlow();
			FlowPath flowPath = new FlowPath(flow);
			flowPaths.add(flowPath);
		}
		return flowPaths;
	}

	@Override
	public void reconcileFlows(IPortObject src_port) {
		// TODO Auto-generated method stub

		log.debug("Reconcile Flows for Port removed: {}:{}",src_port.getSwitch().getDPID(),src_port.getNumber());
		Iterable<IFlowEntry> flowEntries = src_port.getOutFlowEntries();

		for(IFlowEntry fe: flowEntries) {
			IFlowPath flow = fe.getFlow();
			reconcileFlow(flow);
		}
	}

	private void reconcileFlow(IFlowPath flow) {
		// TODO Auto-generated method stub
		String src_dpid = flow.getSrcSwitch();
		String dst_dpid = flow.getDstSwitch();
		Short src_port = flow.getSrcPort();
		Short dst_port = flow.getDstPort();
		IPortObject src = null;
		IPortObject dst = null;
		src = op.searchPort(src_dpid, src_port);
		dst = op.searchPort(dst_dpid, dst_port);
		if (src != null && dst != null) {
			FlowPath newFlow = this.computeFlowPath(src,dst);
			installFlow(newFlow);
			removeFlow(flow);
		}
		
	}

	private void removeFlow(IFlowPath flow) {
		// TODO Auto-generated method stub
		
	}

	private void installFlow(FlowPath newFlow) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void reconcileFlow(IPortObject src_port, IPortObject dest_port) {
		// TODO Auto-generated method stub

	}

	@Override
	public FlowPath computeFlowPath(IPortObject src_port, IPortObject dest_port) {
		// TODO Auto-generated method stub
		DataPath dataPath = new DataPath(); 
		
		// FIXME: Bad idea to use FloodLight data structures (SwitchPort)
		
		dataPath.setSrcPort(new SwitchPort(new Dpid(src_port.getSwitch().getDPID()),
						new Port(src_port.getNumber())));
		dataPath.setDstPort(new SwitchPort(new Dpid(src_port.getSwitch().getDPID()),
				new Port(src_port.getNumber())));
		
		if (src_port.getSwitch().equals(dest_port.getSwitch())) {
			// on same switch create quick path
			FlowEntry flowEntry = new FlowEntry();
		    flowEntry.setDpid(new Dpid(src_port.getSwitch().getDPID()));
		    flowEntry.setInPort(new Port(src_port.getNumber()));
		    flowEntry.setOutPort(new Port(src_port.getNumber()));
		    flowEntry.setFlowEntryMatch(new FlowEntryMatch());
		    flowEntry.flowEntryMatch().enableInPort(flowEntry.inPort());
		    
		    // Set the outgoing port output action
		    ArrayList<FlowEntryAction> flowEntryActions = flowEntry.flowEntryActions();
		    if (flowEntryActions == null) {
			flowEntryActions = new ArrayList<FlowEntryAction>();
			flowEntry.setFlowEntryActions(flowEntryActions);
		    }
		    FlowEntryAction flowEntryAction = new FlowEntryAction();
		    flowEntryAction.setActionOutput(flowEntry.outPort());
		    flowEntryActions.add(flowEntryAction);
		    dataPath.flowEntries().add(flowEntry);
		    
		    FlowPath flowPath = new FlowPath();
			flowPath.setDataPath(dataPath);

			return flowPath;
		}
		Vertex v_src = src_port.getSwitch().asVertex();	
		Vertex v_dest = dest_port.getSwitch().asVertex();

		//
		// Implement the Shortest Path computation by using Breath First Search
		//
		Set<Vertex> visitedSet = new HashSet<Vertex>();
		Queue<Vertex> processingList = new LinkedList<Vertex>();
		Map<Vertex, Vertex> previousVertexMap = new HashMap<Vertex, Vertex>();

		processingList.add(v_src);
		visitedSet.add(v_src);
		Boolean path_found = false;
		while (! processingList.isEmpty()) {
		    Vertex nextVertex = processingList.poll();
		    if (v_dest.equals(nextVertex)) {
			path_found = true;
			break;
		    }
		    for (Vertex parentPort : nextVertex.getVertices(Direction.OUT, "on")) {
			for (Vertex childPort : parentPort.getVertices(Direction.OUT, "link")) {
			    for (Vertex child : childPort.getVertices(Direction.IN, "on")) {
				// Ignore inactive switches
				String state = child.getProperty("state").toString();
				if (! state.equals(SwitchState.ACTIVE.toString()))
				    continue;

				if (! visitedSet.contains(child)) {
				    previousVertexMap.put(parentPort, nextVertex);
				    previousVertexMap.put(childPort, parentPort);
				    previousVertexMap.put(child, childPort);
				    visitedSet.add(child);
				    processingList.add(child);
				}
			    }
			}
		    }
		}
		if (! path_found) {
		    return null;		// No path found
		}

		List<Vertex> resultPath = new LinkedList<Vertex>();
		Vertex previousVertex = v_dest;
		resultPath.add(v_dest);
		while (! v_src.equals(previousVertex)) {
		    Vertex currentVertex = previousVertexMap.get(previousVertex);
		    resultPath.add(currentVertex);
		    previousVertex = currentVertex;
		}
		Collections.reverse(resultPath);
		
		// Loop through the result and prepare the return result
		// as a list of Flow Entries.
		//
		long nodeId = 0;
		short portId = 0;
		Port inPort = new Port(src_port.getNumber());
		Port outPort = new Port();
		int idx = 0;
		for (Vertex v: resultPath) {
		    String type = v.getProperty("type").toString();
		    // System.out.println("type: " + type);
		    if (type.equals("port")) {
			String number = v.getProperty("number").toString();
			// System.out.println("number: " + number);

			Object obj = v.getProperty("number");
			// String class_str = obj.getClass().toString();
			if (obj instanceof Short) {
			    portId = (Short)obj;
			} else if (obj instanceof Integer) {
			    Integer int_nodeId = (Integer)obj;
			    portId = int_nodeId.shortValue();
			    // int int_nodeId = (Integer)obj;
			    // portId = (short)int_nodeId.;
			}
		    } else if (type.equals("switch")) {
			String dpid = v.getProperty("dpid").toString();
			nodeId = HexString.toLong(dpid);

			// System.out.println("dpid: " + dpid);
		    }
		    idx++;
		    if (idx == 1) {
			continue;
		    }
		    int mod = idx % 3;
		    if (mod == 0) {
			// Setup the incoming port
			inPort = new Port(portId);
			continue;
		    }
		    if (mod == 2) {
			// Setup the outgoing port, and add the Flow Entry
			outPort = new Port(portId);

			FlowEntry flowEntry = new FlowEntry();
			flowEntry.setDpid(new Dpid(nodeId));
			flowEntry.setInPort(inPort);
			flowEntry.setOutPort(outPort);
			flowEntry.setFlowEntryMatch(new FlowEntryMatch());
		    flowEntry.flowEntryMatch().enableInPort(flowEntry.inPort());
		    
		    // Set the outgoing port output action
		    ArrayList<FlowEntryAction> flowEntryActions = flowEntry.flowEntryActions();
		    if (flowEntryActions == null) {
			flowEntryActions = new ArrayList<FlowEntryAction>();
			flowEntry.setFlowEntryActions(flowEntryActions);
		    }
		    FlowEntryAction flowEntryAction = new FlowEntryAction();
		    flowEntryAction.setActionOutput(flowEntry.outPort());
		    flowEntryActions.add(flowEntryAction);
		    dataPath.flowEntries().add(flowEntry);
			continue;
		    }
		}
		if (idx > 0) {
		    // Add the last Flow Entry
		    FlowEntry flowEntry = new FlowEntry();
		    flowEntry.setDpid(new Dpid(nodeId));
		    flowEntry.setInPort(inPort);
		    flowEntry.setOutPort(new Port(dest_port.getNumber()));
		    flowEntry.setFlowEntryMatch(new FlowEntryMatch());
		    flowEntry.flowEntryMatch().enableInPort(flowEntry.inPort());
		    
		    // Set the outgoing port output action
		    ArrayList<FlowEntryAction> flowEntryActions = flowEntry.flowEntryActions();
		    if (flowEntryActions == null) {
			flowEntryActions = new ArrayList<FlowEntryAction>();
			flowEntry.setFlowEntryActions(flowEntryActions);
		    }
		    FlowEntryAction flowEntryAction = new FlowEntryAction();
		    flowEntryAction.setActionOutput(flowEntry.outPort());
		    flowEntryActions.add(flowEntryAction);
		    dataPath.flowEntries().add(flowEntry);
		    dataPath.flowEntries().add(flowEntry);
		}

	
		if (dataPath.flowEntries().size() > 0) {
		    FlowPath flowPath = new FlowPath();
			flowPath.setDataPath(dataPath);

			return flowPath;
		}
		return null;		
		
	}

	@Override
	public Iterable<FlowEntry> getFlowEntries(FlowPath flow) {
		// TODO Auto-generated method stub
		return null;
	}


	@Override
	public boolean installRemoteFlowEntry(FlowPath flowPath,
					      FlowEntry entry) {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public boolean removeRemoteFlowEntry(FlowPath flowPath,
					     FlowEntry entry) {
		return false;
		// TODO Auto-generated method stub

	}

	@Override
	public boolean installFlowEntry(IOFSwitch mySwitch,
					FlowPath flowPath,
					FlowEntry flowEntry) {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public boolean removeFlowEntry(IOFSwitch mySwitch,
				       FlowPath flowPath,
				       FlowEntry flowEntry) {
		// TODO Auto-generated method stub
		return false;
	}
	

}
