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.MatchActionId;
import net.onrc.onos.core.matchaction.MatchActionOperationEntry;
import net.onrc.onos.core.matchaction.MatchActionOperations;
import net.onrc.onos.core.matchaction.MatchActionOperationsId;
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.IdGenerator;
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,
            IdGenerator<MatchActionId> maIdGenerator,
            IdGenerator<MatchActionOperationsId> 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,
            IdGenerator<MatchActionId> 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(
            IdGenerator<MatchActionId> maIdGenerator,
            IdGenerator<MatchActionOperationsId> 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(
            IdGenerator<MatchActionId> maIdGenerator,
            IdGenerator<MatchActionOperationsId> maoIdGenerator) {
        // TODO implement it
        throw new UnsupportedOperationException(
                "REMOVE operation is not implemented yet.");
    }
}
