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

package org.onosproject.driver.pipeline;

import com.google.common.collect.Lists;
import org.onlab.packet.VlanId;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.GroupId;
import org.onosproject.driver.extensions.Ofdpa3PushCw;
import org.onosproject.driver.extensions.Ofdpa3PushL2Header;
import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.flow.instructions.Instruction;
import org.onosproject.net.flow.instructions.L2ModificationInstruction;
import org.onosproject.net.flow.instructions.L3ModificationInstruction;
import org.onosproject.net.flowobjective.NextObjective;
import org.onosproject.net.flowobjective.ObjectiveError;
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.ArrayDeque;
import java.util.Collections;
import java.util.Deque;
import java.util.List;

import static org.onosproject.driver.pipeline.Ofdpa2GroupHandler.OfdpaMplsGroupSubType.*;
import static org.onosproject.net.flow.instructions.L3ModificationInstruction.L3SubType.TTL_OUT;
import static org.onosproject.net.group.GroupDescription.Type.INDIRECT;
import static org.slf4j.LoggerFactory.getLogger;

/**
 * Group handler for OFDPA2 pipeline.
 */
public class Ofdpa3GroupHandler extends Ofdpa2GroupHandler {

    private static final int PW_INTERNAL_VLAN = 4094;
    private static final int MAX_DEPTH_UNPROTECTED_PW = 3;

    private final Logger log = getLogger(getClass());

    @Override
    protected GroupInfo createL2L3Chain(TrafficTreatment treatment, int nextId,
                                        ApplicationId appId, boolean mpls,
                                        TrafficSelector meta) {
        return createL2L3ChainInternal(treatment, nextId, appId, mpls, meta, false);
    }

    @Override
    protected void processPwNextObjective(NextObjective nextObjective) {
        TrafficTreatment treatment = nextObjective.next().iterator().next();
        Deque<GroupKey> gkeyChain = new ArrayDeque<>();
        GroupChainElem groupChainElem;
        GroupKey groupKey;
        GroupDescription groupDescription;
        // Now we separate the mpls actions from the l2/l3 actions
        TrafficTreatment.Builder l2L3Treatment = DefaultTrafficTreatment.builder();
        TrafficTreatment.Builder mplsTreatment = DefaultTrafficTreatment.builder();
        createL2L3AndMplsTreatments(treatment, l2L3Treatment, mplsTreatment);
        // We create the chain from mpls intf group to
        // l2 intf group.
        GroupInfo groupInfo = createL2L3ChainInternal(
                l2L3Treatment.build(),
                nextObjective.id(),
                nextObjective.appId(),
                true,
                nextObjective.meta(),
                false
        );
        if (groupInfo == null) {
            log.error("Could not process nextObj={} in dev:{}", nextObjective.id(), deviceId);
            Ofdpa2Pipeline.fail(nextObjective, ObjectiveError.GROUPINSTALLATIONFAILED);
            return;
        }
        // We update the chain with the last two groups;
        gkeyChain.addFirst(groupInfo.getInnerMostGroupDesc().appCookie());
        gkeyChain.addFirst(groupInfo.getNextGroupDesc().appCookie());
        // We retrieve also all mpls instructions.
        List<List<Instruction>> mplsInstructionSets = Lists.newArrayList();
        List<Instruction> mplsInstructionSet = Lists.newArrayList();
        L3ModificationInstruction l3Ins;
        for (Instruction ins : treatment.allInstructions()) {
            // Each mpls instruction set is delimited by a
            // copy ttl outward action.
            mplsInstructionSet.add(ins);
            if (ins.type() == Instruction.Type.L3MODIFICATION) {
                l3Ins = (L3ModificationInstruction) ins;
                if (l3Ins.subtype() == TTL_OUT) {
                    mplsInstructionSets.add(mplsInstructionSet);
                    mplsInstructionSet = Lists.newArrayList();
                }

            }
        }
        if (mplsInstructionSets.size() > MAX_DEPTH_UNPROTECTED_PW) {
            log.error("Next Objective for pseudo wire should have at "
                              + "most {} mpls instruction sets. Next Objective Id:{}",
                      MAX_DEPTH_UNPROTECTED_PW, nextObjective.id());
            Ofdpa2Pipeline.fail(nextObjective, ObjectiveError.BADPARAMS);
            return;
        }
        int nextGid = groupInfo.getNextGroupDesc().givenGroupId();
        int index;
        // We create the mpls tunnel label groups.
        // In this case we need to use also the
        // tunnel label group 2;
        if (mplsInstructionSets.size() == MAX_DEPTH_UNPROTECTED_PW) {
            // We deal with the label 2 group.
            index = getNextAvailableIndex();
            groupDescription = createMplsTunnelLabelGroup(
                    nextGid,
                    MPLS_TUNNEL_LABEL_2,
                    index,
                    mplsInstructionSets.get(2),
                    nextObjective.appId()
            );
            groupKey = new DefaultGroupKey(
                    Ofdpa2Pipeline.appKryo.serialize(index)
            );
            // We update the chain.
            groupChainElem = new GroupChainElem(groupDescription, 1, false);
            updatePendingGroups(
                    groupInfo.getNextGroupDesc().appCookie(),
                    groupChainElem
            );
            gkeyChain.addFirst(groupKey);
            // We have to create tunnel label group and
            // l2 vpn group before to send the inner most
            // group. We update the nextGid.
            nextGid = groupDescription.givenGroupId();
            groupInfo = new GroupInfo(groupInfo.getInnerMostGroupDesc(), groupDescription);

            log.debug("Trying Label 2 Group: device:{} gid:{} gkey:{} nextId:{}",
                      deviceId, Integer.toHexString(nextGid),
                      groupKey, nextObjective.id());
        }
        // We deal with the label 1 group.
        index = getNextAvailableIndex();
        groupDescription = createMplsTunnelLabelGroup(
                nextGid,
                MPLS_TUNNEL_LABEL_1,
                index,
                mplsInstructionSets.get(1),
                nextObjective.appId()
        );
        groupKey = new DefaultGroupKey(
                Ofdpa2Pipeline.appKryo.serialize(index)
        );
        groupChainElem = new GroupChainElem(groupDescription, 1, false);
        updatePendingGroups(
                groupInfo.getNextGroupDesc().appCookie(),
                groupChainElem
        );
        gkeyChain.addFirst(groupKey);
        // We have to create the l2 vpn group before
        // to send the inner most group.
        nextGid = groupDescription.givenGroupId();
        groupInfo = new GroupInfo(groupInfo.getInnerMostGroupDesc(), groupDescription);

        log.debug("Trying Label 1 Group: device:{} gid:{} gkey:{} nextId:{}",
                  deviceId, Integer.toHexString(nextGid),
                  groupKey, nextObjective.id());
        // Finally we create the l2 vpn group.
        index = getNextAvailableIndex();
        groupDescription = createMplsL2VpnGroup(
                nextGid,
                index,
                mplsInstructionSets.get(0),
                nextObjective.appId()
        );
        groupKey = new DefaultGroupKey(
                Ofdpa2Pipeline.appKryo.serialize(index)
        );
        groupChainElem = new GroupChainElem(groupDescription, 1, false);
        updatePendingGroups(
                groupInfo.getNextGroupDesc().appCookie(),
                groupChainElem
        );
        gkeyChain.addFirst(groupKey);
        OfdpaNextGroup ofdpaGrp = new OfdpaNextGroup(
                Collections.singletonList(gkeyChain),
                nextObjective
        );
        updatePendingNextObjective(groupKey, ofdpaGrp);

        log.debug("Trying L2 Vpn Group: device:{} gid:{} gkey:{} nextId:{}",
                  deviceId, Integer.toHexString(nextGid),
                  groupKey, nextObjective.id());
        // Finally we send the innermost group.
        log.debug("Sending innermost group {} in group chain on device {} ",
                  Integer.toHexString(groupInfo.getInnerMostGroupDesc().givenGroupId()), deviceId);
        groupService.addGroup(groupInfo.getInnerMostGroupDesc());
    }

    /**
     * Helper method to create a mpls tunnel label group.
     *
     * @param nextGroupId the next group in the chain
     * @param subtype the mpls tunnel label group subtype
     * @param index the index of the group
     * @param instructions the instructions to push
     * @param applicationId the application id
     * @return the group description
     */
    private GroupDescription createMplsTunnelLabelGroup(int nextGroupId,
                                                          OfdpaMplsGroupSubType subtype,
                                                          int index,
                                                          List<Instruction> instructions,
                                                          ApplicationId applicationId) {
        TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
        // We add all the instructions.
        instructions.forEach(treatment::add);
        // We point the group to the next group.
        treatment.group(new GroupId(nextGroupId));
        GroupBucket groupBucket = DefaultGroupBucket
                .createIndirectGroupBucket(treatment.build());
        // Finally we build the group description.
        int groupId = makeMplsLabelGroupId(subtype, index);
        GroupKey groupKey = new DefaultGroupKey(
                Ofdpa2Pipeline.appKryo.serialize(index)
        );
        return new DefaultGroupDescription(
                deviceId,
                INDIRECT,
                new GroupBuckets(Collections.singletonList(groupBucket)),
                groupKey,
                groupId,
                applicationId
        );
    }

    /**
     * Helper method to create a mpls l2 vpn group.
     *
     * @param nextGroupId the next group in the chain
     * @param index the index of the group
     * @param instructions the instructions to push
     * @param applicationId the application id
     * @return the group description
     */
    private GroupDescription createMplsL2VpnGroup(int nextGroupId,
                                                    int index,
                                                    List<Instruction> instructions,
                                                    ApplicationId applicationId) {
        TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
        // We add the extensions and the instructions.
        treatment.extension(new Ofdpa3PushL2Header(), deviceId);
        treatment.pushVlan();
        instructions.forEach(treatment::add);
        treatment.extension(new Ofdpa3PushCw(), deviceId);
        // We point the group to the next group.
        treatment.group(new GroupId(nextGroupId));
        GroupBucket groupBucket = DefaultGroupBucket
                .createIndirectGroupBucket(treatment.build());
        // Finally we build the group description.
        int groupId = makeMplsLabelGroupId(L2_VPN, index);
        GroupKey groupKey = new DefaultGroupKey(
                Ofdpa2Pipeline.appKryo.serialize(index)
        );
        return new DefaultGroupDescription(
                deviceId,
                INDIRECT,
                new GroupBuckets(Collections.singletonList(groupBucket)),
                groupKey,
                groupId,
                applicationId
        );
    }

    /**
     * Helper method for dividing the l2/l3 instructions from the mpls
     * instructions.
     *
     * @param treatment the treatment to analyze
     * @param l2L3Treatment the l2/l3 treatment builder
     * @param mplsTreatment the mpls treatment builder
     */
    private void createL2L3AndMplsTreatments(TrafficTreatment treatment,
                                               TrafficTreatment.Builder l2L3Treatment,
                                               TrafficTreatment.Builder mplsTreatment) {

        for (Instruction ins : treatment.allInstructions()) {

            if (ins.type() == Instruction.Type.L2MODIFICATION) {
                L2ModificationInstruction l2ins = (L2ModificationInstruction) ins;
                switch (l2ins.subtype()) {
                    // These instructions have to go in the l2/l3 treatment.
                    case ETH_DST:
                    case ETH_SRC:
                    case VLAN_ID:
                    case VLAN_POP:
                        l2L3Treatment.add(ins);
                        break;
                    // These instructions have to go in the mpls treatment.
                    case MPLS_BOS:
                    case DEC_MPLS_TTL:
                    case MPLS_LABEL:
                    case MPLS_PUSH:
                        mplsTreatment.add(ins);
                        break;
                    default:
                        log.warn("Driver does not handle this type of TrafficTreatment"
                                         + " instruction in nextObjectives: {} - {}",
                                 ins.type(), ins);
                        break;
                }
            } else if (ins.type() == Instruction.Type.OUTPUT) {
                // The output goes in the l2/l3 treatment.
                l2L3Treatment.add(ins);
            } else if (ins.type() == Instruction.Type.L3MODIFICATION) {
                 // We support partially the l3 instructions.
                L3ModificationInstruction l3ins = (L3ModificationInstruction) ins;
                switch (l3ins.subtype()) {
                    case TTL_OUT:
                        mplsTreatment.add(ins);
                        break;
                    default:
                        log.warn("Driver does not handle this type of TrafficTreatment"
                                         + " instruction in nextObjectives: {} - {}",
                                 ins.type(), ins);
                }

            } else {
                log.warn("Driver does not handle this type of TrafficTreatment"
                                 + " instruction in nextObjectives: {} - {}",
                         ins.type(), ins);
            }
        }
        // We add in a transparent way the set vlan to 4094.
        l2L3Treatment.setVlanId(VlanId.vlanId((short) PW_INTERNAL_VLAN));
    }
    // TODO Introduce in the future an inner class to return two treatments
}
