package net.onrc.onos.core.intent.runtime.web;

import java.io.IOException;
import java.util.Collection;

import net.floodlightcontroller.util.MACAddress;
import net.onrc.onos.api.intent.ApplicationIntent;
import net.onrc.onos.api.rest.RestError;
import net.onrc.onos.api.rest.RestErrorCodes;
import net.onrc.onos.core.intent.ConstrainedShortestPathIntent;
import net.onrc.onos.core.intent.Intent;
import net.onrc.onos.core.intent.IntentMap;
import net.onrc.onos.core.intent.IntentOperation;
import net.onrc.onos.core.intent.IntentOperationList;
import net.onrc.onos.core.intent.ShortestPathIntent;
import net.onrc.onos.core.intent.runtime.IPathCalcRuntimeService;
import net.onrc.onos.core.util.Dpid;

import org.codehaus.jackson.map.ObjectMapper;
import org.restlet.data.Status;
import org.restlet.representation.Representation;
import org.restlet.resource.Delete;
import org.restlet.resource.Get;
import org.restlet.resource.Post;
import org.restlet.resource.ServerResource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * A class to access the high-level intents.
 */
public class IntentHighResource extends ServerResource {
    private static final Logger log = LoggerFactory.getLogger(IntentHighResource.class);
    // TODO need to assign proper application id.
    private static final String APPLN_ID = "1";

    /**
     * Gets all high-level intents.
     *
     * @return a Representation for a collection with all of the high-level intents.
     */
    @Get("json")
    public Representation retrieve() throws IOException {
        IPathCalcRuntimeService pathRuntime =
            (IPathCalcRuntimeService) getContext().getAttributes()
                .get(IPathCalcRuntimeService.class.getCanonicalName());

        IntentMap intentMap = pathRuntime.getHighLevelIntents();
        Collection<Intent> intents = intentMap.getAllIntents();

        return toRepresentation(intents, null);
    }

    /**
     * Adds a collection of high-level intents.
     *
     * @param jsonIntent JSON representation of the intents to add.
     * @return a Representation of a collection containing the intents that were
     *         created.
     */
    @Post("json")
    public Representation store(String jsonIntent) {
        IPathCalcRuntimeService pathRuntime =
            (IPathCalcRuntimeService) getContext().getAttributes()
                .get(IPathCalcRuntimeService.class.getCanonicalName());
        if (pathRuntime == null) {
            log.warn("Failed to get path calc runtime");
            return null;
        }

        ObjectMapper mapper = new ObjectMapper();
        ApplicationIntent[] addOperations = null;
        try {
            if (jsonIntent != null) {
                addOperations = mapper.readValue(jsonIntent, ApplicationIntent[].class);
            }
        } catch (IOException ex) {
            log.error("Exception occurred parsing inbound JSON", ex);
        }

        if (addOperations == null) {
            setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
            final RestError error =
                    RestError.createRestError(RestErrorCodes.RestErrorCode.INTENT_INVALID);
            return toRepresentation(error, null);
        }

        //
        // Process all intents one-by-one
        //
        // TODO: The Intent Type should be enum instead of a string,
        // and we should use a switch statement below to process the
        // different type of intents.
        //
        IntentOperationList intentOperations = new IntentOperationList();
        for (ApplicationIntent oper : addOperations) {
            String applnIntentId = APPLN_ID + ":" + oper.intentId();

            IntentOperation.Operator operator = IntentOperation.Operator.ADD;
            Dpid srcSwitchDpid = new Dpid(oper.srcSwitchDpid());
            Dpid dstSwitchDpid = new Dpid(oper.dstSwitchDpid());

            if (oper.intentType().equals("SHORTEST_PATH")) {
                //
                // Process Shortest-Path Intent
                //
                ShortestPathIntent spi =
                    new ShortestPathIntent(applnIntentId,
                                           srcSwitchDpid.value(),
                                           oper.srcSwitchPort(),
                                           MACAddress.valueOf(oper.matchSrcMac()).toLong(),
                                           dstSwitchDpid.value(),
                                           oper.dstSwitchPort(),
                                           MACAddress.valueOf(oper.matchDstMac()).toLong());
                spi.setPathFrozen(oper.isStaticPath());
                intentOperations.add(operator, spi);
            } else {
                //
                // Process Constrained Shortest-Path Intent
                //
                ConstrainedShortestPathIntent cspi =
                    new ConstrainedShortestPathIntent(applnIntentId,
                                                      srcSwitchDpid.value(),
                                                      oper.srcSwitchPort(),
                                                      MACAddress.valueOf(oper.matchSrcMac()).toLong(),
                                                      dstSwitchDpid.value(),
                                                      oper.dstSwitchPort(),
                                                      MACAddress.valueOf(oper.matchDstMac()).toLong(),
                                                      oper.bandwidth());
                cspi.setPathFrozen(oper.isStaticPath());
                intentOperations.add(operator, cspi);
            }
        }
        // Apply the Intent Operations
        pathRuntime.executeIntentOperations(intentOperations);

        setStatus(Status.SUCCESS_CREATED);

        return toRepresentation(intentOperations, null);
    }

    /**
     * Deletes all high-level intents.
     *
     * @return a null Representation.
     */
    @Delete("json")
    public Representation remove() {
        IPathCalcRuntimeService pathRuntime =
            (IPathCalcRuntimeService) getContext().getAttributes()
                .get(IPathCalcRuntimeService.class.getCanonicalName());

        // Delete all intents
        // TODO: The implementation below is broken - waiting for the Java API
        // TODO: The deletion should use synchronous Java API?
        pathRuntime.purgeIntents();
        setStatus(Status.SUCCESS_NO_CONTENT);
        return null;      // TODO no reply yet from the purge intents call
    }
}
