/*
 * 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.impl.behaviour;

import com.google.common.collect.ImmutableMap;
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.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.onosproject.pipelines.fabric.FabricConstants;

import java.util.List;
import java.util.stream.Collectors;

import static java.lang.String.format;
import static org.onosproject.net.flow.instructions.Instruction.Type.OUTPUT;
import static org.onosproject.net.flow.instructions.L2ModificationInstruction.L2SubType.ETH_DST;
import static org.onosproject.net.flow.instructions.L2ModificationInstruction.L2SubType.ETH_SRC;
import static org.onosproject.net.flow.instructions.L2ModificationInstruction.L2SubType.MPLS_LABEL;
import static org.onosproject.net.flow.instructions.L2ModificationInstruction.L2SubType.MPLS_PUSH;
import static org.onosproject.net.flow.instructions.L2ModificationInstruction.L2SubType.VLAN_ID;
import static org.onosproject.net.flow.instructions.L2ModificationInstruction.L2SubType.VLAN_POP;
import static org.onosproject.net.flow.instructions.L2ModificationInstruction.L2SubType.VLAN_PUSH;
import static org.onosproject.pipelines.fabric.impl.behaviour.FabricUtils.instruction;
import static org.onosproject.pipelines.fabric.impl.behaviour.FabricUtils.l2Instruction;
import static org.onosproject.pipelines.fabric.impl.behaviour.FabricUtils.l2Instructions;

/**
 * Treatment translation logic.
 */
final class FabricTreatmentInterpreter {

    private final FabricCapabilities capabilities;
    private static final ImmutableMap<PiTableId, PiActionId> NOP_ACTIONS =
            ImmutableMap.<PiTableId, PiActionId>builder()
                    .put(FabricConstants.FABRIC_INGRESS_FILTERING_INGRESS_PORT_VLAN,
                         FabricConstants.FABRIC_INGRESS_FILTERING_PERMIT)
                    .put(FabricConstants.FABRIC_INGRESS_FORWARDING_ROUTING_V4,
                         FabricConstants.FABRIC_INGRESS_FORWARDING_NOP_ROUTING_V4)
                    .put(FabricConstants.FABRIC_INGRESS_ACL_ACL,
                         FabricConstants.FABRIC_INGRESS_ACL_NOP_ACL)
                    .put(FabricConstants.FABRIC_EGRESS_EGRESS_NEXT_EGRESS_VLAN,
                         FabricConstants.FABRIC_EGRESS_EGRESS_NEXT_POP_VLAN)
                    .build();


    FabricTreatmentInterpreter(FabricCapabilities capabilities) {
        this.capabilities = capabilities;
    }

    static PiAction mapFilteringTreatment(TrafficTreatment treatment, PiTableId tableId)
            throws PiInterpreterException {

        if (!tableId.equals(FabricConstants.FABRIC_INGRESS_FILTERING_INGRESS_PORT_VLAN)) {
            // Mapping for other tables of the filtering block must be handled
            // in the pipeliner.
            tableException(tableId);
        }

        // VLAN_POP action is equivalent to the permit action (VLANs pop is done anyway)
        if (isNoAction(treatment) || isFilteringPopAction(treatment)) {
            // Permit action if table is ingress_port_vlan;
            return nop(tableId);
        }

        final ModVlanIdInstruction setVlanInst = (ModVlanIdInstruction) l2InstructionOrFail(
                treatment, VLAN_ID, tableId);
        return PiAction.builder()
                .withId(FabricConstants.FABRIC_INGRESS_FILTERING_PERMIT_WITH_INTERNAL_VLAN)
                .withParameter(new PiActionParam(
                        FabricConstants.VLAN_ID, setVlanInst.vlanId().toShort()))
                .build();
    }


    static PiAction mapForwardingTreatment(TrafficTreatment treatment, PiTableId tableId)
            throws PiInterpreterException {
        if (isNoAction(treatment)) {
            return nop(tableId);
        }
        treatmentException(
                tableId, treatment,
                "supports mapping only for empty/no-action treatments");
        return null;
    }

    PiAction mapNextTreatment(TrafficTreatment treatment, PiTableId tableId)
            throws PiInterpreterException {
        if (tableId == FabricConstants.FABRIC_INGRESS_NEXT_NEXT_VLAN) {
            return mapNextVlanTreatment(treatment, tableId);
        } else if (tableId == FabricConstants.FABRIC_INGRESS_NEXT_HASHED) {
            return mapNextHashedOrSimpleTreatment(treatment, tableId, false);
        } else if (tableId == FabricConstants.FABRIC_INGRESS_NEXT_SIMPLE) {
            return mapNextHashedOrSimpleTreatment(treatment, tableId, true);
        } else if (tableId == FabricConstants.FABRIC_INGRESS_NEXT_XCONNECT) {
            return mapNextXconnect(treatment, tableId);
        }
        throw new PiInterpreterException(format(
                "Treatment mapping not supported for table '%s'", tableId));
    }

    private PiAction mapNextVlanTreatment(TrafficTreatment treatment, PiTableId tableId)
            throws PiInterpreterException {
        final List<ModVlanIdInstruction> modVlanIdInst = l2InstructionsOrFail(treatment, VLAN_ID, tableId)
                .stream().map(i -> (ModVlanIdInstruction) i).collect(Collectors.toList());
        if (modVlanIdInst.size() == 1) {
            return PiAction.builder().withId(FabricConstants.FABRIC_INGRESS_NEXT_SET_VLAN)
                    .withParameter(new PiActionParam(
                            FabricConstants.VLAN_ID,
                            modVlanIdInst.get(0).vlanId().toShort()))
                    .build();
        }
        if (modVlanIdInst.size() == 2 && capabilities.supportDoubleVlanTerm()) {
            return PiAction.builder()
                    .withId(FabricConstants.FABRIC_INGRESS_NEXT_SET_DOUBLE_VLAN)
                    .withParameter(new PiActionParam(
                            FabricConstants.INNER_VLAN_ID,
                            modVlanIdInst.get(0).vlanId().toShort()))
                    .withParameter(new PiActionParam(
                            FabricConstants.OUTER_VLAN_ID,
                            modVlanIdInst.get(1).vlanId().toShort()))
                    .build();
        }
        throw new PiInterpreterException("Too many VLAN instructions");
    }

    private static PiAction mapNextHashedOrSimpleTreatment(
            TrafficTreatment treatment, PiTableId tableId, boolean simple)
            throws PiInterpreterException {
        // Provide mapping for output_hashed, routing_hashed, and
        // mpls_routing_hashed. multicast_hashed can only be invoked with
        // PiAction, hence no mapping. outPort required for all actions. Presence
        // of other instructions will determine which action to map to.
        final PortNumber outPort = ((OutputInstruction) instructionOrFail(
                treatment, OUTPUT, tableId)).port();
        final ModEtherInstruction ethDst = (ModEtherInstruction) l2Instruction(
                treatment, ETH_DST);
        final ModEtherInstruction ethSrc = (ModEtherInstruction) l2Instruction(
                treatment, ETH_SRC);
        final Instruction mplsPush = l2Instruction(
                treatment, MPLS_PUSH);
        final ModMplsLabelInstruction mplsLabel = (ModMplsLabelInstruction) l2Instruction(
                treatment, MPLS_LABEL);

        final PiAction.Builder actionBuilder = PiAction.builder()
                .withParameter(new PiActionParam(FabricConstants.PORT_NUM, outPort.toLong()));

        if (ethDst != null && ethSrc != null) {
            actionBuilder.withParameter(new PiActionParam(
                    FabricConstants.SMAC, ethSrc.mac().toBytes()));
            actionBuilder.withParameter(new PiActionParam(
                    FabricConstants.DMAC, ethDst.mac().toBytes()));
            if (mplsLabel != null) {
                // mpls_routing_hashed
                return actionBuilder
                        .withParameter(new PiActionParam(FabricConstants.LABEL, mplsLabel.label().toInt()))
                        .withId(simple ? FabricConstants.FABRIC_INGRESS_NEXT_MPLS_ROUTING_SIMPLE
                                        : FabricConstants.FABRIC_INGRESS_NEXT_MPLS_ROUTING_HASHED)
                        .build();
            } else {
                // routing_hashed
                return actionBuilder
                        .withId(simple ? FabricConstants.FABRIC_INGRESS_NEXT_ROUTING_SIMPLE
                                        : FabricConstants.FABRIC_INGRESS_NEXT_ROUTING_HASHED)
                        .build();
            }
        } else {
            // output_hashed
            return actionBuilder
                    .withId(simple ? FabricConstants.FABRIC_INGRESS_NEXT_OUTPUT_SIMPLE
                                    : FabricConstants.FABRIC_INGRESS_NEXT_OUTPUT_HASHED)
                    .build();
        }
    }

    private static PiAction mapNextXconnect(
            TrafficTreatment treatment, PiTableId tableId)
            throws PiInterpreterException {
        final PortNumber outPort = ((OutputInstruction) instructionOrFail(
                treatment, OUTPUT, tableId)).port();
        return PiAction.builder()
                .withId(FabricConstants.FABRIC_INGRESS_NEXT_OUTPUT_XCONNECT)
                .withParameter(new PiActionParam(
                        FabricConstants.PORT_NUM, outPort.toLong()))
                .build();
    }

    static PiAction mapAclTreatment(TrafficTreatment treatment, PiTableId tableId)
            throws PiInterpreterException {
        if (isNoAction(treatment)) {
            return nop(tableId);
        }
        treatmentException(
                tableId, treatment,
                "unsupported treatment");

        // This function will never return null
        return null;
    }


    static PiAction mapEgressNextTreatment(
            TrafficTreatment treatment, PiTableId tableId)
            throws PiInterpreterException {
        L2ModificationInstruction pushVlan = l2Instruction(treatment, VLAN_PUSH);
        if (pushVlan != null) {
            return PiAction.builder()
                    .withId(FabricConstants.FABRIC_EGRESS_EGRESS_NEXT_PUSH_VLAN)
                    .build();
        }
        l2InstructionOrFail(treatment, VLAN_POP, tableId);
        return PiAction.builder()
                .withId(FabricConstants.FABRIC_EGRESS_EGRESS_NEXT_POP_VLAN)
                .build();

    }

    private static PiAction nop(PiTableId tableId) throws PiInterpreterException {
        if (!NOP_ACTIONS.containsKey(tableId)) {
            throw new PiInterpreterException(format("table '%s' doe not specify a nop action", tableId));
        }
        return PiAction.builder().withId(NOP_ACTIONS.get(tableId)).build();
    }

    private static boolean isNoAction(TrafficTreatment treatment) {
        // Empty treatment OR
        // No instructions OR
        // Empty treatment AND writeMetadata
        return treatment.equals(DefaultTrafficTreatment.emptyTreatment()) ||
                treatment.allInstructions().isEmpty() ||
                (treatment.allInstructions().size() == 1 && treatment.writeMetadata() != null);
    }

    private static boolean isFilteringPopAction(TrafficTreatment treatment) {
        return l2Instruction(treatment, VLAN_POP) != null;
    }

    private static Instruction l2InstructionOrFail(
            TrafficTreatment treatment,
            L2ModificationInstruction.L2SubType subType, PiTableId tableId)
            throws PiInterpreterException {
        final Instruction inst = l2Instruction(treatment, subType);
        if (inst == null) {
            treatmentException(tableId, treatment, format("missing %s instruction", subType));
        }
        return inst;
    }

    private static List<L2ModificationInstruction> l2InstructionsOrFail(
            TrafficTreatment treatment,
            L2ModificationInstruction.L2SubType subType, PiTableId tableId)
            throws PiInterpreterException {
        final List<L2ModificationInstruction> inst = l2Instructions(treatment, subType);
        if (inst == null || inst.isEmpty()) {
            treatmentException(tableId, treatment, format("missing %s instruction", subType));
        }
        return inst;
    }

    private static Instruction instructionOrFail(
            TrafficTreatment treatment, Instruction.Type type, PiTableId tableId)
            throws PiInterpreterException {
        final Instruction inst = instruction(treatment, type);
        if (inst == null) {
            treatmentException(tableId, treatment, format("missing %s instruction", type));
        }
        return inst;
    }

    private static void tableException(PiTableId tableId)
            throws PiInterpreterException {
        throw new PiInterpreterException(format("Table '%s' not supported", tableId));
    }

    private static void treatmentException(
            PiTableId tableId, TrafficTreatment treatment, String explanation)
            throws PiInterpreterException {
        throw new PiInterpreterException(format(
                "Invalid treatment for table '%s', %s: %s", tableId, explanation, treatment));
    }
}
