/*
 * Copyright 2016-present Open Networking Laboratory
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.onosproject.net.intent.impl.compiler;

import com.google.common.collect.Maps;
import com.google.common.collect.SetMultimap;
import com.google.common.collect.Sets;
import org.onlab.packet.EthType;
import org.onlab.packet.Ethernet;
import org.onlab.packet.Ip4Address;
import org.onlab.packet.IpPrefix;
import org.onlab.packet.MplsLabel;
import org.onlab.packet.VlanId;
import org.onlab.util.Identifier;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DeviceId;
import org.onosproject.net.EncapsulationType;
import org.onosproject.net.Link;
import org.onosproject.net.PortNumber;
import org.onosproject.net.FilteredConnectPoint;
import org.onosproject.net.flow.DefaultTrafficSelector;
import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.flow.criteria.Criteria;
import org.onosproject.net.flow.criteria.Criterion;
import org.onosproject.net.flow.criteria.EthTypeCriterion;
import org.onosproject.net.flow.criteria.MplsCriterion;
import org.onosproject.net.flow.criteria.TunnelIdCriterion;
import org.onosproject.net.flow.criteria.VlanIdCriterion;
import org.onosproject.net.flow.instructions.Instruction;
import org.onosproject.net.flow.instructions.L0ModificationInstruction;
import org.onosproject.net.flow.instructions.L1ModificationInstruction;
import org.onosproject.net.flow.instructions.L2ModificationInstruction;
import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModEtherInstruction;
import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModVlanIdInstruction;
import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModVlanPcpInstruction;
import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModMplsLabelInstruction;
import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModMplsBosInstruction;
import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModTunnelIdInstruction;
import org.onosproject.net.flow.instructions.L3ModificationInstruction;
import org.onosproject.net.flow.instructions.L3ModificationInstruction.ModIPInstruction;
import org.onosproject.net.flow.instructions.L3ModificationInstruction.ModIPv6FlowLabelInstruction;
import org.onosproject.net.flow.instructions.L3ModificationInstruction.ModArpIPInstruction;
import org.onosproject.net.flow.instructions.L3ModificationInstruction.ModArpEthInstruction;
import org.onosproject.net.flow.instructions.L3ModificationInstruction.ModArpOpInstruction;
import org.onosproject.net.flow.instructions.L4ModificationInstruction;
import org.onosproject.net.flow.instructions.L4ModificationInstruction.ModTransportPortInstruction;
import org.onosproject.net.intent.IntentCompilationException;
import org.onosproject.net.intent.LinkCollectionIntent;
import org.onosproject.net.intent.constraint.EncapsulationConstraint;
import org.onosproject.net.resource.impl.LabelAllocator;

import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;

import static org.onosproject.net.flow.criteria.Criterion.Type.MPLS_LABEL;
import static org.onosproject.net.flow.criteria.Criterion.Type.TUNNEL_ID;
import static org.onosproject.net.flow.criteria.Criterion.Type.VLAN_VID;

/**
 * Shared APIs and implementations for Link Collection compilers.
 */
public class LinkCollectionCompiler<T> {

    /**
     * Reference to the label allocator.
     */
    static LabelAllocator labelAllocator;

    /**
     * The allowed tag criterions.
     */
    private static final Set<Criterion.Type> TAG_CRITERION_TYPES =
            Sets.immutableEnumSet(VLAN_VID, MPLS_LABEL, TUNNEL_ID);

    /**
     * Error message for wrong egress scenario.
     */
    private static final String WRONG_EGRESS = "Egress points not equal to 1 " +
            "and apply treatment at ingress, " +
            "which treatments should I apply ???";

    /**
     * Error message for wrong ingress scenario.
     */
    private static final String WRONG_INGRESS = "Ingress points not equal to 1 " +
            "and apply treatment at egress, " +
            "how can I match in the core ???";

    /**
     * Error message for wrong encapsulation scenario.
     */
    private static final String WRONG_ENCAPSULATION = "Wrong scenario - 1 hop with " +
            "encapsualtion";

    /**
     * Error message for unavailable labels.
     */
    private static final String NO_LABELS = "No available label for %s";

    /**
     * Error message for wrong encapsulation.
     */
    private static final String UNKNOWN_ENCAPSULATION = "Unknown encapsulation type";

    /**
     * Error message for unsupported L0 instructions.
     */
    private static final String UNSUPPORTED_L0 = "L0 not supported";

    /**
     * Error message for unsupported L1 instructions.
     */
    private static final String UNSUPPORTED_L1 = "L1 not supported";

    /**
     * Error message for unsupported eth subtype.
     */
    private static final String UNSUPPORTED_ETH_SUBTYPE = "Bad eth subtype";

    /**
     * Error message for unsupported pop action.
     */
    private static final String UNSUPPORTED_POP_ACTION = "Can't handle pop label";

    /**
     * Error message for unsupported L2 instructions.
     */
    private static final String UNSUPPORTED_L2 = "Unknown L2 Modification instruction";

    /**
     * Error message for unsupported IP subtype.
     */
    private static final String UNSUPPORTED_IP_SUBTYPE = "Bad ip subtype";

    /**
     * Error message for unsupported ARP.
     */
    private static final String UNSUPPORTED_ARP = "IPv6 not supported for ARP";

    /**
     * Error message for unsupported L3 instructions.
     */
    private static final String UNSUPPORTED_L3 = "Unknown L3 Modification instruction";

    /**
     * Error message for unsupported L4 subtype.
     */
    private static final String UNSUPPORTED_L4_SUBTYPE = "Unknown L4 subtype";

    /**
     * Error message for unsupported L4 instructions.
     */
    private static final String UNSUPPORTED_L4 = "Unknown L4 Modification instruction";

    /**
     * Error message for unsupported instructions.
     */
    private static final String UNSUPPORTED_INSTRUCTION = "Unknown instruction type";

    /**
     * Creates the flows representations. This default implementation does
     * nothing. Subclasses should override this method to create their
     * specific flows representations (flow rule, flow objective).
     *
     * @param intent the intent to compile
     * @param deviceId the affected device
     * @param inPorts the input ports
     * @param outPorts the output ports
     * @param labels the labels for the label switching hop by hop
     * @return the list of flows representations
     */
    protected List<T> createRules(LinkCollectionIntent intent,
                                  DeviceId deviceId,
                                  Set<PortNumber> inPorts,
                                  Set<PortNumber> outPorts,
                                  Map<ConnectPoint, Identifier<?>> labels) {
        return null;
    }

    /**
     * Helper method to handle the different scenario (not encap, single hop, encap).
     *
     * @param encapConstraint the encapsulation constraint if it is present
     * @param intent the link collection intent
     * @param inPort the in port
     * @param outPorts the out ports
     * @param deviceId the current device
     * @param labels the labels used by the encapsulation
     * @return the forwarding instruction
     */
    protected ForwardingInstructions createForwardingInstruction(Optional<EncapsulationConstraint> encapConstraint,
                                                                 LinkCollectionIntent intent,
                                                                 PortNumber inPort,
                                                                 Set<PortNumber> outPorts,
                                                                 DeviceId deviceId,
                                                                 Map<ConnectPoint, Identifier<?>> labels) {
        ForwardingInstructions instructions = null;
        /*
         * If not encapsulation or single hop.
         */
        if (!encapConstraint.isPresent() || intent.links().isEmpty()) {
            instructions = this.createForwardingInstructions(
                    intent,
                    inPort,
                    deviceId,
                    outPorts
            );
        /*
         * If encapsulation is present. We retrieve the labels
         * for this iteration;
         */
        } else {
            Identifier<?> inLabel = labels.get(new ConnectPoint(deviceId, inPort));
            Map<ConnectPoint, Identifier<?>> outLabels = Maps.newHashMap();
            outPorts.forEach(outPort -> {
                ConnectPoint key = new ConnectPoint(deviceId, outPort);
                outLabels.put(key, labels.get(key));
            });
            instructions = this.createForwardingInstructions(
                    intent,
                    inPort,
                    inLabel,
                    deviceId,
                    outPorts,
                    outLabels,
                    encapConstraint.get().encapType()
            );
        }
        return instructions;
    }

    /**
     * Manages the Intents with a single ingress point (p2p, sp2mp)
     * creating properly the selector builder and the treatment builder.
     *
     * @param selectorBuilder the selector builder to update
     * @param treatmentBuilder the treatment builder to update
     * @param intent the intent to compile
     * @param deviceId the current device
     * @param outPorts the output ports of this device
     */
    private void manageSpIntent(TrafficSelector.Builder selectorBuilder,
                                TrafficTreatment.Builder treatmentBuilder,
                                LinkCollectionIntent intent,
                                DeviceId deviceId,
                                Set<PortNumber> outPorts) {
        /*
         * Sanity check.
         */
        if (intent.filteredIngressPoints().size() != 1) {
            throw new IntentCompilationException(WRONG_INGRESS);
        }
        /*
         * For the p2p and sp2mp the transition initial state
         * to final state is performed at the egress.
         */
        Optional<FilteredConnectPoint> filteredIngressPoint =
                intent.filteredIngressPoints().stream().findFirst();
        /*
         * We build the final selector, adding the selector
         * of the FIP to the Intent selector and potentially
         * overriding its matches.
         */
        filteredIngressPoint.get()
                .trafficSelector()
                .criteria()
                .forEach(selectorBuilder::add);
        /*
         * In this scenario, potentially we can have several output
         * ports.
         */
        for (PortNumber outPort : outPorts) {
            Optional<FilteredConnectPoint> filteredEgressPoint =
                    getFilteredConnectPointFromIntent(deviceId, outPort, intent);
            /*
             * If we are at the egress, we have to transit to the final
             * state.
             */
            if (filteredEgressPoint.isPresent()) {
                /*
                 * We add the Intent treatment.
                 */
                intent.treatment().allInstructions().stream()
                        .filter(inst -> inst.type() != Instruction.Type.NOACTION)
                        .forEach(treatmentBuilder::add);
                /*
                 * We generate the transition FIP->FEP.
                 */
                TrafficTreatment forwardingTreatment =
                        forwardingTreatment(filteredIngressPoint.get().trafficSelector(),
                                            filteredEgressPoint.get().trafficSelector(),
                                            getEthType(intent.selector()));
                /*
                 * We add the instruction necessary to the transition.
                 * Potentially we override the intent treatment.
                 */
                forwardingTreatment.allInstructions().stream()
                        .filter(inst -> inst.type() != Instruction.Type.NOACTION)
                        .forEach(treatmentBuilder::add);
            }
            /*
             * Finally we set the output action.
             */
            treatmentBuilder.setOutput(outPort);
        }
    }

    /**
     * Manages the Intents with multiple ingress points creating properly
     * the selector builder and the treatment builder.
     *
     * @param selectorBuilder the selector builder to update
     * @param treatmentBuilder the treatment builder to update
     * @param intent the intent to compile
     * @param inPort the input port of the current device
     * @param deviceId the current device
     * @param outPorts the output ports of this device
     */
    private void manageMpIntent(TrafficSelector.Builder selectorBuilder,
                                TrafficTreatment.Builder treatmentBuilder,
                                LinkCollectionIntent intent,
                                PortNumber inPort,
                                DeviceId deviceId,
                                Set<PortNumber> outPorts) {
        /*
         * Sanity check
         */
        if (intent.filteredEgressPoints().size() != 1) {
            throw new IntentCompilationException(WRONG_EGRESS);
        }
        /*
         * We try to understand if the device is one of the ingress points.
         */
        Optional<FilteredConnectPoint> filteredIngressPoint =
                getFilteredConnectPointFromIntent(deviceId, inPort, intent);
        /*
         * We retrieve from the Intent the unique egress points.
         */
        Optional<FilteredConnectPoint> filteredEgressPoint =
                intent.filteredEgressPoints().stream().findFirst();
        /*
         * We check if the device is the ingress device
         */
        if (filteredIngressPoint.isPresent()) {
            /*
             * We are at ingress, so basically what we have to do is this:
             * apply a set of operations (treatment, FEP) in order to have
             * a transition from the initial state to the final state.
             *
             * We initialize the treatment with the Intent treatment
             */
            intent.treatment().allInstructions().stream()
                    .filter(inst -> inst.type() != Instruction.Type.NOACTION)
                    .forEach(treatmentBuilder::add);
            /*
             * We build the final selector, adding the selector
             * of the FIP to the Intent selector and potentially
             * overriding its matches.
             */
            filteredIngressPoint.get()
                    .trafficSelector()
                    .criteria()
                    .forEach(selectorBuilder::add);
            /*
             * We define the transition FIP->FEP, basically
             * the set of the operations we need for reaching
             * the final state.
             */
            TrafficTreatment forwardingTreatment =
                    forwardingTreatment(filteredIngressPoint.get().trafficSelector(),
                                        filteredEgressPoint.get().trafficSelector(),
                                        getEthType(intent.selector()));
            /*
             * We add to the treatment the actions necessary for the
             * transition, potentially overriding the treatment of the
             * Intent. The Intent treatment has always a low priority
             * in respect of the FEP.
             */
            forwardingTreatment.allInstructions().stream()
                    .filter(inst -> inst.type() != Instruction.Type.NOACTION)
                    .forEach(treatmentBuilder::add);
        } else {
            /*
             * We are in the core or in the egress switch.
             * The packets are in their final state. We need
             * to match against this final state.
             *
             * we derive the final state defined by the intent
             * treatment.
             */
            updateBuilder(selectorBuilder, intent.treatment());
            /*
             * We derive the final state defined by the unique
             * FEP. We merge the two states.
             */
            filteredEgressPoint.get()
                    .trafficSelector()
                    .criteria()
                    .forEach(selectorBuilder::add);
        }
        /*
         * Finally we set the output action.
         */
        outPorts.forEach(treatmentBuilder::setOutput);
    }

    /**
     * Computes treatment and selector which will be used
     * in the flow representation (Rule, Objective).
     *
     * @param intent the intent to compile
     * @param inPort the input port of this device
     * @param deviceId the current device
     * @param outPorts the output ports of this device
     * @return the forwarding instruction object which encapsulates treatment and selector
     */
    protected ForwardingInstructions createForwardingInstructions(LinkCollectionIntent intent,
                                                                  PortNumber inPort,
                                                                  DeviceId deviceId,
                                                                  Set<PortNumber> outPorts) {

        /*
         * We build an empty treatment and we initialize the selector with
         * the intent selector.
         */
        TrafficTreatment.Builder treatmentBuilder = DefaultTrafficTreatment
                .builder();
        TrafficSelector.Builder selectorBuilder = DefaultTrafficSelector
                .builder(intent.selector())
                .matchInPort(inPort);

        if (!intent.applyTreatmentOnEgress()) {
            manageMpIntent(selectorBuilder,
                           treatmentBuilder,
                           intent,
                           inPort,
                           deviceId,
                           outPorts
            );
        } else {
            manageSpIntent(selectorBuilder,
                           treatmentBuilder,
                           intent,
                           deviceId,
                           outPorts
            );
        }
        /*
         * We return selector and treatment necessary to build the flow rule
         * or the flow objective.
         */
        return new ForwardingInstructions(treatmentBuilder.build(), selectorBuilder.build());
    }

    /**
     * Manages the ingress of the Intents (p2p, sp2mp, mp2sp) with encapsulation.
     *
     * @param selectorBuilder the selector builder to update
     * @param treatmentBuilder the treatment builder to update
     * @param intent the intent to compile
     * @param inPort the input port of this device
     * @param deviceId the current device
     * @param outPorts the output ports of this device
     * @param outLabels the labels associated to the output port
     * @param type the encapsulation type
     */
    private void manageEncapAtIngress(TrafficSelector.Builder selectorBuilder,
                                      TrafficTreatment.Builder treatmentBuilder,
                                      LinkCollectionIntent intent,
                                      PortNumber inPort,
                                      DeviceId deviceId,
                                      Set<PortNumber> outPorts,
                                      Map<ConnectPoint, Identifier<?>> outLabels,
                                      EncapsulationType type) {

        Optional<FilteredConnectPoint> filteredIngressPoint =
                getFilteredConnectPointFromIntent(deviceId, inPort, intent);
        /*
         * We fill the selector builder with the intent selector.
         */
        intent.selector().criteria().forEach(selectorBuilder::add);
        /*
         * We build the final selector, adding the selector
         * of the FIP to the Intent selector and potentially
         * overriding its matches.
         */
        filteredIngressPoint.get()
                .trafficSelector()
                .criteria()
                .forEach(selectorBuilder::add);
        /*
         * In this scenario, we can have several output ports.
         */
        outPorts.forEach(outPort -> {
            Optional<FilteredConnectPoint> filteredEgressPoint =
                    getFilteredConnectPointFromIntent(deviceId, outPort, intent);
            /*
             * If we are at the egress, we don't handle
             * with encapsulation. Error scenario
             */
            if (filteredEgressPoint.isPresent()) {
                throw new IntentCompilationException(WRONG_ENCAPSULATION);
            }
            /*
             * Transit/core, we have to transit to the intermediate
             * state. We build a temporary selector for the encapsulation.
             */
            TrafficSelector.Builder encapBuilder = DefaultTrafficSelector.builder();
            /*
             * We retrieve the associated label to the output port.
             */
            ConnectPoint cp = new ConnectPoint(deviceId, outPort);
            Identifier<?> outLabel = outLabels.get(cp);
            /*
             * If there aren't labels, we cannot handle.
             */
            if (outLabel == null) {
                throw new IntentCompilationException(String.format(NO_LABELS, cp));
            }
            /*
             * In the core we match using encapsulation.
             */
            updateSelectorFromEncapsulation(
                    encapBuilder,
                    type,
                    outLabel
            );
            /*
             * We generate the transition.
             */
            TrafficTreatment forwardingTreatment =
                    forwardingTreatment(filteredIngressPoint.get().trafficSelector(),
                                        encapBuilder.build(),
                                        getEthType(intent.selector()));
            /*
             * We add the instruction necessary to the transition.
             */
            forwardingTreatment.allInstructions().stream()
                    .filter(inst -> inst.type() != Instruction.Type.NOACTION)
                    .forEach(treatmentBuilder::add);
            /*
             * Finally we set the output action.
             */
            treatmentBuilder.setOutput(outPort);
        });

    }

    /**
     * Manages the core and transit of the Intents (p2p, sp2mp, mp2sp)
     * with encapsulation.
     *
     * @param selectorBuilder the selector builder to update
     * @param treatmentBuilder the treatment builder to update
     * @param intent the intent to compile
     * @param inPort the input port of this device
     * @param inLabel the label associated to the input port
     * @param deviceId the current device
     * @param outPorts the output ports of this device
     * @param outLabels the labels associated to the output port
     * @param type the encapsulation type
     */
    private void manageEncapAtCoreAndEgress(TrafficSelector.Builder selectorBuilder,
                                            TrafficTreatment.Builder treatmentBuilder,
                                            LinkCollectionIntent intent,
                                            PortNumber inPort,
                                            Identifier<?> inLabel,
                                            DeviceId deviceId,
                                            Set<PortNumber> outPorts,
                                            Map<ConnectPoint, Identifier<?>> outLabels,
                                            EncapsulationType type) {

        /*
         * If there are not labels, we cannot handle.
         */
        ConnectPoint inCp = new ConnectPoint(deviceId, inPort);
        if (inLabel == null) {
            throw new IntentCompilationException(String.format(NO_LABELS, inCp));
        }
        /*
         * In the core and at egress we match using encapsulation.
         */
        updateSelectorFromEncapsulation(
                selectorBuilder,
                type,
                inLabel
        );
        /*
         * We need to order the actions. First the actions
         * related to the not-egress points.
         */
        outPorts.forEach(outPort -> {
            Optional<FilteredConnectPoint> filteredEgressPoint =
                    getFilteredConnectPointFromIntent(deviceId, outPort, intent);
            if (!filteredEgressPoint.isPresent()) {
                /*
                 * We build a temporary selector for the encapsulation.
                 */
                TrafficSelector.Builder encapBuilder = DefaultTrafficSelector.builder();
                /*
                 * We retrieve the associated label to the output port.
                 */
                ConnectPoint cp = new ConnectPoint(deviceId, outPort);
                Identifier<?> outLabel = outLabels.get(cp);
                /*
                 * If there are not labels, we cannot handle.
                 */
                if (outLabel == null) {
                    throw new IntentCompilationException(String.format(NO_LABELS, cp));
                }
                /*
                 * In the core we match using encapsulation.
                 */
                updateSelectorFromEncapsulation(
                        encapBuilder,
                        type,
                        outLabel
                );
                /*
                 * We generate the transition.
                 */
                TrafficTreatment forwardingTreatment =
                        forwardingTreatment(selectorBuilder.build(),
                                            encapBuilder.build(),
                                            getEthType(intent.selector()));
                /*
                 * We add the instruction necessary to the transition.
                 */
                forwardingTreatment.allInstructions().stream()
                        .filter(inst -> inst.type() != Instruction.Type.NOACTION)
                        .forEach(treatmentBuilder::add);
                /*
                 * Finally we set the output action.
                 */
                treatmentBuilder.setOutput(outPort);
            }

        });
        /*
         * In this case, we have to transit to the final
         * state.
         */
        outPorts.forEach(outPort -> {
            Optional<FilteredConnectPoint> filteredEgressPoint =
                    getFilteredConnectPointFromIntent(deviceId, outPort, intent);
            if (filteredEgressPoint.isPresent()) {
                /*
                 * We add the Intent treatment to the final
                 * treatment.
                 */
                intent.treatment().allInstructions().stream()
                        .filter(inst -> inst.type() != Instruction.Type.NOACTION)
                        .forEach(treatmentBuilder::add);
                /*
                 * We generate the transition FIP->FEP.
                 */
                TrafficTreatment forwardingTreatment =
                        forwardingTreatment(selectorBuilder.build(),
                                            filteredEgressPoint.get().trafficSelector(),
                                            getEthType(intent.selector()));
                /*
                 * We add the instruction necessary to the transition.
                 * Potentially we override the intent treatment.
                 */
                forwardingTreatment.allInstructions().stream()
                        .filter(inst -> inst.type() != Instruction.Type.NOACTION)
                        .forEach(treatmentBuilder::add);
                /*
                 * Finally we set the output action.
                 */
                treatmentBuilder.setOutput(outPort);
            }
        });

    }

    /**
     * Computes treatment and selector which will be used
     * in the flow representation (Rule, Objective).
     *
     * @param intent the intent to compile
     * @param inPort the input port of this device
     * @param inLabel the label associated to the input port
     * @param deviceId the current device
     * @param outPorts the output ports of this device
     * @param outLabels the labels associated to the output port
     * @param type the encapsulation type
     * @return the forwarding instruction object which encapsulates treatment and selector
     */
    protected ForwardingInstructions createForwardingInstructions(LinkCollectionIntent intent,
                                                                  PortNumber inPort,
                                                                  Identifier<?> inLabel,
                                                                  DeviceId deviceId,
                                                                  Set<PortNumber> outPorts,
                                                                  Map<ConnectPoint, Identifier<?>> outLabels,
                                                                  EncapsulationType type) {
        /*
         * We build an empty treatment and an empty selector.
         */
        TrafficTreatment.Builder treatmentBuilder = DefaultTrafficTreatment.builder();
        TrafficSelector.Builder selectorBuilder = DefaultTrafficSelector.builder();
        selectorBuilder.matchInPort(inPort);
        Optional<FilteredConnectPoint> filteredIngressPoint =
                getFilteredConnectPointFromIntent(deviceId, inPort, intent);

        if (filteredIngressPoint.isPresent()) {
            manageEncapAtIngress(selectorBuilder,
                                 treatmentBuilder,
                                 intent,
                                 inPort,
                                 deviceId,
                                 outPorts,
                                 outLabels,
                                 type
            );
        } else {
            manageEncapAtCoreAndEgress(selectorBuilder,
                                       treatmentBuilder,
                                       intent,
                                       inPort,
                                       inLabel,
                                       deviceId,
                                       outPorts,
                                       outLabels,
                                       type);
        }
        /*
         * We return selector and treatment necessary to build the flow rule
         * or the flow objective.
         */
        return new ForwardingInstructions(treatmentBuilder.build(), selectorBuilder.build());
    }

    /**
     * Helper class to encapsulate treatment and selector
     * in an unique abstraction.
     */
    protected class ForwardingInstructions {

        private TrafficTreatment trafficTreatment;

        private TrafficSelector trafficSelector;

        public ForwardingInstructions(TrafficTreatment treatment, TrafficSelector selector) {

            this.trafficTreatment = treatment;
            this.trafficSelector = selector;

        }

        public TrafficTreatment treatment() {
            return this.trafficTreatment;
        }

        public TrafficSelector selector() {
            return this.trafficSelector;
        }

    }

    /**
     * Helper method to compute input and output ports
     * for each device crossed in the path.
     *
     * @param intent the related intents
     * @param inputPorts the input ports to compute
     * @param outputPorts the output ports to compute
     */
    protected void computePorts(LinkCollectionIntent intent,
                                SetMultimap<DeviceId, PortNumber> inputPorts,
                                SetMultimap<DeviceId, PortNumber> outputPorts) {

        for (Link link : intent.links()) {
            inputPorts.put(link.dst().deviceId(), link.dst().port());
            outputPorts.put(link.src().deviceId(), link.src().port());
        }

        for (ConnectPoint ingressPoint : intent.ingressPoints()) {
            inputPorts.put(ingressPoint.deviceId(), ingressPoint.port());
        }

        for (ConnectPoint egressPoint : intent.egressPoints()) {
            outputPorts.put(egressPoint.deviceId(), egressPoint.port());
        }

    }

    /**
     * Retrieves the encapsulation constraint from the link collection intent.
     *
     * @param intent the intent to analyze
     * @return the encapsulation constraint
     */
    protected Optional<EncapsulationConstraint> getIntentEncapConstraint(LinkCollectionIntent intent) {
        return intent.constraints().stream()
                .filter(constraint -> constraint instanceof EncapsulationConstraint)
                .map(x -> (EncapsulationConstraint) x).findAny();
    }


    /**
     * Get FilteredConnectPoint from LinkCollectionIntent.
     *
     * @param deviceId device Id for connect point
     * @param portNumber port number
     * @param intent source intent
     * @return filtered connetion point
     */
    private Optional<FilteredConnectPoint> getFilteredConnectPointFromIntent(DeviceId deviceId,
                                                                             PortNumber portNumber,
                                                                             LinkCollectionIntent intent) {
        Set<FilteredConnectPoint> filteredConnectPoints =
                Sets.union(intent.filteredIngressPoints(), intent.filteredEgressPoints());
        return filteredConnectPoints.stream()
                .filter(port -> port.connectPoint().deviceId().equals(deviceId))
                .filter(port -> port.connectPoint().port().equals(portNumber))
                .findFirst();
    }

    /**
     * Get tag criterion from selector.
     * The criterion should be one of type in tagCriterionTypes.
     *
     * @param selector selector
     * @return Criterion that matched, if there is no tag criterion, return null
     */
    private Criterion getTagCriterion(TrafficSelector selector) {
        return selector.criteria().stream()
                .filter(criterion -> TAG_CRITERION_TYPES.contains(criterion.type()))
                .findFirst()
                .orElse(Criteria.dummy());

    }

    /**
     * Compares tag type between ingress and egress point and generate
     * treatment for egress point of intent.
     *
     * @param ingress ingress selector for the intent
     * @param egress egress selector for the intent
     * @param ethType the ethertype to use in mpls_pop
     * @return Builder of TrafficTreatment
     */
    private TrafficTreatment forwardingTreatment(TrafficSelector ingress,
                                                 TrafficSelector egress,
                                                 EthType ethType) {


        if (ingress.equals(egress)) {
            return DefaultTrafficTreatment.emptyTreatment();
        }

        TrafficTreatment.Builder builder = DefaultTrafficTreatment.builder();

        /*
         * "null" means there is no tag for the port
         * Tag criterion will be null if port is normal connection point
         */
        Criterion ingressTagCriterion = getTagCriterion(ingress);
        Criterion egressTagCriterion = getTagCriterion(egress);

        if (ingressTagCriterion.type() != egressTagCriterion.type()) {

            /*
             * Tag type of ingress port and egress port are different.
             * Need to remove tag from ingress, then add new tag for egress.
             * Remove nothing if ingress port use VXLAN or there is no tag
             * on ingress port.
             */
            switch (ingressTagCriterion.type()) {
                case VLAN_VID:
                    builder.popVlan();
                    break;

                case MPLS_LABEL:
                    builder.popMpls(ethType);
                    break;

                default:
                    break;

            }

            /*
             * Push new tag for egress port.
             */
            switch (egressTagCriterion.type()) {
                case VLAN_VID:
                    builder.pushVlan();
                    break;

                case MPLS_LABEL:
                    builder.pushMpls();
                    break;

                default:
                    break;

            }
        }

        switch (egressTagCriterion.type()) {
            case VLAN_VID:
                VlanIdCriterion vlanIdCriterion = (VlanIdCriterion) egressTagCriterion;
                builder.setVlanId(vlanIdCriterion.vlanId());
                break;

            case MPLS_LABEL:
                MplsCriterion mplsCriterion = (MplsCriterion) egressTagCriterion;
                builder.setMpls(mplsCriterion.label());
                break;

            case TUNNEL_ID:
                TunnelIdCriterion tunnelIdCriterion = (TunnelIdCriterion) egressTagCriterion;
                builder.setTunnelId(tunnelIdCriterion.tunnelId());
                break;

            default:
                break;

        }

        return builder.build();
    }

    /**
     * Update the selector builder using a L0 instruction.
     *
     * @param builder the builder to update
     * @param l0instruction the l0 instruction to use
     */
    private void updateBuilder(TrafficSelector.Builder builder, L0ModificationInstruction l0instruction) {
        throw new IntentCompilationException(UNSUPPORTED_L0);
    }

    /**
     * Update the selector builder using a L1 instruction.
     *
     * @param builder the builder to update
     * @param l1instruction the l1 instruction to use
     */
    private void updateBuilder(TrafficSelector.Builder builder, L1ModificationInstruction l1instruction) {
        throw new IntentCompilationException(UNSUPPORTED_L1);
    }

    /**
     * Update the selector builder using a L2 instruction.
     *
     * @param builder the builder to update
     * @param l2instruction the l2 instruction to use
     */
    private void updateBuilder(TrafficSelector.Builder builder, L2ModificationInstruction l2instruction) {
        switch (l2instruction.subtype()) {
            case ETH_SRC:
            case ETH_DST:
                ModEtherInstruction ethInstr = (ModEtherInstruction) l2instruction;
                switch (ethInstr.subtype()) {
                    case ETH_SRC:
                        builder.matchEthSrc(ethInstr.mac());
                        break;

                    case ETH_DST:
                        builder.matchEthDst(ethInstr.mac());
                        break;

                    default:
                        throw new IntentCompilationException(UNSUPPORTED_ETH_SUBTYPE);
                }
                break;

            case VLAN_ID:
                ModVlanIdInstruction vlanIdInstr = (ModVlanIdInstruction) l2instruction;
                builder.matchVlanId(vlanIdInstr.vlanId());
                break;

            case VLAN_PUSH:
                //FIXME
                break;

            case VLAN_POP:
                //TODO how do we handle dropped label? remove the selector?
                throw new IntentCompilationException(UNSUPPORTED_POP_ACTION);
            case VLAN_PCP:
                ModVlanPcpInstruction vlanPcpInstruction = (ModVlanPcpInstruction) l2instruction;
                builder.matchVlanPcp(vlanPcpInstruction.vlanPcp());
                break;

            case MPLS_LABEL:
            case MPLS_PUSH:
                //FIXME
                ModMplsLabelInstruction mplsInstr = (ModMplsLabelInstruction) l2instruction;
                builder.matchMplsLabel(mplsInstr.label());
                break;

            case MPLS_POP:
                //TODO how do we handle dropped label? remove the selector?
                throw new IntentCompilationException(UNSUPPORTED_POP_ACTION);
            case DEC_MPLS_TTL:
                // no-op
                break;

            case MPLS_BOS:
                ModMplsBosInstruction mplsBosInstr = (ModMplsBosInstruction) l2instruction;
                builder.matchMplsBos(mplsBosInstr.mplsBos());
                break;

            case TUNNEL_ID:
                ModTunnelIdInstruction tunInstr = (ModTunnelIdInstruction) l2instruction;
                builder.matchTunnelId(tunInstr.tunnelId());
                break;

            default:
                throw new IntentCompilationException(UNSUPPORTED_L2);
        }

    }

    /**
     * Update the selector builder using a L3 instruction.
     *
     * @param builder the builder to update
     * @param l3instruction the l3 instruction to use
     */
    private void updateBuilder(TrafficSelector.Builder builder, L3ModificationInstruction l3instruction) {
        // TODO check ethernet proto
        switch (l3instruction.subtype()) {
            case IPV4_SRC:
            case IPV4_DST:
            case IPV6_SRC:
            case IPV6_DST:
                ModIPInstruction ipInstr = (ModIPInstruction) l3instruction;
                // TODO check if ip falls in original prefix
                IpPrefix prefix = ipInstr.ip().toIpPrefix();
                switch (ipInstr.subtype()) {
                    case IPV4_SRC:
                        builder.matchIPSrc(prefix);
                        break;

                    case IPV4_DST:
                        builder.matchIPSrc(prefix);
                        break;

                    case IPV6_SRC:
                        builder.matchIPv6Src(prefix);
                        break;

                    case IPV6_DST:
                        builder.matchIPv6Dst(prefix);
                        break;

                    default:
                        throw new IntentCompilationException(UNSUPPORTED_IP_SUBTYPE);
                }
                break;

            case IPV6_FLABEL:
                ModIPv6FlowLabelInstruction ipFlowInstr = (ModIPv6FlowLabelInstruction) l3instruction;
                builder.matchIPv6FlowLabel(ipFlowInstr.flowLabel());
                break;

            case DEC_TTL:
                // no-op
                break;

            case TTL_OUT:
                // no-op
                break;

            case TTL_IN:
                // no-op
                break;

            case ARP_SPA:
                ModArpIPInstruction arpIpInstr = (ModArpIPInstruction) l3instruction;
                if (arpIpInstr.ip().isIp4()) {
                    builder.matchArpSpa((Ip4Address) arpIpInstr.ip());
                } else {
                    throw new IntentCompilationException(UNSUPPORTED_ARP);
                }
                break;

            case ARP_SHA:
                ModArpEthInstruction arpEthInstr = (ModArpEthInstruction) l3instruction;
                builder.matchArpSha(arpEthInstr.mac());
                break;

            case ARP_OP:
                ModArpOpInstruction arpOpInstr = (ModArpOpInstruction) l3instruction;
                //FIXME is the long to int cast safe?
                builder.matchArpOp((int) arpOpInstr.op());
                break;

            default:
                throw new IntentCompilationException(UNSUPPORTED_L3);
        }
    }

    /**
     * Update the selector builder using a L4 instruction.
     *
     * @param builder the builder to update
     * @param l4instruction the l4 instruction to use
     */
    private void updateBuilder(TrafficSelector.Builder builder, L4ModificationInstruction l4instruction) {
        if (l4instruction instanceof ModTransportPortInstruction) {
            // TODO check IP proto
            ModTransportPortInstruction l4mod = (ModTransportPortInstruction) l4instruction;
            switch (l4mod.subtype()) {
                case TCP_SRC:
                    builder.matchTcpSrc(l4mod.port());
                    break;

                case TCP_DST:
                    builder.matchTcpDst(l4mod.port());
                    break;

                case UDP_SRC:
                    builder.matchUdpSrc(l4mod.port());
                    break;

                case UDP_DST:
                    builder.matchUdpDst(l4mod.port());
                    break;

                default:
                    throw new IntentCompilationException(UNSUPPORTED_L4_SUBTYPE);
            }
        } else {
            throw new IntentCompilationException(UNSUPPORTED_L4);
        }
    }

    /**
     * Update selector builder by using treatment.
     *
     * @param builder builder to update
     * @param treatment traffic treatment
     */
    private void updateBuilder(TrafficSelector.Builder builder, TrafficTreatment treatment) {

        treatment.allInstructions().forEach(instruction -> {
            switch (instruction.type()) {
                case L0MODIFICATION:
                    updateBuilder(builder, (L0ModificationInstruction) instruction);
                    break;

                case L1MODIFICATION:
                    updateBuilder(builder, (L1ModificationInstruction) instruction);
                    break;

                case L2MODIFICATION:
                    updateBuilder(builder, (L2ModificationInstruction) instruction);
                    break;

                case L3MODIFICATION:
                    updateBuilder(builder, (L3ModificationInstruction) instruction);
                    break;

                case L4MODIFICATION:
                    updateBuilder(builder, (L4ModificationInstruction) instruction);
                    break;

                case NOACTION:
                case OUTPUT:
                case GROUP:
                case QUEUE:
                case TABLE:
                case METER:
                case METADATA:
                case EXTENSION: // TODO is extension no-op or unsupported?
                    // Nothing to do
                    break;

                default:
                    throw new IntentCompilationException(UNSUPPORTED_INSTRUCTION);
            }
        });

    }

    /**
     * The method generates a selector starting from
     * the encapsulation information (type and label to match).
     *
     * @param selectorBuilder the builder to update
     * @param type the type of encapsulation
     * @param identifier the label to match
     */
    private void updateSelectorFromEncapsulation(TrafficSelector.Builder selectorBuilder,
                                                 EncapsulationType type,
                                                 Identifier<?> identifier) {
        switch (type) {
            case MPLS:
                MplsLabel label = (MplsLabel) identifier;
                selectorBuilder.matchMplsLabel(label);
                selectorBuilder.matchEthType(Ethernet.MPLS_UNICAST);
                break;

            case VLAN:
                VlanId id = (VlanId) identifier;
                selectorBuilder.matchVlanId(id);
                break;

            default:
                throw new IntentCompilationException(UNKNOWN_ENCAPSULATION);
        }
    }

    /**
     * Helper function to define the match on the ethertype.
     * If the selector define an ethertype we will use it,
     * otherwise IPv4 will be used by default.
     *
     * @param selector the traffic selector
     * @return the ethertype we should match
     */
    private EthType getEthType(TrafficSelector selector) {
        Criterion c = selector.getCriterion(Criterion.Type.ETH_TYPE);
        if (c != null && c instanceof EthTypeCriterion) {
            EthTypeCriterion ethertype = (EthTypeCriterion) c;
            return ethertype.ethType();
        }
        return EthType.EtherType.IPV4.ethType();
    }

}
