/*
 * Copyright 2020-present Open Networking Foundation
 *
 * 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.driver.traceable;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import org.onlab.packet.EthType;
import org.onlab.packet.IpPrefix;
import org.onlab.packet.VlanId;
import org.onosproject.core.GroupId;
import org.onosproject.driver.pipeline.ofdpa.Ofdpa2Pipeline;
import org.onosproject.driver.pipeline.ofdpa.OvsOfdpaPipeline;
import org.onosproject.net.DeviceId;
import org.onosproject.net.PipelineTraceableHitChain;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DataPlaneEntity;
import org.onosproject.net.PipelineTraceableInput;
import org.onosproject.net.PipelineTraceableOutput;
import org.onosproject.net.PortNumber;
import org.onosproject.net.behaviour.PipelineTraceable;
import org.onosproject.net.behaviour.Pipeliner;
import org.onosproject.net.driver.AbstractHandlerBehaviour;
import org.onosproject.net.flow.DefaultTrafficSelector;
import org.onosproject.net.flow.FlowEntry;
import org.onosproject.net.flow.FlowRule;
import org.onosproject.net.flow.IndexTableId;
import org.onosproject.net.flow.TableId;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flow.criteria.Criteria;
import org.onosproject.net.flow.criteria.Criterion;
import org.onosproject.net.flow.criteria.EthCriterion;
import org.onosproject.net.flow.criteria.EthTypeCriterion;
import org.onosproject.net.flow.criteria.IPCriterion;
import org.onosproject.net.flow.criteria.MetadataCriterion;
import org.onosproject.net.flow.criteria.VlanIdCriterion;
import org.onosproject.net.flow.instructions.Instruction;
import org.onosproject.net.flow.instructions.Instructions;
import org.onosproject.net.flow.instructions.Instructions.OutputInstruction;
import org.onosproject.net.flow.instructions.L2ModificationInstruction;
import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModVlanIdInstruction;
import org.onosproject.net.group.Group;
import org.onosproject.net.group.GroupBucket;
import org.slf4j.Logger;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

import static org.onosproject.driver.pipeline.ofdpa.OfdpaGroupHandlerUtility.L2_FLOOD_TYPE;
import static org.onosproject.driver.pipeline.ofdpa.OfdpaGroupHandlerUtility.L2_INTERFACE_TYPE;
import static org.onosproject.driver.pipeline.ofdpa.OfdpaGroupHandlerUtility.L2_MULTICAST_TYPE;
import static org.onosproject.driver.pipeline.ofdpa.OfdpaGroupHandlerUtility.L3_MULTICAST_TYPE;
import static org.onosproject.driver.pipeline.ofdpa.OfdpaPipelineUtility.ACL_TABLE;
import static org.onosproject.driver.pipeline.ofdpa.OfdpaPipelineUtility.BRIDGING_TABLE;
import static org.onosproject.driver.pipeline.ofdpa.OfdpaPipelineUtility.MPLS_L3_TYPE_TABLE;
import static org.onosproject.driver.pipeline.ofdpa.OfdpaPipelineUtility.MULTICAST_ROUTING_TABLE;
import static org.onosproject.driver.pipeline.ofdpa.OfdpaPipelineUtility.TMAC_TABLE;
import static org.onosproject.driver.pipeline.ofdpa.OfdpaPipelineUtility.VLAN_TABLE;

import static org.slf4j.LoggerFactory.getLogger;

/**
 * Implements a driver behavior that enables a logical probe packet to traverse the device pipeline
 * and to return dataplane entities that matched against the logical probe packet.
 */
public class OfdpaPipelineTraceable extends AbstractHandlerBehaviour implements PipelineTraceable {

    private static final Logger log = getLogger(OfdpaPipelineTraceable.class);
    // Behavior context
    private DeviceId deviceId;
    private String driverName;
    // Utility
    private final Comparator<FlowEntry> comparatorById = Comparator.comparing(
            (FlowEntry f) -> ((IndexTableId) f.table()).id());
    private final Comparator<FlowEntry> comparatorByPriority = Comparator.comparing(
            FlowRule::priority);

    @Override
    public void init() {
        this.deviceId = this.data().deviceId();
        this.driverName = this.data().driver().name();
    }

    @Override
    public PipelineTraceableOutput apply(PipelineTraceableInput input) {
        PipelineTraceableOutput.Builder outputBuilder = PipelineTraceableOutput.builder();
        log.debug("Current packet {} - applying flow tables", input.ingressPacket());
        List<FlowEntry> outputFlows = new ArrayList<>();
        List<Instruction> deferredInstructions = new ArrayList<>();
        PipelineTraceableHitChain currentHitChain = PipelineTraceableHitChain.emptyHitChain();
        TrafficSelector currentPacket = DefaultTrafficSelector.builder(input.ingressPacket()).build();

        // Init step - find out the first table
        int initialTableId = -1;
        FlowEntry nextTableIdEntry = findNextTableIdEntry(initialTableId, input.flows());
        if (nextTableIdEntry == null) {
            currentHitChain.setEgressPacket(currentPacket);
            currentHitChain.dropped();
            return outputBuilder.appendToLog("No flow rules for device " + deviceId + ". Aborting")
                    .noFlows()
                    .addHitChain(currentHitChain)
                    .build();
        }

        // Iterates over the flow tables until the end of the pipeline
        TableId tableId = nextTableIdEntry.table();
        FlowEntry flowEntry;
        boolean lastTable = false;
        while (!lastTable) {
            log.debug("Searching a Flow Entry on table {} for packet {}", tableId, currentPacket);

            // Gets the rule that matches the incoming packet
            flowEntry = matchHighestPriority(currentPacket, tableId, input.flows());
            log.debug("Found Flow Entry {}", flowEntry);

            // If the flow entry on a table is null and we are on hardware we treat as table miss, with few exceptions
            if (flowEntry == null && isHardwareSwitch()) {
                log.debug("Ofdpa Hw setup, no flow rule means table miss");

                if (((IndexTableId) tableId).id() == MPLS_L3_TYPE_TABLE) {
                    // Apparently a miss but Table 27 on OFDPA is a fixed table
                    currentPacket = handleOfdpa27FixedTable(input.ingressPacket(), currentPacket);
                    // The nextTable should be ACL
                    tableId = IndexTableId.of(ACL_TABLE - 1);
                }

                // Finding next table to go In case of miss
                nextTableIdEntry = findNextTableIdEntry(((IndexTableId) tableId).id(), input.flows());
                log.debug("Next table id entry {}", nextTableIdEntry);
                // FIXME Find better solution that enable granularity greater than 0 or all rules
                // (another possibility is max tableId)
                if (nextTableIdEntry == null && currentHitChain.getHitChain().size() == 0) {
                    currentHitChain.setEgressPacket(currentPacket);
                    currentHitChain.dropped();
                    return outputBuilder.appendToLog("No flow rules for device " + deviceId + ". Aborting")
                            .noFlows()
                            .addHitChain(currentHitChain)
                            .build();

                } else if (nextTableIdEntry == null) {
                    // Means that no more flow rules are present
                    lastTable = true;

                } else if (((IndexTableId) tableId).id() == TMAC_TABLE) {
                    // If the table is 20 OFDPA skips to table 50
                    log.debug("A miss on Table 20 on OFDPA means that we skip directly to table 50");
                    tableId = IndexTableId.of(BRIDGING_TABLE);

                } else if (((IndexTableId) tableId).id() == MULTICAST_ROUTING_TABLE) {
                    // If the table is 40 OFDPA skips to table 60
                    log.debug("A miss on Table 40 on OFDPA means that we skip directly to table 60");
                    tableId = IndexTableId.of(ACL_TABLE);
                } else {
                    tableId = nextTableIdEntry.table();
                }

            } else if (flowEntry == null) {
                currentHitChain.setEgressPacket(currentPacket);
                currentHitChain.dropped();
                return outputBuilder.appendToLog("Packet has no match on table " + tableId
                        + " in device " + deviceId + ". Dropping")
                        .noFlows()
                        .addHitChain(currentHitChain)
                        .build();
            } else {

                // If the table has a transition
                if (flowEntry.treatment().tableTransition() != null) {
                    // Updates the next table we transitions to
                    tableId = IndexTableId.of(flowEntry.treatment().tableTransition().tableId());
                    log.debug("Flow Entry has transition to table Id {}", tableId);
                    currentHitChain.addDataPlaneEntity(new DataPlaneEntity(flowEntry));
                } else {
                    // Table has no transition so it means that it's an output rule if on the last table
                    log.debug("Flow Entry has no transition to table, treating as last rule {}", flowEntry);
                    currentHitChain.addDataPlaneEntity(new DataPlaneEntity(flowEntry));
                    outputFlows.add(flowEntry);
                    lastTable = true;
                }

                // Updates the packet according to the immediate actions of this flow rule.
                currentPacket = updatePacket(currentPacket, flowEntry.treatment().immediate()).build();

                // Saves the deferred rules for later maintaining the order
                deferredInstructions.addAll(flowEntry.treatment().deferred());

                // If the flow requires to clear deferred actions we do so for all the ones we encountered.
                if (flowEntry.treatment().clearedDeferred()) {
                    deferredInstructions.clear();
                }

                // On table 10 OFDPA needs two rules to apply the vlan if none and then to transition to the next table.
                if (shouldMatchSecondVlanFlow(flowEntry)) {

                    // Let's get the packet vlanId instruction
                    VlanIdCriterion packetVlanIdCriterion =
                            (VlanIdCriterion) currentPacket.getCriterion(Criterion.Type.VLAN_VID);

                    // Let's get the flow entry vlan mod instructions
                    ModVlanIdInstruction entryModVlanIdInstruction = (ModVlanIdInstruction) flowEntry.treatment()
                            .immediate().stream()
                            .filter(instruction -> instruction instanceof ModVlanIdInstruction)
                            .findFirst().orElse(null);

                    // If the entry modVlan is not null we need to make sure that the packet has been updated and there
                    // is a flow rule that matches on same criteria and with updated vlanId
                    if (entryModVlanIdInstruction != null) {

                        FlowEntry secondVlanFlow = getSecondFlowEntryOnTable10(currentPacket,
                                packetVlanIdCriterion, entryModVlanIdInstruction, input.flows());

                        // We found the flow that we expected
                        if (secondVlanFlow != null) {
                            currentHitChain.addDataPlaneEntity(new DataPlaneEntity(secondVlanFlow));
                        } else {
                            currentHitChain.setEgressPacket(currentPacket);
                            currentHitChain.dropped();
                            return outputBuilder.appendToLog("Missing forwarding rule for tagged"
                                    + " packet on " + deviceId)
                                    .noFlows()
                                    .addHitChain(currentHitChain)
                                    .build();
                        }
                    }
                }
            }
        }

        // Creating a modifiable builder for the egress packet
        TrafficSelector.Builder egressPacket = DefaultTrafficSelector.builder(currentPacket);

        log.debug("Current packet {} - applying output flows", currentPacket);
        // Handling output flows which basically means handling output to controller.
        // OVS and OFDPA have both immediate -> OUTPUT:CONTROLLER. Theoretically there is no
        // need to reflect the updates performed on the packets and on the chain.
        List<PortNumber> outputPorts = new ArrayList<>();
        handleOutputFlows(currentPacket, outputFlows, egressPacket, outputPorts, currentHitChain,
                outputBuilder, input.ingressPacket());

        // Immediate instructions
        log.debug("Current packet {} - applying immediate instructions", currentPacket);
        // Handling immediate instructions which basically means handling output to controller.
        // OVS has immediate -> group -> OUTPUT:CONTROLLER.
        List<DataPlaneEntity> entries = ImmutableList.copyOf(currentHitChain.getHitChain());
        // Go to the next step - using a copy of the egress packet and of the hit chain
        PipelineTraceableHitChain newHitChain = PipelineTraceableHitChain.emptyHitChain();
        currentHitChain.getHitChain().forEach(newHitChain::addDataPlaneEntity);
        TrafficSelector.Builder newEgressPacket = DefaultTrafficSelector.builder(egressPacket.build());
        for (DataPlaneEntity entry : entries) {
            flowEntry = entry.getFlowEntry();
            if (flowEntry != null) {
                getGroupsFromInstructions(input.groups(), flowEntry.treatment().immediate(), newEgressPacket,
                        outputPorts, newHitChain, outputBuilder, input, false);
            }
        }

        // Deferred instructions
        log.debug("Current packet {} - applying deferred instructions", egressPacket.build());
        // If we have deferred instructions at this point we handle them.
        // Here, we are basically handling the normal forwarding scenarios that
        // always happen through deferred:group. Here we don't care about the
        // egress packet and of the hit chain. This is the last step.
        if (deferredInstructions.size() > 0) {
            handleDeferredActions(egressPacket.build(), input.groups(), deferredInstructions, outputPorts,
                    currentHitChain, outputBuilder, input);
        }

        // If there are no outputs - packet is dropped
        // Let's store the partial hit chain and set a message
        if (outputPorts.isEmpty()) {
            currentHitChain.setEgressPacket(egressPacket.build());
            currentHitChain.dropped();
            outputBuilder.appendToLog("Packet has no output in device " + deviceId + ". Dropping")
                    .dropped()
                    .addHitChain(currentHitChain);
        }

        // Done!
        return outputBuilder.build();
    }

    // Finds the flow entry with the minimum next table Id.
    private FlowEntry findNextTableIdEntry(int currentId, List<FlowEntry> flows) {
        return flows.stream()
                .filter(f -> ((IndexTableId) f.table()).id() > currentId)
                .min(comparatorById).orElse(null);
    }

    // Finds the rule in the device that matches the input packet and has the highest priority.
    // TODO Candidate for an AbstractBehavior implementation
    private FlowEntry matchHighestPriority(TrafficSelector packet, TableId tableId, List<FlowEntry> flows) {
        //Computing the possible match rules.
        return flows.stream()
                .filter(flowEntry -> flowEntry.table().equals(tableId))
                .filter(flowEntry -> match(packet, flowEntry))
                .max(comparatorByPriority).orElse(null);
    }

    // Matches the packet with the given flow entry
    // TODO Candidate for an AbstractBehavior implementation
    private boolean match(TrafficSelector packet, FlowEntry flowEntry) {
        return flowEntry.selector().criteria().stream().allMatch(criterion -> {
            Criterion.Type type = criterion.type();
            //If the criterion has IP we need to do LPM to establish matching.
            if (type.equals(Criterion.Type.IPV4_SRC) || type.equals(Criterion.Type.IPV4_DST) ||
                    type.equals(Criterion.Type.IPV6_SRC) || type.equals(Criterion.Type.IPV6_DST)) {
                return matchIp(packet, (IPCriterion) criterion);
                //we check that the packet contains the criterion provided by the flow rule.
            } else if (type.equals(Criterion.Type.ETH_SRC_MASKED)) {
                return matchMac(packet, (EthCriterion) criterion, false);
            } else if (type.equals(Criterion.Type.ETH_DST_MASKED)) {
                return matchMac(packet, (EthCriterion) criterion, true);
            } else {
                return packet.criteria().contains(criterion);
            }
        });
    }

    // Checks if the packet has an dst or src IP and if that IP matches the subnet of the ip criterion
    // TODO Candidate for an AbstractBehavior implementation
    private boolean matchIp(TrafficSelector packet, IPCriterion criterion) {
        IPCriterion matchCriterion = (IPCriterion) packet.getCriterion(criterion.type());
        // if the packet does not have an IPv4 or IPv6 criterion we return true
        if (matchCriterion == null) {
            return false;
        }
        log.debug("Checking if {} is under {}", matchCriterion.ip(), criterion.ip());
        IpPrefix subnet = criterion.ip();
        return subnet.contains(matchCriterion.ip().address());
    }

    // Checks if the packet has a dst or src MAC and if that Mac matches the mask of the mac criterion
    // TODO Candidate for an AbstractBehavior implementation
    private boolean matchMac(TrafficSelector packet, EthCriterion hitCriterion, boolean dst) {
        //Packet can have only one EthCriterion
        EthCriterion matchCriterion;
        if (dst) {
            matchCriterion = (EthCriterion) packet.criteria().stream().filter(criterion1 ->
                    criterion1.type().equals(Criterion.Type.ETH_DST_MASKED) ||
                            criterion1.type().equals(Criterion.Type.ETH_DST))
                    .findFirst().orElse(null);
        } else {
            matchCriterion = (EthCriterion) packet.criteria().stream().filter(criterion1 ->
                    criterion1.type().equals(Criterion.Type.ETH_SRC_MASKED) ||
                            criterion1.type().equals(Criterion.Type.ETH_SRC))
                    .findFirst().orElse(null);
        }
        //if the packet does not have an ETH criterion we return true
        if (matchCriterion == null) {
            return true;
        }
        log.debug("Checking if {} is under {}/{}", matchCriterion.mac(), hitCriterion.mac(), hitCriterion.mask());
        return matchCriterion.mac().inRange(hitCriterion.mac(), hitCriterion.mask());
    }

    // Handles table 27 in Ofpda which is a fixed table not visible to any controller that handles Mpls Labels.
    private TrafficSelector handleOfdpa27FixedTable(TrafficSelector initialPacket, TrafficSelector packet) {
        log.debug("Handling table 27 on OFDPA, removing mpls ETH Type and change mpls label");

        Criterion mplsCriterion = packet.getCriterion(Criterion.Type.ETH_TYPE);
        // T3 was using the initial packet of the trace - using the metadata in the packet to carry this info
        Criterion metadataCriterion = initialPacket.getCriterion(Criterion.Type.METADATA);
        ImmutableList.Builder<Instruction> builder = ImmutableList.builder();

        // If the packet comes in with the expected elements we update it as per OFDPA spec.
        if (mplsCriterion != null && ((EthTypeCriterion) mplsCriterion).ethType()
                .equals(EthType.EtherType.MPLS_UNICAST.ethType()) && metadataCriterion != null) {

            // Get the metadata to restore the original ethertype
            long ethType = ((MetadataCriterion) metadataCriterion).metadata();
            //TODO update with parsing with eth MPLS pop Instruction for treating label an bos
            Instruction ethInstruction = Instructions.popMpls(EthType.EtherType.lookup((short) ethType).ethType());
            //FIXME what do we use as L3_Unicast mpls Label ?
            //translateInstruction(builder, ethInstruction);
            builder.add(ethInstruction);

            // Filtering out metadata
            TrafficSelector.Builder currentPacketBuilder = DefaultTrafficSelector.builder();
            packet.criteria().stream()
                    .filter(criterion -> criterion.type() != Criterion.Type.METADATA)
                    .forEach(currentPacketBuilder::add);
            packet = currentPacketBuilder.build();
        }
        packet = updatePacket(packet, builder.build()).build();
        return packet;
    }

    // Applies all give instructions to the input packet
    private TrafficSelector.Builder updatePacket(TrafficSelector packet, List<Instruction> instructions) {
        TrafficSelector.Builder newSelector = DefaultTrafficSelector.builder(packet);

        //FIXME optimize
        for (Instruction instruction : instructions) {
            newSelector = translateInstruction(newSelector, instruction);
        }
        return newSelector;
    }

    // Applies an instruction to the packet in the form of a selector
    private TrafficSelector.Builder translateInstruction(TrafficSelector.Builder newSelector, Instruction instruction) {
        log.debug("Translating instruction {}", instruction);
        log.debug("New Selector {}", newSelector.build());
        //TODO add as required
        Criterion criterion = null;
        if (instruction.type() == Instruction.Type.L2MODIFICATION) {
            L2ModificationInstruction l2Instruction = (L2ModificationInstruction) instruction;
            switch (l2Instruction.subtype()) {
                case VLAN_ID:
                    ModVlanIdInstruction vlanIdInstruction =
                            (ModVlanIdInstruction) instruction;
                    VlanId id = vlanIdInstruction.vlanId();
                    criterion = Criteria.matchVlanId(id);
                    break;
                case VLAN_POP:
                    criterion = Criteria.matchVlanId(VlanId.NONE);
                    break;
                case MPLS_PUSH:
                    L2ModificationInstruction.ModMplsHeaderInstruction mplsEthInstruction =
                            (L2ModificationInstruction.ModMplsHeaderInstruction) instruction;
                    criterion = Criteria.matchEthType(mplsEthInstruction.ethernetType().toShort());

                    // When pushing MPLS adding metadata to remember the original ethtype
                    if (isHardwareSwitch()) {
                        TrafficSelector temporaryPacket = newSelector.build();
                        Criterion ethCriterion = temporaryPacket.getCriterion(Criterion.Type.ETH_TYPE);
                        if (ethCriterion != null) {
                            TrafficSelector.Builder tempSelector = DefaultTrafficSelector.builder(temporaryPacket);
                            // Store the old ether type for the
                            tempSelector.matchMetadata(((EthTypeCriterion) ethCriterion).ethType().toShort());
                            newSelector = tempSelector;
                        }
                    }

                    break;
                case MPLS_POP:
                    L2ModificationInstruction.ModMplsHeaderInstruction mplsPopInstruction =
                            (L2ModificationInstruction.ModMplsHeaderInstruction) instruction;
                    criterion = Criteria.matchEthType(mplsPopInstruction.ethernetType().toShort());

                    //When popping MPLS we remove label and BOS
                    TrafficSelector temporaryPacket = newSelector.build();
                    if (temporaryPacket.getCriterion(Criterion.Type.MPLS_LABEL) != null) {
                        TrafficSelector.Builder noMplsSelector = DefaultTrafficSelector.builder();
                        temporaryPacket.criteria().stream().filter(c ->
                                !c.type().equals(Criterion.Type.MPLS_LABEL) &&
                                        !c.type().equals(Criterion.Type.MPLS_BOS))
                                .forEach(noMplsSelector::add);
                        newSelector = noMplsSelector;
                    }

                    break;
                case MPLS_LABEL:
                    L2ModificationInstruction.ModMplsLabelInstruction mplsLabelInstruction =
                            (L2ModificationInstruction.ModMplsLabelInstruction) instruction;
                    criterion = Criteria.matchMplsLabel(mplsLabelInstruction.label());
                    newSelector.matchMplsBos(true);
                    break;
                case ETH_DST:
                    L2ModificationInstruction.ModEtherInstruction modEtherDstInstruction =
                            (L2ModificationInstruction.ModEtherInstruction) instruction;
                    criterion = Criteria.matchEthDst(modEtherDstInstruction.mac());
                    break;
                case ETH_SRC:
                    L2ModificationInstruction.ModEtherInstruction modEtherSrcInstruction =
                            (L2ModificationInstruction.ModEtherInstruction) instruction;
                    criterion = Criteria.matchEthSrc(modEtherSrcInstruction.mac());
                    break;
                default:
                    log.debug("Unsupported L2 Instruction");
                    break;
            }
        } else {
            log.debug("Unsupported Instruction");
        }
        if (criterion != null) {
            log.debug("Adding criterion {}", criterion);
            newSelector.add(criterion);
        }
        return newSelector;
    }

    // Method that finds a flow rule on table 10 that matches the packet and the VLAN of the already
    // found rule on table 10. This is because OFDPA needs two rules on table 10, first to apply the rule,
    // second to transition to following table
    private FlowEntry getSecondFlowEntryOnTable10(TrafficSelector packet, VlanIdCriterion packetVlanIdCriterion,
                                                  ModVlanIdInstruction entryModVlanIdInstruction,
                                                  List<FlowEntry> flows) {
        FlowEntry secondVlanFlow = null;
        // Check the packet has been update from the first rule.
        if (packetVlanIdCriterion.vlanId().equals(entryModVlanIdInstruction.vlanId())) {
            // find a rule on the same table that matches the vlan and
            // also all the other elements of the flow such as input port
            secondVlanFlow = flows.stream()
                    .filter(entry -> entry.table().equals(IndexTableId.of(VLAN_TABLE)))
                    .filter(entry -> {
                        VlanIdCriterion criterion = (VlanIdCriterion) entry.selector()
                                .getCriterion(Criterion.Type.VLAN_VID);
                        return criterion != null && match(packet, entry)
                                && criterion.vlanId().equals(entryModVlanIdInstruction.vlanId());
                    }).findFirst().orElse(null);

        }
        return secondVlanFlow;
    }

    // Handles output flows
    private List<FlowEntry> handleOutputFlows(TrafficSelector currentPacket, List<FlowEntry> outputFlows,
                                              TrafficSelector.Builder egressPacket, List<PortNumber> outputPorts,
                                              PipelineTraceableHitChain currentHitChain,
                                              PipelineTraceableOutput.Builder outputBuilder,
                                              TrafficSelector initialPacket) {
        // TODO optimization
        // outputFlows contains also last rule of device, so we need filtering for OUTPUT instructions.
        List<FlowEntry> outputFlowEntries = outputFlows.stream().filter(flow -> flow.treatment()
                .allInstructions().stream().filter(instruction -> instruction.type()
                        .equals(Instruction.Type.OUTPUT)).count() > 0).collect(Collectors.toList());

        if (outputFlowEntries.size() > 1) {
            outputBuilder.appendToLog("More than one flow rule with OUTPUT instruction");
            log.warn("There cannot be more than one flow entry with OUTPUT instruction for {}", currentPacket);
        }

        if (outputFlowEntries.size() == 1) {
            OutputInstruction outputInstruction = (OutputInstruction) outputFlowEntries.get(0).treatment()
                    .allInstructions().stream()
                    .filter(instruction -> instruction.type().equals(Instruction.Type.OUTPUT))
                    .findFirst().get();
            buildOutputFromDevice(egressPacket, outputPorts, outputInstruction, currentHitChain,
                    outputBuilder, initialPacket, false);
        }

        return outputFlowEntries;
    }

    // Builds a possible output from this device
    private void buildOutputFromDevice(TrafficSelector.Builder egressPacket,
                                       List<PortNumber> outputPorts,
                                       OutputInstruction outputInstruction,
                                       PipelineTraceableHitChain currentHitChain,
                                       PipelineTraceableOutput.Builder outputBuilder,
                                       TrafficSelector initialPacket,
                                       boolean dropped) {
        // Store the output port for further processing
        outputPorts.add(outputInstruction.port());
        // Create the final hit chain from the current one (deep copy)
        ConnectPoint outputPort = new ConnectPoint(deviceId, outputInstruction.port());
        PipelineTraceableHitChain finalHitChain = new PipelineTraceableHitChain(outputPort,
                Lists.newArrayList(currentHitChain.getHitChain()),
                egressPacket.build());
        // Dropped early
        if (dropped) {
            log.debug("Packet {} has been dropped", egressPacket.build());
        } else {
            finalHitChain.pass();
        }
        if (outputPort.port().equals(PortNumber.CONTROLLER)) {
            handleVlanToController(finalHitChain, initialPacket);
        }
        // If there is already a chain do not add a copy
        outputBuilder.addHitChain(finalHitChain);
    }

    // If the initial packet comes tagged with a Vlan we output it with that to ONOS.
    // If ONOS applied a vlan we remove it.
    // TODO Candidate for an AbstractBehavior implementation
    private void handleVlanToController(PipelineTraceableHitChain currentHitChain, TrafficSelector initialPacket) {

        VlanIdCriterion initialVid = (VlanIdCriterion) initialPacket
                .getCriterion(Criterion.Type.VLAN_VID);
        VlanIdCriterion finalVid = (VlanIdCriterion) currentHitChain.getEgressPacket()
                .getCriterion(Criterion.Type.VLAN_VID);

        if (initialVid != null && !initialVid.equals(finalVid) && initialVid.vlanId().equals(VlanId.NONE)) {
            Set<Criterion> finalCriteria = new HashSet<>(currentHitChain.getEgressPacket().criteria());
            //removing the final vlanId
            finalCriteria.remove(finalVid);
            TrafficSelector.Builder packetUpdated = DefaultTrafficSelector.builder();
            finalCriteria.forEach(packetUpdated::add);
            //Initial was none so we set it to that
            packetUpdated.add(Criteria.matchVlanId(VlanId.NONE));
            //Update final packet
            currentHitChain.setEgressPacket(packetUpdated.build());
        }
    }

    // Gets group information from instructions.
    private void getGroupsFromInstructions(Map<GroupId, Group> groups, List<Instruction> instructions,
                                           TrafficSelector.Builder egressPacket, List<PortNumber> outputPorts,
                                           PipelineTraceableHitChain currentHitChain,
                                           PipelineTraceableOutput.Builder outputBuilder,
                                           PipelineTraceableInput input,
                                           boolean dropped) {

        List<Instruction> groupInstructionlist = new ArrayList<>();
        // sort instructions according to priority (larger Instruction.Type ENUM constant first)
        // which enables to treat other actions before the OUTPUT action
        // TODO improve the priority scheme according to the OpenFlow ActionSet spec
        List<Instruction> instructionsSorted = new ArrayList<>();
        instructionsSorted.addAll(instructions);
        instructionsSorted.sort((instr1, instr2) ->
                Integer.compare(instr2.type().ordinal(), instr1.type().ordinal()));

        // Handles first all non-group instructions
        for (Instruction instruction : instructionsSorted) {
            log.debug("Considering Instruction {}", instruction);
            // if the instruction is not group we need to update the packet or add the output
            // to the possible outputs for this packet
            if (!instruction.type().equals(Instruction.Type.GROUP)) {
                // FIXME ?? if the instruction is not group we need to update the packet
                // or add the output to the possible outputs for this packet
                if (instruction.type().equals(Instruction.Type.OUTPUT)) {
                    buildOutputFromDevice(egressPacket, outputPorts, (OutputInstruction) instruction,
                            currentHitChain, outputBuilder, input.ingressPacket(), dropped);
                } else {
                    egressPacket = translateInstruction(egressPacket, instruction);
                }
            } else {
                // Store for later if the instruction is pointing to a group
                groupInstructionlist.add(instruction);
            }
        }

        // handle all the internal instructions pointing to a group.
        for (Instruction instr : groupInstructionlist) {
            Instructions.GroupInstruction groupInstruction = (Instructions.GroupInstruction) instr;
            Group group = groups.get(groupInstruction.groupId());

            // group does not exist in the dataplane
            if (group == null) {
                currentHitChain.setEgressPacket(egressPacket.build());
                currentHitChain.dropped();
                outputBuilder.appendToLog("Null group for Instruction " + instr)
                        .noGroups()
                        .addHitChain(currentHitChain);
                break;
            }

            log.debug("Analyzing group {}", group.id());

            // group is there but there are no members/buckets
            if (group.buckets().buckets().size() == 0) {
                // add the group to the traversed groups
                currentHitChain.addDataPlaneEntity(new DataPlaneEntity(group));
                currentHitChain.setEgressPacket(egressPacket.build());
                currentHitChain.dropped();
                outputBuilder.appendToLog("Group " + group.id() + " has no buckets")
                        .noMembers()
                        .addHitChain(currentHitChain);
                break;
            }

            PipelineTraceableHitChain newHitChain;
            TrafficSelector.Builder newEgressPacket;
            // Cycle in each of the group's buckets and add them to the groups for this Device.
            for (GroupBucket bucket : group.buckets().buckets()) {

                // add the group to the traversed groups
                currentHitChain.addDataPlaneEntity(new DataPlaneEntity(group));

                // Go to the next step - using a copy of the egress packet and of the hit chain
                newHitChain = PipelineTraceableHitChain.emptyHitChain();
                currentHitChain.getHitChain().forEach(newHitChain::addDataPlaneEntity);
                newEgressPacket = DefaultTrafficSelector.builder(egressPacket.build());
                getGroupsFromInstructions(groups, bucket.treatment().allInstructions(), newEgressPacket,
                        outputPorts, newHitChain, outputBuilder, input,
                        dropped | isDropped(group.id(), bucket, input.ingressPort()));
            }
        }
    }

    private boolean isDropped(GroupId groupId, GroupBucket bucket, ConnectPoint ingressPort) {
        log.debug("Verify if the packet has to be dropped by the input port {}",
                ingressPort);
        // if It is not a l2 flood group and l2/l3 mcast skip
        int maskedId = groupId.id() & 0xF0000000;
        if (maskedId != L2_FLOOD_TYPE && maskedId != L2_MULTICAST_TYPE &&
                maskedId != L3_MULTICAST_TYPE) {
            return false;
        }
        // Verify if the bucket points to the ingress port
        Instructions.GroupInstruction groupInstruction;
        for (Instruction instr : bucket.treatment().allInstructions()) {
            if (instr.type().equals(Instruction.Type.GROUP)) {
                groupInstruction = (Instructions.GroupInstruction) instr;
                // FIXME According to the OFDPA spec for L3 MCAST if the VLAN is changed packet is not dropped
                if ((groupInstruction.groupId().id() & 0xF0000000) == L2_INTERFACE_TYPE) {
                    return (groupInstruction.groupId().id() & 0x0000FFFF) == ingressPort.port().toLong();
                }
            }
        }
        return false;
    }

    // Handles deferred instructions taken from the flows
    private void handleDeferredActions(TrafficSelector egressPacket, Map<GroupId, Group> groups,
                                       List<Instruction> deferredInstructions, List<PortNumber> outputPorts,
                                       PipelineTraceableHitChain currentHitChain,
                                       PipelineTraceableOutput.Builder outputBuilder,
                                       PipelineTraceableInput input) {
        // Update the packet with the deferred instructions
        TrafficSelector.Builder newEgressPacket = updatePacket(egressPacket, deferredInstructions);

        //Gather any output instructions from the deferred instruction
        List<Instruction> outputFlowInstruction = deferredInstructions.stream().filter(instruction ->
                instruction.type().equals(Instruction.Type.OUTPUT))
                .collect(Collectors.toList());

        //We are considering deferred instructions from flows, there can only be one output.
        if (outputFlowInstruction.size() > 1) {
            outputBuilder.appendToLog("More than one flow rule with OUTPUT instruction");
            log.warn("There cannot be more than one flow entry with OUTPUT instruction for {}", egressPacket);
        }

        // If there is one output let's go through that. No need to make a copy
        // of the egress packet and of the current hit chain.
        if (outputFlowInstruction.size() == 1) {
            buildOutputFromDevice(newEgressPacket, outputPorts, (OutputInstruction) outputFlowInstruction.get(0),
                    currentHitChain, outputBuilder, input.ingressPacket(), false);
        }

        // If there is no output let's see if there any deferred instruction point to groups.
        // No need to make a copy of the egress packet and of the current chain.
        if (outputFlowInstruction.size() == 0) {
            getGroupsFromInstructions(groups, deferredInstructions, newEgressPacket, outputPorts,
                    currentHitChain, outputBuilder, input, false);
        }
    }

    // Checks whether it is an hw device based on different means.
    // throws an exception if the behavior has been used with wrong drivers
    private boolean isHardwareSwitch() {
        // Check if we are using ofdpa hw device by looking at the pipeliner
        // if we need to support a device that does not have a pipeliner
        // we can add an exclusion rules before this
        if (!this.handler().hasBehaviour(Pipeliner.class)) {
            throw new UnsupportedOperationException("Not supported device");
        }
        Pipeliner pipeliner = this.handler().behaviour(Pipeliner.class);
        if (pipeliner instanceof OvsOfdpaPipeline) {
            return false;
        } else if (pipeliner instanceof Ofdpa2Pipeline) {
            return true;
        }
        throw new UnsupportedOperationException("Not supported device");
    }

    // OF-DPA hardware requires one VLAN filtering rule and one VLAN assignment flow in the VLAN table.
    // This method is used to determine whether there is a need to match a second VLAN flow after
    // matching the given flowEntry.
    private boolean shouldMatchSecondVlanFlow(FlowEntry flowEntry) {
        // if we need to support a device that does not have a pipeliner
        // we can add an exclusion rules before this
        if (!this.handler().hasBehaviour(Pipeliner.class)) {
            throw new UnsupportedOperationException("Not supported device");
        }
        Pipeliner pipeliner = this.handler().behaviour(Pipeliner.class);
        if (!(pipeliner instanceof Ofdpa2Pipeline)) {
            return false;
        }
        return ((Ofdpa2Pipeline) pipeliner).requireSecondVlanTableEntry() &&
                flowEntry.table().equals(IndexTableId.of(VLAN_TABLE)) &&
                flowEntry.selector().getCriterion(Criterion.Type.VLAN_VID) != null &&
                ((VlanIdCriterion) flowEntry.selector().getCriterion(Criterion.Type.VLAN_VID))
                        .vlanId().equals(VlanId.NONE);
    }

}
