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.ArrayList;
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());
            List<Action> l = new ArrayList<Action>();
            l.add(new OutputAction(link.getSrcPortNumber()));
            actionsList.add(l);
            // 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.");
    }
}
