/*
 * 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.pipelines.fabric;

import com.google.common.collect.ImmutableList;
import org.onlab.packet.MacAddress;
import org.onlab.packet.MplsLabel;
import org.onlab.packet.VlanId;
import org.onlab.util.ImmutableByteSequence;
import org.onosproject.net.PortNumber;
import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.TrafficTreatment;
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.ModEtherInstruction;
import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModMplsLabelInstruction;
import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModVlanIdInstruction;
import org.onosproject.net.pi.model.PiActionId;
import org.onosproject.net.pi.model.PiPipelineInterpreter.PiInterpreterException;
import org.onosproject.net.pi.model.PiTableId;
import org.onosproject.net.pi.runtime.PiAction;
import org.onosproject.net.pi.runtime.PiActionParam;
import org.slf4j.Logger;

import java.util.List;

import static java.lang.String.format;
import static org.onosproject.net.flow.instructions.Instruction.Type.L2MODIFICATION;
import static org.onosproject.net.flow.instructions.L2ModificationInstruction.L2SubType.VLAN_ID;
import static org.onosproject.net.flow.instructions.L2ModificationInstruction.L2SubType.VLAN_PUSH;
import static org.onosproject.pipelines.fabric.FabricUtils.getOutputPort;
import static org.slf4j.LoggerFactory.getLogger;


final class FabricTreatmentInterpreter {
    private static final Logger log = getLogger(FabricTreatmentInterpreter.class);
    private static final String INVALID_TREATMENT = "Invalid treatment for %s block [%s]";
    private static final String INVALID_TREATMENT_WITH_EXP = "Invalid treatment for %s block: %s [%s]";
    private static final PiAction NOP = PiAction.builder()
            .withId(FabricConstants.NOP)
            .build();

    private static final PiAction POP_VLAN = PiAction.builder()
            .withId(FabricConstants.FABRIC_EGRESS_EGRESS_NEXT_POP_VLAN)
            .build();

    // Hide default constructor
    protected FabricTreatmentInterpreter() {
    }

    /*
     * In Filtering block, we need to implement these actions:
     * push_internal_vlan
     * set_vlan
     * nop
     *
     * Unsupported, using PiAction directly:
     * set_forwarding_type
     * drop
     */

    static PiAction mapFilteringTreatment(TrafficTreatment treatment, PiTableId tableId)
            throws PiInterpreterException {
        List<Instruction> instructions = treatment.allInstructions();
        Instruction noActInst = Instructions.createNoAction();
        if (instructions.isEmpty() || instructions.contains(noActInst)) {
            // nop
            return NOP;
        }

        L2ModificationInstruction.ModVlanHeaderInstruction pushVlanInst = null;
        ModVlanIdInstruction setVlanInst = null;

        for (Instruction inst : instructions) {
            if (inst.type() == L2MODIFICATION) {
                L2ModificationInstruction l2Inst = (L2ModificationInstruction) inst;

                if (l2Inst.subtype() == VLAN_PUSH) {
                    pushVlanInst = (L2ModificationInstruction.ModVlanHeaderInstruction) l2Inst;

                } else if (l2Inst.subtype() == VLAN_ID) {
                    setVlanInst = (ModVlanIdInstruction) l2Inst;
                }
            }
        }

        if (setVlanInst == null) {
            throw new PiInterpreterException(format(INVALID_TREATMENT, "filtering", treatment));
        }

        VlanId vlanId = setVlanInst.vlanId();
        PiActionParam param = new PiActionParam(FabricConstants.NEW_VLAN_ID,
                                                ImmutableByteSequence.copyFrom(vlanId.toShort()));
        PiActionId actionId;
        if (pushVlanInst != null) {
            // push_internal_vlan
            actionId = FabricConstants.FABRIC_INGRESS_FILTERING_PUSH_INTERNAL_VLAN;
        } else {
            actionId = FabricConstants.FABRIC_INGRESS_FILTERING_SET_VLAN;
        }

        // set_vlan
        return PiAction.builder()
                .withId(actionId)
                .withParameter(param)
                .build();
    }

    /*
     * In forwarding block, we need to implement these actions:
     * send_to_controller
     *
     * Unsupported, using PiAction directly:
     * set_next_id_bridging
     * pop_mpls_and_next
     * set_next_id_unicast_v4
     * set_next_id_multicast_v4
     * set_next_id_acl
     * drop
     * set_next_id_unicast_v6
     * set_next_id_multicast_v6
     */

    public static PiAction mapForwardingTreatment(TrafficTreatment treatment, PiTableId tableId)
            throws PiInterpreterException {
        // Empty treatment, generate table entry with no action
        if (treatment.equals(DefaultTrafficTreatment.emptyTreatment())) {
            return null;
        }
        PortNumber outPort = getOutputPort(treatment);
        if (outPort == null
                || !outPort.equals(PortNumber.CONTROLLER)
                || treatment.allInstructions().size() > 1) {
            throw new PiInterpreterException(
                    format(INVALID_TREATMENT_WITH_EXP,
                           "forwarding", "supports only punt/clone to CPU actions",
                           treatment));
        }

        final PiActionId actionId = treatment.clearedDeferred()
                ? FabricConstants.FABRIC_INGRESS_FORWARDING_PUNT_TO_CPU
                : FabricConstants.FABRIC_INGRESS_FORWARDING_CLONE_TO_CPU;

        return PiAction.builder()
                .withId(actionId)
                .build();
    }

    /*
     * In Next block, we need to implement these actions:
     * set_vlan
     * set_vlan_output
     * output_simple
     * output_hashed
     * l3_routing_simple
     * l3_routing_vlan
     * l3_routing_hashed
     * mpls_routing_v4_simple
     * mpls_routing_v6_simple
     * mpls_routing_v4_hashed
     * mpls_routing_v6_hashed
     *
     * Unsupported, need to find a way to implement it
     *
     * set_mcast_group
     *
     */

    public static PiAction mapNextTreatment(TrafficTreatment treatment, PiTableId tableId)
            throws PiInterpreterException {
        // TODO: refactor this method
        List<Instruction> insts = treatment.allInstructions();
        OutputInstruction outInst = null;
        ModEtherInstruction modEthDstInst = null;
        ModEtherInstruction modEthSrcInst = null;
        ModVlanIdInstruction modVlanIdInst = null;
        ModMplsLabelInstruction modMplsInst = null;

        // TODO: add NextFunctionType (like ForwardingFunctionType)
        for (Instruction inst : insts) {
            switch (inst.type()) {
                case L2MODIFICATION:
                    L2ModificationInstruction l2Inst = (L2ModificationInstruction) inst;
                    switch (l2Inst.subtype()) {
                        case ETH_SRC:
                            modEthSrcInst = (ModEtherInstruction) l2Inst;
                            break;
                        case ETH_DST:
                            modEthDstInst = (ModEtherInstruction) l2Inst;
                            break;
                        case VLAN_ID:
                            modVlanIdInst = (ModVlanIdInstruction) l2Inst;
                            break;
                        case MPLS_LABEL:
                            modMplsInst = (ModMplsLabelInstruction) l2Inst;
                            break;
                        default:
                            log.warn("Unsupported l2 instruction sub type {} [table={}, {}]",
                                     l2Inst.subtype(), tableId, treatment);
                            break;
                    }
                    break;
                case OUTPUT:
                    outInst = (OutputInstruction) inst;
                    break;
                default:
                    log.warn("Unsupported instruction sub type {} [table={}, {}]",
                             inst.type(), tableId, treatment);
                    break;
            }
        }

        if (tableId.equals(FabricConstants.FABRIC_INGRESS_NEXT_VLAN_META) &&
                modVlanIdInst != null) {
            // set_vlan
            VlanId vlanId = modVlanIdInst.vlanId();
            PiActionParam newVlanParam =
                    new PiActionParam(FabricConstants.NEW_VLAN_ID,
                                      ImmutableByteSequence.copyFrom(vlanId.toShort()));
            return PiAction.builder()
                    .withId(FabricConstants.FABRIC_INGRESS_NEXT_SET_VLAN)
                    .withParameter(newVlanParam)
                    .build();
        }

        if (outInst == null) {
            throw new PiInterpreterException(format(INVALID_TREATMENT, "next", treatment));
        }

        short portNum = (short) outInst.port().toLong();
        PiActionParam portNumParam = new PiActionParam(FabricConstants.PORT_NUM,
                                                       ImmutableByteSequence.copyFrom(portNum));
        if (modEthDstInst == null && modEthSrcInst == null) {
            if (modVlanIdInst != null) {
                VlanId vlanId = modVlanIdInst.vlanId();
                PiActionParam vlanParam =
                        new PiActionParam(FabricConstants.NEW_VLAN_ID,
                                          ImmutableByteSequence.copyFrom(vlanId.toShort()));
                // set_vlan_output (simple table)
                return PiAction.builder()
                        .withId(FabricConstants.FABRIC_INGRESS_NEXT_SET_VLAN_OUTPUT)
                        .withParameters(ImmutableList.of(portNumParam, vlanParam))
                        .build();
            } else {
                // output (simple or hashed table)
                return PiAction.builder()
                        .withId(FabricConstants.FABRIC_INGRESS_NEXT_OUTPUT_SIMPLE)
                        .withParameter(portNumParam)
                        .build();
            }
        }

        if (modEthDstInst != null && modEthSrcInst != null) {
            MacAddress srcMac = modEthSrcInst.mac();
            MacAddress dstMac = modEthDstInst.mac();
            PiActionParam srcMacParam = new PiActionParam(FabricConstants.SMAC,
                                                          ImmutableByteSequence.copyFrom(srcMac.toBytes()));
            PiActionParam dstMacParam = new PiActionParam(FabricConstants.DMAC,
                                                          ImmutableByteSequence.copyFrom(dstMac.toBytes()));

            if (modMplsInst != null) {
                // MPLS routing
                MplsLabel mplsLabel = modMplsInst.label();
                try {
                    ImmutableByteSequence mplsValue =
                            ImmutableByteSequence.copyFrom(mplsLabel.toInt()).fit(20);
                    PiActionParam mplsParam = new PiActionParam(FabricConstants.LABEL, mplsValue);

                    PiActionId actionId;
                    // FIXME: finds a way to determine v4 or v6
                    if (tableId.equals(FabricConstants.FABRIC_INGRESS_NEXT_SIMPLE)) {
                        actionId = FabricConstants.FABRIC_INGRESS_NEXT_MPLS_ROUTING_V4_SIMPLE;
                    } else if (tableId.equals(FabricConstants.FABRIC_INGRESS_NEXT_HASHED)) {
                        actionId = FabricConstants.FABRIC_INGRESS_NEXT_MPLS_ROUTING_V4_HASHED;
                    } else {
                        throw new PiInterpreterException(format(INVALID_TREATMENT, "next", treatment));
                    }

                    return PiAction.builder()
                            .withId(actionId)
                            .withParameters(ImmutableList.of(portNumParam,
                                                             srcMacParam,
                                                             dstMacParam,
                                                             mplsParam))
                            .build();
                } catch (ImmutableByteSequence.ByteSequenceTrimException e) {
                    // Basically this won't happened because we already limited
                    // size of mpls value to 20 bits (0xFFFFF)
                    throw new PiInterpreterException(format(INVALID_TREATMENT, "next", treatment));
                }
            }

            if (modVlanIdInst != null) {
                VlanId vlanId = modVlanIdInst.vlanId();
                PiActionParam vlanParam =
                        new PiActionParam(FabricConstants.NEW_VLAN_ID,
                                          ImmutableByteSequence.copyFrom(vlanId.toShort()));
                // L3 routing and set VLAN
                return PiAction.builder()
                        .withId(FabricConstants.FABRIC_INGRESS_NEXT_L3_ROUTING_VLAN)
                        .withParameters(ImmutableList.of(srcMacParam, dstMacParam, portNumParam, vlanParam))
                        .build();
            } else {
                PiActionId actionId;
                if (tableId.equals(FabricConstants.FABRIC_INGRESS_NEXT_SIMPLE)) {
                    actionId = FabricConstants.FABRIC_INGRESS_NEXT_L3_ROUTING_SIMPLE;
                } else if (tableId.equals(FabricConstants.FABRIC_INGRESS_NEXT_HASHED)) {
                    actionId = FabricConstants.FABRIC_INGRESS_NEXT_L3_ROUTING_HASHED;
                } else {
                    throw new PiInterpreterException(format(INVALID_TREATMENT, "next", treatment));
                }

                // L3 routing
                return PiAction.builder()
                        .withId(actionId)
                        .withParameters(ImmutableList.of(portNumParam,
                                                         srcMacParam,
                                                         dstMacParam))
                        .build();
            }
        }

        throw new PiInterpreterException(format(INVALID_TREATMENT, "next", treatment));
    }

    /*
     * pop_vlan
     */
    public static PiAction mapEgressNextTreatment(TrafficTreatment treatment, PiTableId tableId) {
        // Pop VLAN action for now, may add new action to this control block in the future.
        return treatment.allInstructions()
                .stream()
                .filter(inst -> inst.type() == Instruction.Type.L2MODIFICATION)
                .map(inst -> (L2ModificationInstruction) inst)
                .filter(inst -> inst.subtype() == L2ModificationInstruction.L2SubType.VLAN_POP)
                .findFirst()
                .map(inst -> POP_VLAN)
                .orElse(NOP);
    }
}
