/*
 * Copyright 2016-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 org.onlab.packet.MacAddress;
import org.onlab.packet.VlanId;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.GroupId;
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.flowobjective.NextObjective;
import org.onosproject.net.group.DefaultGroupBucket;
import org.onosproject.net.group.DefaultGroupDescription;
import org.onosproject.net.group.DefaultGroupKey;
import org.onosproject.net.group.GroupBucket;
import org.onosproject.net.group.GroupBuckets;
import org.onosproject.net.group.GroupDescription;
import org.onosproject.net.group.GroupKey;
import org.slf4j.Logger;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Deque;
import java.util.List;

import static org.onosproject.driver.pipeline.ofdpa.OfdpaGroupHandlerUtility.*;
import static org.slf4j.LoggerFactory.getLogger;

/**
 * Group handler for Open vSwitch OFDPA pipeline.
 */
public class OvsOfdpaGroupHandler extends Ofdpa2GroupHandler {
    private final Logger log = getLogger(getClass());

    @Override
    protected boolean supportCopyTtl() {
        return false;
    }

    @Override
    protected boolean supportSetMplsBos() {
        return false;
    }

    @Override
    protected boolean requireVlanPopBeforeMplsPush() {
        return true;
    }

    @Override
    protected GroupInfo createL2L3Chain(TrafficTreatment treatment, int nextId,
                                        ApplicationId appId, boolean mpls,
                                        TrafficSelector meta) {
        if (createUnfiltered(treatment, meta)) {
            return createUnfilteredL2L3Chain(treatment, nextId, appId);
        }
        // for the l2interface group, get vlan and port info
        // for the outer group, get the src/dst mac, and vlan info
        TrafficTreatment.Builder outerTtb = DefaultTrafficTreatment.builder();
        TrafficTreatment.Builder innerTtb = DefaultTrafficTreatment.builder();
        VlanId vlanid = null;
        long portNum = 0;
        boolean setVlan = false, popVlan = false;
        MacAddress srcMac = MacAddress.ZERO;
        MacAddress dstMac = MacAddress.ZERO;
        for (Instruction ins : treatment.allInstructions()) {
            if (ins.type() == Instruction.Type.L2MODIFICATION) {
                L2ModificationInstruction l2ins = (L2ModificationInstruction) ins;
                switch (l2ins.subtype()) {
                    case ETH_DST:
                        dstMac = ((L2ModificationInstruction.ModEtherInstruction) l2ins).mac();
                        outerTtb.setEthDst(dstMac);
                        break;
                    case ETH_SRC:
                        srcMac = ((L2ModificationInstruction.ModEtherInstruction) l2ins).mac();
                        outerTtb.setEthSrc(srcMac);
                        break;
                    case VLAN_ID:
                        vlanid = ((L2ModificationInstruction.ModVlanIdInstruction) l2ins).vlanId();
                        outerTtb.setVlanId(vlanid);
                        setVlan = true;
                        break;
                    case VLAN_POP:
                        innerTtb.popVlan();
                        popVlan = true;
                        break;
                    case DEC_MPLS_TTL:
                    case MPLS_LABEL:
                    case MPLS_POP:
                    case MPLS_PUSH:
                    case VLAN_PCP:
                    case VLAN_PUSH:
                    default:
                        break;
                }
            } else if (ins.type() == Instruction.Type.OUTPUT) {
                portNum = ((Instructions.OutputInstruction) ins).port().toLong();
                innerTtb.add(ins);
            } else {
                log.debug("Driver does not handle this type of TrafficTreatment"
                        + " instruction in l2l3chain:  {} - {}", ins.type(),
                         ins);
            }
        }

        if (vlanid == null && meta != null) {
            // use metadata if available
            Criterion vidCriterion = meta.getCriterion(Criterion.Type.VLAN_VID);
            if (vidCriterion != null) {
                vlanid = ((VlanIdCriterion) vidCriterion).vlanId();
            }
            // if vlan is not set, use the vlan in metadata for outerTtb
            if (vlanid != null && !setVlan) {
                outerTtb.setVlanId(vlanid);
            }
        }

        if (vlanid == null) {
            log.error("Driver cannot process an L2/L3 group chain without "
                              + "egress vlan information for dev: {} port:{}",
                      deviceId, portNum);
            return null;
        }

        if (!setVlan && !popVlan) {
            // untagged outgoing port
            TrafficTreatment.Builder temp = DefaultTrafficTreatment.builder();
            temp.popVlan();
            innerTtb.build().allInstructions().forEach(i -> temp.add(i));
            innerTtb = temp;
        }

        // assemble information for ofdpa l2interface group
        int l2groupId = L2_INTERFACE_TYPE | (vlanid.toShort() << 16) | (int) portNum;
        // a globally unique groupkey that is different for ports in the same device,
        // but different for the same portnumber on different devices. Also different
        // for the various group-types created out of the same next objective.
        int l2gk = l2InterfaceGroupKey(deviceId, vlanid, portNum);
        final GroupKey l2groupkey = new DefaultGroupKey(Ofdpa2Pipeline.appKryo.serialize(l2gk));

        // assemble information for outer group
        GroupDescription outerGrpDesc = null;
        if (mpls) {
            // outer group is MPLSInteface
            int mplsInterfaceIndex = getNextAvailableIndex();
            int mplsgroupId = MPLS_INTERFACE_TYPE | (SUBTYPE_MASK & mplsInterfaceIndex);
            final GroupKey mplsgroupkey = new DefaultGroupKey(
                    Ofdpa2Pipeline.appKryo.serialize(mplsInterfaceIndex));
            outerTtb.group(new GroupId(l2groupId));
            // create the mpls-interface group description to wait for the
            // l2 interface group to be processed
            GroupBucket mplsinterfaceGroupBucket =
                    DefaultGroupBucket.createIndirectGroupBucket(outerTtb.build());
            outerGrpDesc = new DefaultGroupDescription(
                    deviceId,
                    GroupDescription.Type.INDIRECT,
                    new GroupBuckets(Collections.singletonList(
                            mplsinterfaceGroupBucket)),
                    mplsgroupkey,
                    mplsgroupId,
                    appId);
            log.debug("Trying MPLS-Interface: device:{} gid:{} gkey:{} nextid:{}",
                      deviceId, Integer.toHexString(mplsgroupId),
                      mplsgroupkey, nextId);
        } else {
            // outer group is L3Unicast
            int l3unicastIndex = getNextAvailableIndex();
            int l3groupId = L3_UNICAST_TYPE | (TYPE_MASK & l3unicastIndex);
            final GroupKey l3groupkey = new DefaultGroupKey(
                    Ofdpa2Pipeline.appKryo.serialize(l3unicastIndex));
            outerTtb.group(new GroupId(l2groupId));
            // create the l3unicast group description to wait for the
            // l2 interface group to be processed
            GroupBucket l3unicastGroupBucket =
                    DefaultGroupBucket.createIndirectGroupBucket(outerTtb.build());
            outerGrpDesc = new DefaultGroupDescription(
                    deviceId,
                    GroupDescription.Type.INDIRECT,
                    new GroupBuckets(Collections.singletonList(
                            l3unicastGroupBucket)),
                    l3groupkey,
                    l3groupId,
                    appId);
            log.debug("Trying L3Unicast: device:{} gid:{} gkey:{} nextid:{}",
                      deviceId, Integer.toHexString(l3groupId),
                      l3groupkey, nextId);
        }

        // store l2groupkey with the groupChainElem for the outer-group that depends on it
        GroupChainElem gce = new GroupChainElem(outerGrpDesc,
                                                1,
                                                false,
                                                deviceId);
        updatePendingGroups(l2groupkey, gce);

        // create group description for the inner l2interfacegroup
        GroupBucket l2InterfaceGroupBucket =
                DefaultGroupBucket.createIndirectGroupBucket(innerTtb.build());
        GroupDescription l2groupDescription =
                new DefaultGroupDescription(
                        deviceId,
                        GroupDescription.Type.INDIRECT,
                        new GroupBuckets(Collections.singletonList(
                                l2InterfaceGroupBucket)),
                        l2groupkey,
                        l2groupId,
                        appId);
        log.debug("Trying L2Interface: device:{} gid:{} gkey:{} nextId:{}",
                  deviceId, Integer.toHexString(l2groupId),
                  l2groupkey, nextId);
        return new GroupInfo(l2groupDescription, outerGrpDesc);
    }

    /**
     * In OFDPA2 we do not support the MPLS-ECMP, while we do in
     * Open vSwitch implementation.
     *
     * @param nextObjective the hashed next objective to support.
     */
    @Override
    protected void processHashedNextObjective(NextObjective nextObjective) {
        // The case for 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 && OfdpaPipelineUtility.isNotMplsBos(metaSelector)) {
            // storage for all group keys in the chain of groups created
            List<Deque<GroupKey>> allGroupKeys = new ArrayList<>();
            List<GroupInfo> unsentGroups = new ArrayList<>();
            createHashBucketChains(nextObjective, allGroupKeys, unsentGroups);
            // now we can create the outermost MPLS ECMP group
            List<GroupBucket> mplsEcmpGroupBuckets = new ArrayList<>();
            for (GroupInfo gi : unsentGroups) {
                // create ECMP bucket to point to the outer group
                TrafficTreatment.Builder ttb = DefaultTrafficTreatment.builder();
                ttb.group(new GroupId(gi.nextGroupDesc().givenGroupId()));
                GroupBucket sbucket = DefaultGroupBucket
                        .createSelectGroupBucket(ttb.build());
                mplsEcmpGroupBuckets.add(sbucket);
            }
            int mplsEcmpIndex = getNextAvailableIndex();
            int mplsEcmpGroupId = makeMplsForwardingGroupId(OfdpaMplsGroupSubType.MPLS_ECMP, mplsEcmpIndex);
            GroupKey mplsEmpGroupKey = new DefaultGroupKey(
                    Ofdpa2Pipeline.appKryo.serialize(mplsEcmpIndex)
            );
            GroupDescription mplsEcmpGroupDesc = new DefaultGroupDescription(
                    deviceId,
                    GroupDescription.Type.SELECT,
                    new GroupBuckets(mplsEcmpGroupBuckets),
                    mplsEmpGroupKey,
                    mplsEcmpGroupId,
                    nextObjective.appId()
            );
            GroupChainElem mplsEcmpGce = new GroupChainElem(mplsEcmpGroupDesc,
                                                            mplsEcmpGroupBuckets.size(),
                                                            false,
                                                            deviceId);

            // create objects for local and distributed storage
            allGroupKeys.forEach(gkeyChain -> gkeyChain.addFirst(mplsEmpGroupKey));
            OfdpaNextGroup ofdpaGrp = new OfdpaNextGroup(allGroupKeys, nextObjective);

            // store mplsEcmpGroupKey with the ofdpaGroupChain for the nextObjective
            // that depends on it
            updatePendingNextObjective(mplsEmpGroupKey, ofdpaGrp);

            log.debug("Trying MPLS-ECMP: device:{} gid:{} gkey:{} nextId:{}",
                      deviceId, Integer.toHexString(mplsEcmpGroupId),
                      mplsEmpGroupKey, nextObjective.id());

            // finally we are ready to send the innermost groups
            for (GroupInfo gi : unsentGroups) {
                log.debug("Sending innermost group {} in group chain on device {} ",
                          Integer.toHexString(gi.innerMostGroupDesc().givenGroupId()), deviceId);
                updatePendingGroups(gi.nextGroupDesc().appCookie(), mplsEcmpGce);
                groupService.addGroup(gi.innerMostGroupDesc());
            }
            return;
        }
        super.processHashedNextObjective(nextObjective);
    }

    /**
     * Internal implementation of createL2L3Chain to handle double-tagged vlan.
     * L3UG Group carries dummyVlanId and output port information in its groupId,
     * and does not set vlan.
     * L2UG Group only has OUTPUT instruction.
     *
     * @param treatment that needs to be broken up to create the group chain
     * @param nextId of the next objective that needs this group chain
     * @param appId of the application that sent this next objective
     * @return GroupInfo containing the GroupDescription of the
     *         L2 Unfiltered Interface group(inner) and the GroupDescription of the (outer)
     *         L3Unicast group. May return null if there is an error in processing the chain.
     */
    private GroupInfo createUnfilteredL2L3Chain(TrafficTreatment treatment, int nextId,
                                                ApplicationId appId) {
        // for the l2 unfiltered interface group, get port info
        // for the l3 unicast group, get the src/dst mac, and vlan info
        TrafficTreatment.Builder outerTtb = DefaultTrafficTreatment.builder();
        TrafficTreatment.Builder innerTtb = DefaultTrafficTreatment.builder();
        VlanId vlanId = VlanId.NONE;
        long portNum = 0;
        MacAddress srcMac;
        MacAddress dstMac;
        for (Instruction ins : treatment.allInstructions()) {
            if (ins.type() == Instruction.Type.L2MODIFICATION) {
                L2ModificationInstruction l2ins = (L2ModificationInstruction) ins;
                switch (l2ins.subtype()) {
                    case ETH_DST:
                        dstMac = ((L2ModificationInstruction.ModEtherInstruction) l2ins).mac();
                        outerTtb.setEthDst(dstMac);
                        break;
                    case ETH_SRC:
                        srcMac = ((L2ModificationInstruction.ModEtherInstruction) l2ins).mac();
                        outerTtb.setEthSrc(srcMac);
                        break;
                    case VLAN_ID:
                        vlanId = ((L2ModificationInstruction.ModVlanIdInstruction) l2ins).vlanId();
                        break;
                    default:
                        break;
                }
            } else if (ins.type() == Instruction.Type.OUTPUT) {
                portNum = ((Instructions.OutputInstruction) ins).port().toLong();
                innerTtb.add(ins);
            } else {
                log.debug("Driver does not handle this type of TrafficTreatment"
                                  + " instruction in l2l3chain:  {} - {}", ins.type(),
                          ins);
            }
        }

        // assemble information for ofdpa l2 unfiltered interface group
        int l2groupId = l2UnfilteredGroupId(portNum);
        // a globally unique groupkey that is different for ports in the same device,
        // but different for the same portnumber on different devices. Also different
        // for the various group-types created out of the same next objective.
        int l2gk = l2UnfilteredGroupKey(deviceId, portNum);
        final GroupKey l2groupkey = new DefaultGroupKey(Ofdpa2Pipeline.appKryo.serialize(l2gk));

        // assemble information for outer group (L3Unicast)
        GroupDescription outerGrpDesc;
        int l3groupId = doubleVlanL3UnicastGroupId(vlanId, portNum);
        final GroupKey l3groupkey = new DefaultGroupKey(
                Ofdpa3Pipeline.appKryo.serialize(doubleVlanL3UnicastGroupKey(deviceId, vlanId, portNum)));
        outerTtb.group(new GroupId(l2groupId));
        // create the l3unicast group description to wait for the
        // l2 unfiltered interface group to be processed
        GroupBucket l3unicastGroupBucket =
                DefaultGroupBucket.createIndirectGroupBucket(outerTtb.build());
        outerGrpDesc = new DefaultGroupDescription(
                deviceId,
                GroupDescription.Type.INDIRECT,
                new GroupBuckets(Collections.singletonList(l3unicastGroupBucket)),
                l3groupkey,
                l3groupId,
                appId);
        log.debug("Trying L3Unicast: device:{} gid:{} gkey:{} nextid:{}",
                  deviceId, Integer.toHexString(l3groupId),
                  l3groupkey, nextId);

        // store l2groupkey with the groupChainElem for the outer-group that depends on it
        OfdpaGroupHandlerUtility.GroupChainElem gce = new OfdpaGroupHandlerUtility.GroupChainElem(
                outerGrpDesc, 1, false, deviceId);
        updatePendingGroups(l2groupkey, gce);

        // create group description for the inner l2 unfiltered interface group
        GroupBucket l2InterfaceGroupBucket =
                DefaultGroupBucket.createIndirectGroupBucket(innerTtb.build());
        GroupDescription l2groupDescription =
                new DefaultGroupDescription(deviceId,
                                            GroupDescription.Type.INDIRECT,
                                            new GroupBuckets(Collections.singletonList(l2InterfaceGroupBucket)),
                                            l2groupkey,
                                            l2groupId,
                                            appId);
        log.debug("Trying L2Unfiltered: device:{} gid:{} gkey:{} nextId:{}",
                  deviceId, Integer.toHexString(l2groupId), l2groupkey, nextId);
        return new OfdpaGroupHandlerUtility.GroupInfo(l2groupDescription, outerGrpDesc);
    }

}
