package net.onrc.onos.datagrid.web;

import java.util.ArrayList;
import java.util.Collection;
import java.util.SortedMap;
import java.util.TreeMap;

import net.onrc.onos.intent.Intent;
import net.onrc.onos.intent.PathIntent;
import net.onrc.onos.intent.ShortestPathIntent;
import net.onrc.onos.intent.Intent.IntentState;
import net.onrc.onos.intent.IntentMap;
import net.onrc.onos.intent.runtime.IPathCalcRuntimeService;

import net.onrc.onos.ofcontroller.networkgraph.LinkEvent;
import net.onrc.onos.ofcontroller.networkgraph.Path;
import net.onrc.onos.ofcontroller.util.CallerId;
import net.onrc.onos.ofcontroller.util.Dpid;
import net.onrc.onos.ofcontroller.util.FlowEntry;
import net.onrc.onos.ofcontroller.util.FlowId;
import net.onrc.onos.ofcontroller.util.FlowPath;
import net.onrc.onos.ofcontroller.util.FlowPathType;
import net.onrc.onos.ofcontroller.util.FlowPathUserState;
import net.onrc.onos.ofcontroller.util.Port;
import net.onrc.onos.ofcontroller.util.SwitchPort;

import org.restlet.resource.Get;
import org.restlet.resource.ServerResource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * REST API call to get a summary of Flow Paths.
 *
 * NOTE: This REST API call is needed for the ONOS GUI.
 *
 *    GET /wm/onos/datagrid/get/ng-flows/summary/json
 */
public class GetNGFlowsSummaryResource extends ServerResource {
    public static final Logger log = LoggerFactory.getLogger(GetNGFlowsSummaryResource.class);
	
    @Get("json")
    public ArrayList<FlowPath> retrieve() {
	ArrayList<FlowPath> result = new ArrayList<>();
	SortedMap<Long, FlowPath> sortedFlowPaths = new TreeMap<>();

        IPathCalcRuntimeService pathRuntime =
	    (IPathCalcRuntimeService)getContext().
	    getAttributes().get(IPathCalcRuntimeService.class.getCanonicalName());
	log.debug("Get NG Flows Summary");


	IntentMap parentIntentMap = pathRuntime.getHighLevelIntents();
	IntentMap intentMap = pathRuntime.getPathIntents();
	for (Intent parentIntent : parentIntentMap.getAllIntents()) {
	    // Get only installed Shortest Paths
	    if (parentIntent.getState() != IntentState.INST_ACK)
		continue;
	    if (! (parentIntent instanceof ShortestPathIntent))
		continue;
	    ShortestPathIntent spIntent = (ShortestPathIntent)parentIntent;

	    // Get the Path Intent
	    Intent intent = intentMap.getIntent(spIntent.getPathIntentId());
	    if (! (intent instanceof PathIntent))
		continue;
	    PathIntent pathIntent = (PathIntent)intent;

	    // Decode the Shortest Path ID
	    String applnIntentId = parentIntent.getId();
	    String intentId = applnIntentId.split(":")[1];

	    // Create the Flow Path
	    FlowId flowId = new FlowId(intentId);
	    FlowPath flowPath = new FlowPath();
	    flowPath.setFlowId(flowId);
	    sortedFlowPaths.put(flowPath.flowId().value(), flowPath);

	    flowPath.setInstallerId(new CallerId("E"));
	    flowPath.setFlowEntryActions(null);
	    flowPath.setFlowPathType(FlowPathType.FP_TYPE_SHORTEST_PATH);
	    flowPath.setFlowPathUserState(FlowPathUserState.FP_USER_ADD);

	    // Setup the Source and Destination DPID and Port
	    SwitchPort srcPort = flowPath.dataPath().srcPort();
	    SwitchPort dstPort = flowPath.dataPath().dstPort();
	    srcPort.setDpid(new Dpid(spIntent.getSrcSwitchDpid()));
	    srcPort.setPort(new Port((short)spIntent.getSrcPortNumber()));
	    dstPort.setDpid(new Dpid(spIntent.getDstSwitchDpid()));
	    dstPort.setPort(new Port((short)spIntent.getDstPortNumber()));

	    // Extract the Flow Entries
	    Path path = pathIntent.getPath();
	    FlowEntry flowEntry;
	    ArrayList<FlowEntry> flowEntries = new ArrayList<>();
	    for (LinkEvent linkEvent : path) {
		Dpid dpid = new Dpid(linkEvent.getSrc().getDpid());
		flowEntry = new FlowEntry();
		flowEntry.setDpid(dpid);
		flowEntries.add(flowEntry);
	    }
	    // Add the final Flow Entry
	    flowEntry = new FlowEntry();
	    flowEntry.setDpid(new Dpid(spIntent.getDstSwitchDpid()));
	    flowEntries.add(flowEntry);
	    flowPath.dataPath().setFlowEntries(flowEntries);
	}

	// Prepare the return result
	for (FlowPath flowPath : sortedFlowPaths.values())
	    result.add(flowPath);

	return result;
    }
}

@@ -2591,16 +2591,98 @@
 %22:%22)%5B1%5D;
+%0A%09    // A hack for Flow IDs that are not routable%0A%09    intentId.replace(%22F%22, %22%22);
 %0A%0A%09    /

Add a hack to remove 'F' from the Flow ID when the Flows are not routable.