package net.onrc.onos.api.flowmanager;

import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;

import java.util.Arrays;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

import net.onrc.onos.api.flowmanager.FlowBatchOperation.Operator;
import net.onrc.onos.core.matchaction.MatchAction;
import net.onrc.onos.core.matchaction.MatchActionIdGenerator;
import net.onrc.onos.core.matchaction.MatchActionOperationEntry;
import net.onrc.onos.core.matchaction.MatchActionOperations;
import net.onrc.onos.core.matchaction.MatchActionOperationsIdGenerator;
import net.onrc.onos.core.matchaction.action.Action;
import net.onrc.onos.core.matchaction.action.OutputAction;
import net.onrc.onos.core.matchaction.match.PacketMatch;
import net.onrc.onos.core.util.PortNumber;
import net.onrc.onos.core.util.SwitchPort;

/**
 * Flow object representing a packet path.
 * <p>
 * TODO: Think this: Do we need a bandwidth constraint?
 */
public class PacketPathFlow extends PathFlow {
    private final PacketMatch match;
    private final int hardTimeout;
    private final int idleTimeout;

    /**
     * Default constructor for Kryo deserialization.
     */
    @Deprecated
    protected PacketPathFlow() {
        match = null;
        hardTimeout = 0;
        idleTimeout = 0;
    }

    /**
     * Constructor.
     *
     * @param id ID for this new Flow object
     * @param match the Match object at the source node of the path
     * @param ingressPort the Ingress port number at the ingress edge node
     * @param path the Path between ingress and egress edge node
     * @param egressActions the list of Action objects at the egress edge node
     * @param hardTimeout the hard-timeout value in seconds, or 0 for no timeout
     * @param idleTimeout the idle-timeout value in seconds, or 0 for no timeout
     */
    public PacketPathFlow(FlowId id,
            PacketMatch match, PortNumber ingressPort, Path path,
            List<Action> egressActions,
            int hardTimeout, int idleTimeout) {
        super(id, ingressPort, path, egressActions);
        this.match = checkNotNull(match);
        this.hardTimeout = hardTimeout;
        this.idleTimeout = idleTimeout;
    }

    /**
     * Gets idle-timeout value.
     *
     * @return Idle-timeout value (seconds)
     */
    public int getIdleTimeout() {
        return idleTimeout;
    }

    /**
     * Gets hard-timeout value.
     *
     * @return Hard-timeout value (seconds)
     */
    public int getHardTimeout() {
        return hardTimeout;
    }

    @Override
    public PacketMatch getMatch() {
        return match;
    }

    @Override
    public List<MatchActionOperations> compile(Operator op,
            MatchActionIdGenerator maIdGenerator,
            MatchActionOperationsIdGenerator maoIdGenerator) {
        switch (op) {
        case ADD:
            return compileAddOperation(maIdGenerator, maoIdGenerator);
        case REMOVE:
            return compileRemoveOperation(maIdGenerator, maoIdGenerator);
        default:
            throw new UnsupportedOperationException("Unknown operation.");
        }
    }

    /**
     * Creates the next {@link MatchAction} object using iterators.
     *
     * @param portIterator the iterator for {@link SwitchPort} objects
     * @param actionsIterator the iterator for the lists of {@link Action}
     * @param maIdGenerator the ID generator of {@link MatchAction}
     * @return {@link MatchAction} object based on the specified iterators
     */
    private MatchAction createNextMatchAction(Iterator<SwitchPort> portIterator,
            Iterator<List<Action>> actionsIterator,
            MatchActionIdGenerator maIdGenerator) {
        if (portIterator == null || actionsIterator == null ||
                !portIterator.hasNext() || !actionsIterator.hasNext()) {
            return null;
        }

        // TODO: Update this after merging the new MatchAction API.
        return new MatchAction(
                maIdGenerator.getNewId(),
                portIterator.next(),
                getMatch(), actionsIterator.next());
    }

    /**
     * Generates the list of {@link MatchActionOperations} objects with
     * add-operation.
     *
     * @return the list of {@link MatchActionOperations} objects
     */
    private List<MatchActionOperations> compileAddOperation(
            MatchActionIdGenerator maIdGenerator,
            MatchActionOperationsIdGenerator maoIdGenerator) {
        Path path = checkNotNull(getPath());
        checkState(path.size() > 0, "Path object has no link.");

        // Preparing each actions and ingress port for each switch
        List<List<Action>> actionsList = new LinkedList<>();
        List<SwitchPort> portList = new LinkedList<>();
        for (FlowLink link : path) {
            portList.add(link.getDstSwitchPort());
            actionsList.add(Arrays.asList(
                    (Action) new OutputAction(link.getSrcPortNumber())));
        }

        // The head switch's ingress port
        portList.add(0, new SwitchPort(path.getSrcDpid(), getIngressPortNumber()));

        // The tail switch's action
        actionsList.add(getEgressActions());

        Iterator<SwitchPort> portIterator = portList.iterator();
        Iterator<List<Action>> actionsIterator = actionsList.iterator();

        // Creates the second phase operation
        // using the head switch's match action
        MatchAction headMatchAction = createNextMatchAction(portIterator,
                actionsIterator, maIdGenerator);
        if (headMatchAction == null) {
            return null;
        }
        MatchActionOperations secondOp = new MatchActionOperations(
                maoIdGenerator.getNewId());
        secondOp.addOperation(new MatchActionOperationEntry(
                MatchActionOperations.Operator.ADD, headMatchAction));

        // Creates the first phase operation
        // using the remaining switches' match actions
        MatchActionOperations firstOp = new MatchActionOperations(
                maoIdGenerator.getNewId());
        MatchAction ma;
        while ((ma = createNextMatchAction(portIterator, actionsIterator, maIdGenerator)) != null) {
            firstOp.addOperation(new MatchActionOperationEntry(
                    MatchActionOperations.Operator.ADD, ma));
        }

        return Arrays.asList(firstOp, secondOp);
    }

    /**
     * Generates the list of {@link MatchActionOperations} objects with
     * remote-operation.
     *
     * @return the list of {@link MatchActionOperations} objects
     */
    private List<MatchActionOperations> compileRemoveOperation(
            MatchActionIdGenerator maIdGenerator,
            MatchActionOperationsIdGenerator maoIdGenerator) {
        // TODO implement it
        throw new UnsupportedOperationException(
                "REMOVE operation is not implemented yet.");
    }
}
