/*
 * Copyright 2017-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.pipeline.ofdpa;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import org.onlab.packet.VlanId;
import org.onosproject.core.GroupId;
import org.onosproject.net.DeviceId;
import org.onosproject.net.PortNumber;
import org.onosproject.net.behaviour.NextGroup;
import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.flow.criteria.Criterion;
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.L2ModificationInstruction;
import org.onosproject.net.flow.instructions.L2ModificationInstruction.L2SubType;
import org.onosproject.net.flowobjective.NextObjective;
import org.onosproject.net.group.DefaultGroupBucket;
import org.onosproject.net.group.DefaultGroupKey;
import org.onosproject.net.group.Group;
import org.onosproject.net.group.GroupBucket;
import org.onosproject.net.group.GroupDescription;
import org.onosproject.net.group.GroupKey;
import org.onosproject.net.group.GroupService;
import org.slf4j.Logger;

import java.util.ArrayList;
import java.util.Deque;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

import static org.onosproject.driver.pipeline.ofdpa.Ofdpa2Pipeline.isNotMplsBos;
import static org.onosproject.driver.pipeline.ofdpa.OfdpaGroupHandlerUtility.OfdpaMplsGroupSubType.OFDPA_GROUP_TYPE_SHIFT;
import static org.onosproject.driver.pipeline.ofdpa.OfdpaGroupHandlerUtility.OfdpaMplsGroupSubType.OFDPA_MPLS_SUBTYPE_SHIFT;
import static org.onosproject.net.flowobjective.NextObjective.Type.HASHED;
import static org.slf4j.LoggerFactory.getLogger;

public final class OfdpaGroupHandlerUtility {
    /*
     * OFDPA requires group-id's to have a certain form.
     * L2 Interface Groups have <4bits-0><12bits-vlanId><16bits-portId>
     * L3 Unicast Groups have <4bits-2><28bits-index>
     * L3 Unicast Groups for double-vlan have <4bits-2><1bit-1><12bits-vlanId><15bits-portId>
     * MPLS Interface Groups have <4bits-9><4bits:0><24bits-index>
     * L3 ECMP Groups have <4bits-7><28bits-index>
     * L2 Flood Groups have <4bits-4><12bits-vlanId><16bits-index>
     * L3 VPN Groups have <4bits-9><4bits-2><24bits-index>
     */
    static final int L2_INTERFACE_TYPE = 0x00000000;
    static final int L2_UNFILTERED_TYPE = 0xb0000000;
    static final int L3_INTERFACE_TYPE = 0x50000000;
    static final int L3_UNICAST_TYPE = 0x20000000;
    static final int L3_MULTICAST_TYPE = 0x60000000;
    static final int MPLS_INTERFACE_TYPE = 0x90000000;
    static final int MPLS_L3VPN_SUBTYPE = 0x92000000;
    static final int L3_ECMP_TYPE = 0x70000000;
    static final int L2_FLOOD_TYPE = 0x40000000;
    static final int L2_MULTICAST_TYPE = 0x30000000;

    static final int TYPE_MASK = 0x0fffffff;
    static final int SUBTYPE_MASK = 0x00ffffff;
    static final int TYPE_VLAN_MASK = 0x0000ffff;
    static final int TYPE_L3UG_DOUBLE_VLAN_MASK = 0x08000000;

    static final int THREE_BIT_MASK = 0x0fff;
    static final int FOUR_BIT_MASK = 0xffff;
    static final int PORT_LEN = 16;

    static final int PORT_LOWER_BITS_MASK = 0x3f;
    static final long PORT_HIGHER_BITS_MASK = ~PORT_LOWER_BITS_MASK;

    static final String HEX_PREFIX = "0x";
    private static final Logger log = getLogger(OfdpaGroupHandlerUtility.class);

    private OfdpaGroupHandlerUtility() {
        // Utility classes should not have a public or default constructor.
    }

    /**
     * Returns the outport in a traffic treatment.
     *
     * @param tt the treatment
     * @return the PortNumber for the outport or null
     */
    static PortNumber readOutPortFromTreatment(TrafficTreatment tt) {
        for (Instruction ins : tt.allInstructions()) {
            if (ins.type() == Instruction.Type.OUTPUT) {
                return ((Instructions.OutputInstruction) ins).port();
            }
        }
        return null;
    }

    /**
     * Returns the MPLS label-id in a traffic treatment.
     *
     * @param tt the traffic treatment
     * @return an integer representing the MPLS label-id, or -1 if not found
     */
    static int readLabelFromTreatment(TrafficTreatment tt) {
        for (Instruction ins : tt.allInstructions()) {
            if (ins.type() == Instruction.Type.L2MODIFICATION) {
                L2ModificationInstruction insl2 = (L2ModificationInstruction) ins;
                if (insl2.subtype() == L2SubType.MPLS_LABEL) {
                    return ((L2ModificationInstruction.ModMplsLabelInstruction) insl2)
                                .label().id();
                }
            }
        }
        return -1;
    }

    /**
     * Helper enum to handle the different MPLS group
     * types.
     */
    public enum OfdpaMplsGroupSubType {
        MPLS_INTF((short) 0),
        L2_VPN((short) 1),
        L3_VPN((short) 2),
        MPLS_TUNNEL_LABEL_1((short) 3),
        MPLS_TUNNEL_LABEL_2((short) 4),
        MPLS_SWAP_LABEL((short) 5),
        MPLS_ECMP((short) 8);

        private short value;
        public static final int OFDPA_GROUP_TYPE_SHIFT = 28;
        public static final int OFDPA_MPLS_SUBTYPE_SHIFT = 24;

        OfdpaMplsGroupSubType(short value) {
            this.value = value;
        }

        /**
         * Gets the value as an short.
         *
         * @return the value as an short
         */
        public short getValue() {
            return this.value;
        }

    }

    /**
     * Creates MPLS Label group id given a sub type and
     * the index.
     *
     * @param subType the MPLS Label group sub type
     * @param index the index of the group
     * @return the OFDPA group id
     */
    public static Integer makeMplsLabelGroupId(OfdpaMplsGroupSubType subType, int index) {
        index = index & 0x00FFFFFF;
        return index | (9 << OFDPA_GROUP_TYPE_SHIFT) | (subType.value << OFDPA_MPLS_SUBTYPE_SHIFT);
    }

    /**
     * Creates MPLS Forwarding group id given a sub type and
     * the index.
     *
     * @param subType the MPLS forwarding group sub type
     * @param index the index of the group
     * @return the OFDPA group id
     */
    public static Integer makeMplsForwardingGroupId(OfdpaMplsGroupSubType subType, int index) {
        index = index & 0x00FFFFFF;
        return index | (10 << OFDPA_GROUP_TYPE_SHIFT) | (subType.value << OFDPA_MPLS_SUBTYPE_SHIFT);
    }

    /**
     * Returns the set of existing output ports in the group represented by
     * allActiveKeys.
     *
     * @param allActiveKeys list of group key chain
     * @param groupService the group service to get group information
     * @param deviceId the device id to get group
     * @return a set of output port from the list of group key chain
     */
    public static Set<PortNumber> getExistingOutputPorts(List<Deque<GroupKey>> allActiveKeys,
                                                     GroupService groupService,
                                                     DeviceId deviceId) {
        Set<PortNumber> existingPorts = Sets.newHashSet();

        allActiveKeys.forEach(keyChain -> {
            GroupKey ifaceGroupKey = keyChain.peekLast();
            Group ifaceGroup = groupService.getGroup(deviceId, ifaceGroupKey);
            if (ifaceGroup != null && !ifaceGroup.buckets().buckets().isEmpty()) {
                ifaceGroup.buckets().buckets().forEach(bucket -> {
                    PortNumber portNumber = readOutPortFromTreatment(bucket.treatment());
                    if (portNumber != null) {
                        existingPorts.add(portNumber);
                    }
                });
            }
        });
        return existingPorts;
    }

    /**
     * Returns a list of all indices in the allActiveKeys list (that represents
     * a group) if the list element (a bucket or group-chain) has treatments
     * that match the given outport and label.
     *
     * @param allActiveKeys the representation of the group
     * @param groupService groups service for querying group information
     * @param deviceId the device id for the device that contains the group
     * @param portToMatch the port to match in the group buckets
     * @param labelToMatch the MPLS label-id to match in the group buckets
     * @return a list of indexes in the allActiveKeys list where the list element
     *         has treatments that match the given portToMatch and labelToMatch.
     *         Could be empty if no list elements were found to match the given
     *         port and label.
     */
    public static List<Integer> existingPortAndLabel(
                                               List<Deque<GroupKey>> allActiveKeys,
                                               GroupService groupService,
                                               DeviceId deviceId,
                                               PortNumber portToMatch,
                                               int labelToMatch) {
        List<Integer> indices = new ArrayList<>();
        int index = 0;
        for (Deque<GroupKey> keyChain : allActiveKeys) {
            GroupKey ifaceGroupKey = keyChain.peekLast();
            Group ifaceGroup = groupService.getGroup(deviceId, ifaceGroupKey);
            if (ifaceGroup != null && !ifaceGroup.buckets().buckets().isEmpty()) {
                PortNumber portNumber = readOutPortFromTreatment(
                   ifaceGroup.buckets().buckets().iterator().next().treatment());
                if (portNumber != null && portNumber.equals(portToMatch)) {
                    // check for label in the 2nd group of this chain
                    GroupKey secondKey = (GroupKey) keyChain.toArray()[1];
                    Group secondGroup = groupService.getGroup(deviceId, secondKey);
                    if (secondGroup != null &&
                            !secondGroup.buckets().buckets().isEmpty()) {
                        int label = readLabelFromTreatment(
                                        secondGroup.buckets().buckets()
                                        .iterator().next().treatment());
                        if (label == labelToMatch) {
                            indices.add(index);
                        }
                    }
                }
            }
            index++;
        }

        return indices;
    }

    /**
     * Get indices to remove comparing next group with next objective.
     *
     * @param allActiveKeys the representation of the group
     * @param nextObjective the next objective to verify
     * @param groupService groups service for querying group information
     * @param deviceId the device id for the device that contains the group
     * @return a list of indexes in the allActiveKeys to remove.
     */
    public static List<Integer> indicesToRemoveFromNextGroup(List<Deque<GroupKey>> allActiveKeys,
                                                       NextObjective nextObjective,
                                                       GroupService groupService,
                                                       DeviceId deviceId) {
        List<Integer> indicesToRemove = Lists.newArrayList();
        int index = 0;
        // Iterate over the chain in the next data
        for (Deque<GroupKey> keyChain : allActiveKeys) {
            // Valid chain should have at least two elements
            if (keyChain.size() >= 2) {
                // Get last group (l2if) and retrieve port number
                GroupKey ifaceGroupKey = keyChain.peekLast();
                Group ifaceGroup = groupService.getGroup(deviceId, ifaceGroupKey);
                if (ifaceGroup != null && !ifaceGroup.buckets().buckets().isEmpty()) {
                    PortNumber portNumber = readOutPortFromTreatment(
                            ifaceGroup.buckets().buckets().iterator().next().treatment());
                    // If there is not a port number continue
                    if (portNumber != null) {
                        // check for label in the 2nd group of this chain
                        GroupKey secondKey = (GroupKey) keyChain.toArray()[1];
                        Group secondGroup = groupService.getGroup(deviceId, secondKey);
                        // If there is not a second group or there are no buckets continue
                        if (secondGroup != null && !secondGroup.buckets().buckets().isEmpty()) {
                            // Get label or -1
                            int label = readLabelFromTreatment(
                                    secondGroup.buckets().buckets()
                                            .iterator().next().treatment());
                            // Iterate over the next treatments looking for the port and the label
                            boolean matches = false;
                            for (TrafficTreatment t : nextObjective.next()) {
                                PortNumber tPort = readOutPortFromTreatment(t);
                                int tLabel = readLabelFromTreatment(t);
                                if (tPort != null && tPort.equals(portNumber) && tLabel == label) {
                                    // We found it, exit
                                    matches = true;
                                    break;
                                }
                            }
                            // Not found, we have to remove it
                            if (!matches) {
                                indicesToRemove.add(index);
                            }
                        }
                    }
                }
            }
            index++;
        }
        return indicesToRemove;
    }

    /**
     * The purpose of this function is to verify if the hashed next
     * objective is supported by the current pipeline.
     *
     * @param nextObjective the hashed objective to verify
     * @return true if the hashed objective is supported. Otherwise false.
     */
    public static boolean verifyHashedNextObjective(NextObjective nextObjective) {
        // if it is not hashed, there is something wrong;
        if (nextObjective.type() != HASHED) {
            return false;
        }
        // The case non supported is the MPLS-ECMP. For now, we try
        // to create a MPLS-ECMP for the transport of a VPWS. The
        // necessary info are contained in the meta selector. In particular
        // we are looking for the case of BoS==False;
        TrafficSelector metaSelector = nextObjective.meta();
        if (metaSelector != null && isNotMplsBos(metaSelector)) {
            return false;
        }

        return true;
    }

    /**
     * Generates a list of group buckets from given list of group information
     * and group bucket type.
     *
     * @param groupInfos a list of group information
     * @param bucketType group bucket type
     * @return list of group bucket generate from group information
     */
    static List<GroupBucket> generateNextGroupBuckets(List<GroupInfo> groupInfos,
                                                       GroupDescription.Type bucketType) {
        List<GroupBucket> newBuckets = Lists.newArrayList();

        groupInfos.forEach(groupInfo -> {
            GroupDescription groupDesc = groupInfo.nextGroupDesc();
            TrafficTreatment.Builder treatmentBuilder = DefaultTrafficTreatment.builder();
            treatmentBuilder.group(new GroupId(groupDesc.givenGroupId()));
            GroupBucket newBucket = null;
            switch (bucketType) {
                case ALL:
                    newBucket =
                            DefaultGroupBucket.createAllGroupBucket(treatmentBuilder.build());
                    break;
                case INDIRECT:
                    newBucket =
                            DefaultGroupBucket.createIndirectGroupBucket(treatmentBuilder.build());
                    break;
                case SELECT:
                    newBucket =
                            DefaultGroupBucket.createSelectGroupBucket(treatmentBuilder.build());
                    break;
                case FAILOVER:
                    // TODO: support failover bucket type
                default:
                    log.warn("Unknown bucket type: {}", bucketType);
                    break;
            }

            if (newBucket != null) {
                newBuckets.add(newBucket);
            }

        });

        return ImmutableList.copyOf(newBuckets);
    }

    static List<GroupBucket> createL3MulticastBucket(List<GroupInfo> groupInfos) {
        List<GroupBucket> l3McastBuckets = new ArrayList<>();
        // For each inner group
        groupInfos.forEach(groupInfo -> {
            // Points to L3 interface group if there is one.
            // Otherwise points to L2 interface group directly.
            GroupDescription nextGroupDesc = (groupInfo.nextGroupDesc() != null) ?
                    groupInfo.nextGroupDesc() : groupInfo.innerMostGroupDesc();
            TrafficTreatment.Builder ttb = DefaultTrafficTreatment.builder();
            ttb.group(new GroupId(nextGroupDesc.givenGroupId()));
            GroupBucket abucket = DefaultGroupBucket.createAllGroupBucket(ttb.build());
            l3McastBuckets.add(abucket);
        });
        // Done return the new list of buckets
        return l3McastBuckets;
    }

    static Group retrieveTopLevelGroup(List<Deque<GroupKey>> allActiveKeys,
                                       DeviceId deviceId,
                                       GroupService groupService,
                                       int nextid) {
        GroupKey topLevelGroupKey;
        if (!allActiveKeys.isEmpty()) {
            topLevelGroupKey = allActiveKeys.get(0).peekFirst();
        } else {
            log.warn("Could not determine top level group while processing"
                             + "next:{} in dev:{}", nextid, deviceId);
            return null;
        }
        Group topGroup = groupService.getGroup(deviceId, topLevelGroupKey);
        if (topGroup == null) {
            log.warn("Could not find top level group while processing "
                             + "next:{} in dev:{}", nextid, deviceId);
        }
        return topGroup;
    }

    /**
     * Extracts VlanId from given group ID.
     *
     * @param groupId the group ID
     * @return vlan id of the group
     */
    public static VlanId extractVlanIdFromGroupId(int groupId) {
        // Extract the 9th to 20th bit from group id as vlan id.
        short vlanId = (short) ((groupId & 0x0fff0000) >> 16);
        return VlanId.vlanId(vlanId);
    }

    public static GroupKey l2FloodGroupKey(VlanId vlanId, DeviceId deviceId) {
        int hash = Objects.hash(deviceId, vlanId);
        hash = L2_FLOOD_TYPE | TYPE_MASK & hash;
        return new DefaultGroupKey(Ofdpa2Pipeline.appKryo.serialize(hash));
    }

    public static GroupKey l2MulticastGroupKey(VlanId vlanId, DeviceId deviceId) {
        int hash = Objects.hash(deviceId, vlanId);
        hash = L2_MULTICAST_TYPE | TYPE_MASK & hash;
        return new DefaultGroupKey(Ofdpa2Pipeline.appKryo.serialize(hash));
    }

    public static int l2GroupId(VlanId vlanId, long portNum) {
        return L2_INTERFACE_TYPE | (vlanId.toShort() << 16) | (int) portNum;
    }

    public static int l2UnfilteredGroupId(long portNum) {
        return L2_UNFILTERED_TYPE | (int) portNum;
    }

    /**
     * Returns a hash as the L2 Interface Group Key.
     *
     * Keep the lower 6-bit for port since port number usually smaller than 64.
     * Hash other information into remaining 28 bits.
     *
     * @param deviceId Device ID
     * @param vlanId VLAN ID
     * @param portNumber Port number
     * @return L2 interface group key
     */
    public static int l2InterfaceGroupKey(DeviceId deviceId, VlanId vlanId, long portNumber) {
        int portLowerBits = (int) portNumber & PORT_LOWER_BITS_MASK;
        long portHigherBits = portNumber & PORT_HIGHER_BITS_MASK;
        int hash = Objects.hash(deviceId, vlanId, portHigherBits);
        return L2_INTERFACE_TYPE | (TYPE_MASK & hash << 6) | portLowerBits;
    }

    /**
     * Returns a hash as the L2 Unfiltered Interface Group Key.
     *
     * Keep the lower 6-bit for port since port number usually smaller than 64.
     * Hash other information into remaining 28 bits.
     *
     * @param deviceId Device ID
     * @param portNumber Port number
     * @return L2 unfiltered interface group key
     */
    public static int l2UnfilteredGroupKey(DeviceId deviceId, long portNumber) {
        int portLowerBits = (int) portNumber & PORT_LOWER_BITS_MASK;
        long portHigherBits = portNumber & PORT_HIGHER_BITS_MASK;
        int hash = Objects.hash(deviceId, portHigherBits);
        return L2_UNFILTERED_TYPE | (TYPE_MASK & hash << 6) | portLowerBits;
    }

    /**
     * Utility class for moving group information around.
     *
     * Example: Suppose we are trying to create a group-chain A-B-C-D, where
     * A is the top level group, and D is the inner-most group, typically L2 Interface.
     * The innerMostGroupDesc is always D. At various stages of the creation
     * process the nextGroupDesc may be C or B. The nextGroupDesc exists to
     * inform the referencing group about which group it needs to point to,
     * and wait for. In some cases the group chain may simply be A-B. In this case,
     * both innerMostGroupDesc and nextGroupDesc will be B.
     */
    public static class GroupInfo {
        /**
         * Description of the inner-most group of the group chain.
         * It is always an L2 interface group.
         */
        private GroupDescription innerMostGroupDesc;

        /**
         * Description of the next group in the group chain.
         * It can be L2 interface, L3 interface, L3 unicast, L3 VPN group.
         * It is possible that nextGroupDesc is the same as the innerMostGroup.
         */
        private GroupDescription nextGroupDesc;

        GroupInfo(GroupDescription innerMostGroupDesc, GroupDescription nextGroupDesc) {
            this.innerMostGroupDesc = innerMostGroupDesc;
            this.nextGroupDesc = nextGroupDesc;
        }

        /**
         * Getter for innerMostGroupDesc.
         *
         * @return the inner most group description
         */
        public GroupDescription innerMostGroupDesc() {
            return innerMostGroupDesc;
        }

        /**
         * Getter for the next group description.
         *
         * @return the next group description
         */
        public GroupDescription nextGroupDesc() {
            return nextGroupDesc;
        }

        /**
         * Setter of nextGroupDesc.
         *
         * @param nextGroupDesc the given value to set
         */
        public void nextGroupDesc(GroupDescription nextGroupDesc) {
            this.nextGroupDesc = nextGroupDesc;
        }
    }

    /**
     * Represents an entire group-chain that implements a Next-Objective from
     * the application. The objective is represented as a list of deques, where
     * each deque is a separate chain of groups.
     * <p>
     * For example, an ECMP group with 3 buckets, where each bucket points to
     * a group chain of L3 Unicast and L2 interface groups will look like this:
     * <ul>
     * <li>List[0] is a Deque of GroupKeyECMP(first)-GroupKeyL3(middle)-GroupKeyL2(last)
     * <li>List[1] is a Deque of GroupKeyECMP(first)-GroupKeyL3(middle)-GroupKeyL2(last)
     * <li>List[2] is a Deque of GroupKeyECMP(first)-GroupKeyL3(middle)-GroupKeyL2(last)
     * </ul>
     * where the first element of each deque is the same, representing the
     * top level ECMP group, while every other element represents a unique groupKey.
     * <p>
     * Also includes information about the next objective that
     * resulted in these group-chains.
     *
     */
    public static class OfdpaNextGroup implements NextGroup {
        private final NextObjective nextObj;
        private final List<Deque<GroupKey>> gkeys;

        public OfdpaNextGroup(List<Deque<GroupKey>> gkeys, NextObjective nextObj) {
            this.nextObj = nextObj;
            this.gkeys = gkeys;
        }

        public NextObjective nextObjective() {
            return nextObj;
        }

        public List<Deque<GroupKey>> allKeys() {
            return gkeys;
        }

        @Override
        public byte[] data() {
            return Ofdpa2Pipeline.appKryo.serialize(gkeys);
        }
    }

    /**
     * Represents a group element that is part of a chain of groups.
     * Stores enough information to create a Group Description to add the group
     * to the switch by requesting the Group Service. Objects instantiating this
     * class are meant to be temporary and live as long as it is needed to wait for
     * referenced groups in the group chain to be created.
     */
    public static class GroupChainElem {
        private GroupDescription groupDescription;
        private AtomicInteger waitOnGroups;
        private boolean addBucketToGroup;
        private DeviceId deviceId;

        public GroupChainElem(GroupDescription groupDescription, int waitOnGroups,
                       boolean addBucketToGroup, DeviceId deviceId) {
            this.groupDescription = groupDescription;
            this.waitOnGroups = new AtomicInteger(waitOnGroups);
            this.addBucketToGroup = addBucketToGroup;
            this.deviceId = deviceId;
        }

        /**
         * This method atomically decrements the counter for the number of
         * groups this GroupChainElement is waiting on, for notifications from
         * the Group Service. When this method returns a value of 0, this
         * GroupChainElement is ready to be processed.
         *
         * @return integer indication of the number of notifications being waited on
         */
        int decrementAndGetGroupsWaitedOn() {
            return waitOnGroups.decrementAndGet();
        }

        public GroupDescription groupDescription() {
            return groupDescription;
        }

        public boolean addBucketToGroup() {
            return addBucketToGroup;
        }

        @Override
        public String toString() {
            return (Integer.toHexString(groupDescription.givenGroupId()) +
                    " groupKey: " + groupDescription.appCookie() +
                    " waiting-on-groups: " + waitOnGroups.get() +
                    " addBucketToGroup: " + addBucketToGroup +
                    " device: " + deviceId);
        }
    }

    public static class GroupChecker implements Runnable {
        final Logger log = getLogger(getClass());
        private Ofdpa2GroupHandler groupHandler;

        public GroupChecker(Ofdpa2GroupHandler groupHandler) {
            this.groupHandler = groupHandler;
        }

        @Override
        public void run() {
            // GroupChecker execution needs to be protected
            // from unhandled exceptions
            try {
                if (groupHandler.pendingGroups.size() != 0) {
                    log.debug("pending groups being checked: {}",
                              groupHandler.pendingGroups.asMap().keySet());
                }
                if (groupHandler.pendingAddNextObjectives.size() != 0) {
                    log.debug("pending add-next-obj being checked: {}",
                              groupHandler.pendingAddNextObjectives.asMap().keySet());
                }
                if (groupHandler.pendingRemoveNextObjectives.size() != 0) {
                    log.debug("pending remove-next-obj being checked: {}",
                              groupHandler.pendingRemoveNextObjectives.asMap().values());
                }
                if (groupHandler.pendingUpdateNextObjectives.size() != 0) {
                    log.debug("pending update-next-obj being checked: {}",
                              groupHandler.pendingUpdateNextObjectives.keySet());
                }

                Set<GroupKey> keys = groupHandler.pendingGroups.asMap().keySet()
                        .stream()
                        .filter(key -> groupHandler.groupService
                                .getGroup(groupHandler.deviceId, key) != null)
                        .collect(Collectors.toSet());
                Set<GroupKey> otherkeys = groupHandler.pendingAddNextObjectives
                        .asMap().keySet().stream()
                        .filter(otherkey -> groupHandler.groupService
                                .getGroup(groupHandler.deviceId, otherkey) != null)
                        .collect(Collectors.toSet());
                keys.addAll(otherkeys);
                keys.forEach(key -> groupHandler.processPendingAddGroupsOrNextObjs(key, false));

                keys = groupHandler.pendingUpdateNextObjectives.keySet()
                        .stream()
                        .filter(key -> groupHandler.groupService
                                .getGroup(groupHandler.deviceId, key) != null)
                        .collect(Collectors.toSet());
                keys.forEach(key -> groupHandler.processPendingUpdateNextObjs(key));

                Set<GroupKey> k = Sets.newHashSet();
                groupHandler.pendingRemoveNextObjectives
                    .asMap().values().stream().forEach(keylist -> {
                        k.addAll(keylist.stream()
                                 .filter(key -> groupHandler.groupService
                                         .getGroup(groupHandler.deviceId, key) == null)
                                 .collect(Collectors.toSet()));
                    });
                k.forEach(key -> groupHandler.processPendingRemoveNextObjs(key));

            } catch (Exception exception) {
                // Just log. It is safe for now.
                log.warn("Uncaught exception is detected: {}", exception.getMessage());
                log.debug("Uncaught exception is detected (full stack trace): ", exception);
            }
        }
    }

    /**
     * Helper method to decide whether L2 Interface group or L2 Unfiltered group needs to be created.
     * L2 Unfiltered group will be created if meta has VlanIdCriterion with VlanId.ANY, and
     * treatment has set Vlan ID action.
     *
     * @param treatment  treatment passed in by the application as part of the nextObjective
     * @param meta       metadata passed in by the application as part of the nextObjective
     * @return true if L2 Unfiltered group needs to be created, false otherwise.
     */
    public static boolean createUnfiltered(TrafficTreatment treatment, TrafficSelector meta) {
        if (meta == null || treatment == null) {
            return false;
        }
        VlanIdCriterion vlanIdCriterion = (VlanIdCriterion) meta.getCriterion(Criterion.Type.VLAN_VID);
        if (vlanIdCriterion == null || !vlanIdCriterion.vlanId().equals(VlanId.ANY)) {
            return false;
        }

        return treatment.allInstructions().stream()
                .filter(i -> (i.type() == Instruction.Type.L2MODIFICATION
                        && ((L2ModificationInstruction) i).subtype() == L2ModificationInstruction.L2SubType.VLAN_ID))
                .count() == 1;
    }

    /**
     * Returns a hash as the L3 Unicast Group Key.
     *
     * Keep the lower 6-bit for port since port number usually smaller than 64.
     * Hash other information into remaining 28 bits.
     *
     * @param deviceId Device ID
     * @param vlanId vlan ID
     * @param portNumber Port number
     * @return L3 unicast group key
     */
    public static int doubleVlanL3UnicastGroupKey(DeviceId deviceId, VlanId vlanId, long portNumber) {
        int portLowerBits = (int) portNumber & PORT_LOWER_BITS_MASK;
        long portHigherBits = portNumber & PORT_HIGHER_BITS_MASK;
        int hash = Objects.hash(deviceId, portHigherBits, vlanId);
        return  L3_UNICAST_TYPE | (TYPE_MASK & hash << 6) | portLowerBits;
    }

    public static int doubleVlanL3UnicastGroupId(VlanId vlanId, long portNum) {
        // <4bits-2><1bit-1><12bits-vlanId><15bits-portId>
        return L3_UNICAST_TYPE | 1 << 27 | (vlanId.toShort() << 15) | (int) (portNum & 0x7FFF);
    }

}
