package net.onrc.onos.core.datagrid.web;

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

import net.onrc.onos.core.intent.Intent;
import net.onrc.onos.core.intent.Intent.IntentState;
import net.onrc.onos.core.intent.IntentMap;
import net.onrc.onos.core.intent.PathIntent;
import net.onrc.onos.core.intent.ShortestPathIntent;
import net.onrc.onos.core.intent.runtime.IPathCalcRuntimeService;
import net.onrc.onos.core.topology.LinkEvent;
import net.onrc.onos.core.topology.Path;
import net.onrc.onos.core.util.CallerId;
import net.onrc.onos.core.util.Dpid;
import net.onrc.onos.core.util.FlowEntry;
import net.onrc.onos.core.util.FlowId;
import net.onrc.onos.core.util.FlowPath;
import net.onrc.onos.core.util.FlowPathType;
import net.onrc.onos.core.util.FlowPathUserState;
import net.onrc.onos.core.util.Port;
import net.onrc.onos.core.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.
 * <p/>
 * NOTE: This REST API call is needed for the ONOS GUI.
 * <p/>
 * 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;
    }
}
