package net.floodlightcontroller.routing;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import net.floodlightcontroller.core.internal.SwitchStorageImpl;
import net.floodlightcontroller.core.INetMapTopologyService.ITopoRouteService;
import net.floodlightcontroller.topology.NodePortTuple;

import org.openflow.util.HexString;

import com.thinkaurelius.titan.core.TitanFactory;
import com.thinkaurelius.titan.core.TitanGraph;
// import com.tinkerpop.blueprints.Direction;
import com.tinkerpop.blueprints.Vertex;
// import com.tinkerpop.gremlin.groovy.Gremlin;
// import com.tinkerpop.gremlin.java.GremlinPipeline;
// import com.tinkerpop.pipes.Pipe;
// import com.tinkerpop.pipes.PipeFunction;
// import com.tinkerpop.pipes.branch.LoopPipe;
// import com.tinkerpop.pipes.branch.LoopPipe.LoopBundle;
// import com.tinkerpop.pipes.filter.FilterPipe.Filter;
// import com.tinkerpop.pipes.util.PipesFluentPipeline;

import com.tinkerpop.blueprints.Element;

import javax.script.ScriptContext;
import javax.script.ScriptEngine;
import javax.script.ScriptException;
import com.tinkerpop.gremlin.groovy.jsr223.GremlinGroovyScriptEngine;

public class TopoRouteService implements ITopoRouteService {

	ThreadLocal<SwitchStorageImpl> store = new ThreadLocal<SwitchStorageImpl>() {
	    @Override
	    protected SwitchStorageImpl initialValue() {
		SwitchStorageImpl swStore = new SwitchStorageImpl();
		// NOTE: This is the file path from global properties
		swStore.init("/tmp/cassandra.titan");
		return swStore;
	    }
	};

	SwitchStorageImpl swStore = store.get();

	@Override
	public List<NodePortTuple> GetShortestPath(NodePortTuple src,
			NodePortTuple dest) {
	    List<NodePortTuple> result_list = new ArrayList<NodePortTuple>();

	    TitanGraph titanGraph = swStore.graph;

	    String dpid_src = HexString.toHexString(src.getNodeId());
	    String dpid_dest = HexString.toHexString(dest.getNodeId());

	    //
	    // Implement the Shortest Path between two vertices by using
	    // the following Gremlin code:
	    //   results = []; v_src.as('x').out.out.in.has("type", "switch").dedup().loop('x'){it.object.dpid != v_dest.dpid & it.loops < 10}.path().fill(results)
	    //

	    String gremlin = "v_src.as(\"x\").out.out.in.has(\"type\", \"switch\").dedup().loop(\"x\"){it.object.dpid != v_dest.dpid & it.loops < 10}.path().fill(results)";

	    // Get the source vertex
	    Iterator<Vertex> iter = titanGraph.getVertices("dpid", dpid_src).iterator();
	    if (! iter.hasNext())
		return null;		// Source vertex not found
	    Vertex v_src = iter.next();

	    // Get the destination vertex
	    iter = titanGraph.getVertices("dpid", dpid_dest).iterator();
	    if (! iter.hasNext())
		return null;		// Destination vertex not found
	    Vertex v_dest = iter.next();
	
	    //
	    // Implement the Gremlin script and run it
	    //
	    ScriptEngine engine = new GremlinGroovyScriptEngine();

	    ArrayList<ArrayList<Vertex>> results = new ArrayList<ArrayList<Vertex>>();
	    engine.getBindings(ScriptContext.ENGINE_SCOPE).put("g", titanGraph);
	    engine.getBindings(ScriptContext.ENGINE_SCOPE).put("v_src", v_src);
	    engine.getBindings(ScriptContext.ENGINE_SCOPE).put("v_dest", v_dest);
	    engine.getBindings(ScriptContext.ENGINE_SCOPE).put("results", results);

	    try {
		engine.eval(gremlin);
	    } catch (ScriptException e) {
		System.err.println("Caught ScriptException running Gremlin script: " + e.getMessage());
		return null;
	    }

	    //
	    // Loop through the result and return the list
	    // of <dpid, port> tuples.
	    //
	    long nodeId = 0;
	    short portId = 0;
	    for (ArrayList<Vertex> lv : results) {
		int idx = 0;
		for (Vertex v: lv) {
		    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);
		    }
		    if (idx == 0) {
			idx++;
			continue;
		    }
		    int mod = (idx - 1) % 3;
		    if ((mod == 0) || (mod == 2))  {
			result_list.add(new NodePortTuple(nodeId, portId));
		    }
		    idx++;
		}
	    }
	    if (result_list.size() > 0)
		return result_list;

	    return null;
	}

	@Override
	public Boolean RouteExists(NodePortTuple src, NodePortTuple dest) {
		List<NodePortTuple> route = GetShortestPath(src, dest);
		if (route != null)
		    return true;
		return false;
	}
}
