/*
 * Copyright 2021-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.upf;

import org.apache.commons.lang3.tuple.Pair;
import org.onlab.packet.Ip4Address;
import org.onlab.util.ImmutableByteSequence;
import org.onosproject.core.ApplicationId;
import org.onosproject.net.DeviceId;
import org.onosproject.net.behaviour.upf.ForwardingActionRule;
import org.onosproject.net.behaviour.upf.GtpTunnel;
import org.onosproject.net.behaviour.upf.PacketDetectionRule;
import org.onosproject.net.behaviour.upf.UpfInterface;
import org.onosproject.net.behaviour.upf.UpfProgrammableException;
import org.onosproject.net.flow.DefaultFlowRule;
import org.onosproject.net.flow.DefaultTrafficSelector;
import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.FlowRule;
import org.onosproject.net.flow.criteria.PiCriterion;
import org.onosproject.net.pi.model.PiActionId;
import org.onosproject.net.pi.model.PiTableId;
import org.onosproject.net.pi.runtime.PiAction;
import org.onosproject.net.pi.runtime.PiActionParam;
import org.onosproject.net.pi.runtime.PiTableAction;

import java.util.Arrays;

import static org.onosproject.pipelines.fabric.FabricConstants.CTR_ID;
import static org.onosproject.pipelines.fabric.FabricConstants.DROP;
import static org.onosproject.pipelines.fabric.FabricConstants.FABRIC_INGRESS_SPGW_DOWNLINK_PDRS;
import static org.onosproject.pipelines.fabric.FabricConstants.FABRIC_INGRESS_SPGW_FARS;
import static org.onosproject.pipelines.fabric.FabricConstants.FABRIC_INGRESS_SPGW_INTERFACES;
import static org.onosproject.pipelines.fabric.FabricConstants.FABRIC_INGRESS_SPGW_LOAD_DBUF_FAR;
import static org.onosproject.pipelines.fabric.FabricConstants.FABRIC_INGRESS_SPGW_LOAD_IFACE;
import static org.onosproject.pipelines.fabric.FabricConstants.FABRIC_INGRESS_SPGW_LOAD_NORMAL_FAR;
import static org.onosproject.pipelines.fabric.FabricConstants.FABRIC_INGRESS_SPGW_LOAD_PDR;
import static org.onosproject.pipelines.fabric.FabricConstants.FABRIC_INGRESS_SPGW_LOAD_PDR_QOS;
import static org.onosproject.pipelines.fabric.FabricConstants.FABRIC_INGRESS_SPGW_LOAD_TUNNEL_FAR;
import static org.onosproject.pipelines.fabric.FabricConstants.FABRIC_INGRESS_SPGW_UPLINK_PDRS;
import static org.onosproject.pipelines.fabric.FabricConstants.FAR_ID;
import static org.onosproject.pipelines.fabric.FabricConstants.HDR_FAR_ID;
import static org.onosproject.pipelines.fabric.FabricConstants.HDR_GTPU_IS_VALID;
import static org.onosproject.pipelines.fabric.FabricConstants.HDR_HAS_QFI;
import static org.onosproject.pipelines.fabric.FabricConstants.HDR_IPV4_DST_ADDR;
import static org.onosproject.pipelines.fabric.FabricConstants.HDR_QFI;
import static org.onosproject.pipelines.fabric.FabricConstants.HDR_TEID;
import static org.onosproject.pipelines.fabric.FabricConstants.HDR_TUNNEL_IPV4_DST;
import static org.onosproject.pipelines.fabric.FabricConstants.HDR_UE_ADDR;
import static org.onosproject.pipelines.fabric.FabricConstants.NEEDS_GTPU_DECAP;
import static org.onosproject.pipelines.fabric.FabricConstants.NEEDS_QFI_PUSH;
import static org.onosproject.pipelines.fabric.FabricConstants.NOTIFY_CP;
import static org.onosproject.pipelines.fabric.FabricConstants.QFI;
import static org.onosproject.pipelines.fabric.FabricConstants.SLICE_ID;
import static org.onosproject.pipelines.fabric.FabricConstants.SRC_IFACE;
import static org.onosproject.pipelines.fabric.FabricConstants.TC;
import static org.onosproject.pipelines.fabric.FabricConstants.TEID;
import static org.onosproject.pipelines.fabric.FabricConstants.TUNNEL_DST_ADDR;
import static org.onosproject.pipelines.fabric.FabricConstants.TUNNEL_SRC_ADDR;
import static org.onosproject.pipelines.fabric.FabricConstants.TUNNEL_SRC_PORT;
import static org.onosproject.pipelines.fabric.impl.behaviour.Constants.DEFAULT_QFI;
import static org.onosproject.pipelines.fabric.impl.behaviour.Constants.DEFAULT_SLICE_ID;
import static org.onosproject.pipelines.fabric.impl.behaviour.Constants.DEFAULT_TC;
import static org.onosproject.pipelines.fabric.impl.behaviour.Constants.FALSE;
import static org.onosproject.pipelines.fabric.impl.behaviour.Constants.TRUE;

/**
 * Provides logic to translate UPF entities into pipeline-specific ones and vice-versa.
 * Implementation should be stateless, with all state delegated to FabricUpfStore.
 */
public class FabricUpfTranslator {

    // UPF related constants
    public static final int INTERFACE_ACCESS = 1;
    public static final int INTERFACE_CORE = 2;
    public static final int INTERFACE_DBUF = 3;

    private final FabricUpfStore fabricUpfStore;

    public FabricUpfTranslator(FabricUpfStore fabricUpfStore) {
        this.fabricUpfStore = fabricUpfStore;
    }

    /**
     * Returns true if the given table entry is a Packet Detection Rule from the physical fabric pipeline, and
     * false otherwise.
     *
     * @param entry the entry that may or may not be a fabric.p4 PDR
     * @return true if the entry is a fabric.p4 PDR
     */
    public boolean isFabricPdr(FlowRule entry) {
        return entry.table().equals(FABRIC_INGRESS_SPGW_UPLINK_PDRS)
                || entry.table().equals(FABRIC_INGRESS_SPGW_DOWNLINK_PDRS);
    }

    /**
     * Returns true if the given table entry is a Forwarding Action Rule from the physical fabric pipeline, and
     * false otherwise.
     *
     * @param entry the entry that may or may not be a fabric.p4 FAR
     * @return true if the entry is a fabric.p4 FAR
     */
    public boolean isFabricFar(FlowRule entry) {
        return entry.table().equals(FABRIC_INGRESS_SPGW_FARS);
    }

    /**
     * Returns true if the given table entry is an interface table entry from the fabric.p4 physical pipeline, and
     * false otherwise.
     *
     * @param entry the entry that may or may not be a fabric.p4 UPF interface
     * @return true if the entry is a fabric.p4 UPF interface
     */
    public boolean isFabricInterface(FlowRule entry) {
        return entry.table().equals(FABRIC_INGRESS_SPGW_INTERFACES);
    }


    /**
     * Translate a fabric.p4 PDR table entry to a PacketDetectionRule instance for easier handling.
     *
     * @param entry the fabric.p4 entry to translate
     * @return the corresponding PacketDetectionRule
     * @throws UpfProgrammableException if the entry cannot be translated
     */
    public PacketDetectionRule fabricEntryToPdr(FlowRule entry)
            throws UpfProgrammableException {
        var pdrBuilder = PacketDetectionRule.builder();
        Pair<PiCriterion, PiTableAction> matchActionPair = FabricUpfTranslatorUtil.fabricEntryToPiPair(entry);
        PiCriterion match = matchActionPair.getLeft();
        PiAction action = (PiAction) matchActionPair.getRight();

        // Grab keys and parameters that are present for all PDRs
        int globalFarId = FabricUpfTranslatorUtil.getParamInt(action, FAR_ID);
        UpfRuleIdentifier farId = fabricUpfStore.localFarIdOf(globalFarId);
        if (farId == null) {
            throw new UpfProgrammableException(String.format("Unable to find local far id of %s", globalFarId));
        }

        pdrBuilder.withCounterId(FabricUpfTranslatorUtil.getParamInt(action, CTR_ID))
                .withLocalFarId(farId.getSessionLocalId())
                .withSessionId(farId.getPfcpSessionId());

        PiActionId actionId = action.id();
        if (actionId.equals(FABRIC_INGRESS_SPGW_LOAD_PDR_QOS)) {
            pdrBuilder.withQfi(FabricUpfTranslatorUtil.getParamByte(action, QFI));
            if (FabricUpfTranslatorUtil.getParamByte(action, NEEDS_QFI_PUSH) == TRUE) {
                pdrBuilder.withQfiPush();
            }
        }

        if (FabricUpfTranslatorUtil.fieldIsPresent(match, HDR_TEID)) {
            // F-TEID is only present for GTP-matching PDRs
            ImmutableByteSequence teid = FabricUpfTranslatorUtil.getFieldValue(match, HDR_TEID);
            Ip4Address tunnelDst = FabricUpfTranslatorUtil.getFieldAddress(match, HDR_TUNNEL_IPV4_DST);
            pdrBuilder.withTeid(teid)
                    .withTunnelDst(tunnelDst);
            if (FabricUpfTranslatorUtil.fieldIsPresent(match, HDR_HAS_QFI) &&
                    FabricUpfTranslatorUtil.getFieldByte(match, HDR_HAS_QFI) == TRUE) {
                pdrBuilder.withQfi(FabricUpfTranslatorUtil.getFieldByte(match, HDR_QFI));
                pdrBuilder.withQfiMatch();
            }
        } else if (FabricUpfTranslatorUtil.fieldIsPresent(match, HDR_UE_ADDR)) {
            // And UE address is only present for non-GTP-matching PDRs
            pdrBuilder.withUeAddr(FabricUpfTranslatorUtil.getFieldAddress(match, HDR_UE_ADDR));
        } else {
            throw new UpfProgrammableException("Read malformed PDR from dataplane!:" + entry);
        }
        return pdrBuilder.build();
    }

    /**
     * Translate a fabric.p4 FAR table entry to a ForwardActionRule instance for easier handling.
     *
     * @param entry the fabric.p4 entry to translate
     * @return the corresponding ForwardingActionRule
     * @throws UpfProgrammableException if the entry cannot be translated
     */
    public ForwardingActionRule fabricEntryToFar(FlowRule entry)
            throws UpfProgrammableException {
        var farBuilder = ForwardingActionRule.builder();
        Pair<PiCriterion, PiTableAction> matchActionPair = FabricUpfTranslatorUtil.fabricEntryToPiPair(entry);
        PiCriterion match = matchActionPair.getLeft();
        PiAction action = (PiAction) matchActionPair.getRight();

        int globalFarId = FabricUpfTranslatorUtil.getFieldInt(match, HDR_FAR_ID);
        UpfRuleIdentifier farId = fabricUpfStore.localFarIdOf(globalFarId);
        if (farId == null) {
            throw new UpfProgrammableException(String.format("Unable to find local far id of %s", globalFarId));
        }

        boolean dropFlag = FabricUpfTranslatorUtil.getParamInt(action, DROP) > 0;
        boolean notifyFlag = FabricUpfTranslatorUtil.getParamInt(action, NOTIFY_CP) > 0;

        // Match keys
        farBuilder.withSessionId(farId.getPfcpSessionId())
                .setFarId(farId.getSessionLocalId());

        // Parameters common to all types of FARs
        farBuilder.setDropFlag(dropFlag)
                .setNotifyFlag(notifyFlag);

        PiActionId actionId = action.id();

        if (actionId.equals(FABRIC_INGRESS_SPGW_LOAD_TUNNEL_FAR)
                || actionId.equals(FABRIC_INGRESS_SPGW_LOAD_DBUF_FAR)) {
            // Grab parameters specific to encapsulating FARs if they're present
            Ip4Address tunnelSrc = FabricUpfTranslatorUtil.getParamAddress(action, TUNNEL_SRC_ADDR);
            Ip4Address tunnelDst = FabricUpfTranslatorUtil.getParamAddress(action, TUNNEL_DST_ADDR);
            ImmutableByteSequence teid = FabricUpfTranslatorUtil.getParamValue(action, TEID);
            short tunnelSrcPort = (short) FabricUpfTranslatorUtil.getParamInt(action, TUNNEL_SRC_PORT);

            farBuilder.setBufferFlag(actionId.equals(FABRIC_INGRESS_SPGW_LOAD_DBUF_FAR));

            farBuilder.setTunnel(
                    GtpTunnel.builder()
                            .setSrc(tunnelSrc)
                            .setDst(tunnelDst)
                            .setTeid(teid)
                            .setSrcPort(tunnelSrcPort)
                            .build());
        }
        return farBuilder.build();
    }

    /**
     * Translate a fabric.p4 interface table entry to a UpfInterface instance for easier handling.
     *
     * @param entry the fabric.p4 entry to translate
     * @return the corresponding UpfInterface
     * @throws UpfProgrammableException if the entry cannot be translated
     */
    public UpfInterface fabricEntryToInterface(FlowRule entry)
            throws UpfProgrammableException {
        Pair<PiCriterion, PiTableAction> matchActionPair = FabricUpfTranslatorUtil.fabricEntryToPiPair(entry);
        PiCriterion match = matchActionPair.getLeft();
        PiAction action = (PiAction) matchActionPair.getRight();

        var ifaceBuilder = UpfInterface.builder()
                .setPrefix(FabricUpfTranslatorUtil.getFieldPrefix(match, HDR_IPV4_DST_ADDR));

        int interfaceType = FabricUpfTranslatorUtil.getParamInt(action, SRC_IFACE);
        if (interfaceType == INTERFACE_ACCESS) {
            ifaceBuilder.setAccess();
        } else if (interfaceType == INTERFACE_CORE) {
            ifaceBuilder.setCore();
        } else if (interfaceType == INTERFACE_DBUF) {
            ifaceBuilder.setDbufReceiver();
        }
        return ifaceBuilder.build();
    }

    /**
     * Translate a ForwardingActionRule to a FlowRule to be inserted into the fabric.p4 pipeline.
     * A side effect of calling this method is the FAR object's globalFarId is assigned if it was not already.
     *
     * @param far      The FAR to be translated
     * @param deviceId the ID of the device the FlowRule should be installed on
     * @param appId    the ID of the application that will insert the FlowRule
     * @param priority the FlowRule's priority
     * @return the FAR translated to a FlowRule
     * @throws UpfProgrammableException if the FAR to be translated is malformed
     */
    public FlowRule farToFabricEntry(ForwardingActionRule far, DeviceId deviceId, ApplicationId appId, int priority)
            throws UpfProgrammableException {
        PiAction action;
        if (!far.encaps()) {
            action = PiAction.builder()
                    .withId(FABRIC_INGRESS_SPGW_LOAD_NORMAL_FAR)
                    .withParameters(Arrays.asList(
                            new PiActionParam(DROP, far.drops() ? 1 : 0),
                            new PiActionParam(NOTIFY_CP, far.notifies() ? 1 : 0)
                    ))
                    .build();

        } else {
            if (far.tunnelSrc() == null || far.tunnelDst() == null
                    || far.teid() == null || far.tunnel().srcPort() == null) {
                throw new UpfProgrammableException(
                        "Not all action parameters present when translating " +
                                "intermediate encapsulating/buffering FAR to physical FAR!");
            }
            // TODO: copy tunnel destination port from logical switch write requests, instead of hardcoding 2152
            PiActionId actionId = far.buffers() ? FABRIC_INGRESS_SPGW_LOAD_DBUF_FAR :
                    FABRIC_INGRESS_SPGW_LOAD_TUNNEL_FAR;
            action = PiAction.builder()
                    .withId(actionId)
                    .withParameters(Arrays.asList(
                            new PiActionParam(DROP, far.drops() ? 1 : 0),
                            new PiActionParam(NOTIFY_CP, far.notifies() ? 1 : 0),
                            new PiActionParam(TEID, far.teid()),
                            new PiActionParam(TUNNEL_SRC_ADDR, far.tunnelSrc().toInt()),
                            new PiActionParam(TUNNEL_DST_ADDR, far.tunnelDst().toInt()),
                            new PiActionParam(TUNNEL_SRC_PORT, far.tunnel().srcPort())
                    ))
                    .build();
        }
        PiCriterion match = PiCriterion.builder()
                .matchExact(HDR_FAR_ID, fabricUpfStore.globalFarIdOf(far.sessionId(), far.farId()))
                .build();
        return DefaultFlowRule.builder()
                .forDevice(deviceId).fromApp(appId).makePermanent()
                .forTable(FABRIC_INGRESS_SPGW_FARS)
                .withSelector(DefaultTrafficSelector.builder().matchPi(match).build())
                .withTreatment(DefaultTrafficTreatment.builder().piTableAction(action).build())
                .withPriority(priority)
                .build();
    }

    /**
     * Translate a PacketDetectionRule to a FlowRule to be inserted into the fabric.p4 pipeline.
     * A side effect of calling this method is the PDR object's globalFarId is assigned if it was not already.
     *
     * @param pdr      The PDR to be translated
     * @param deviceId the ID of the device the FlowRule should be installed on
     * @param appId    the ID of the application that will insert the FlowRule
     * @param priority the FlowRule's priority
     * @return the FAR translated to a FlowRule
     * @throws UpfProgrammableException if the PDR to be translated is malformed
     */
    public FlowRule pdrToFabricEntry(PacketDetectionRule pdr, DeviceId deviceId, ApplicationId appId, int priority)
            throws UpfProgrammableException {
        final PiCriterion match;
        final PiTableId tableId;
        final PiAction action;

        final PiCriterion.Builder matchBuilder = PiCriterion.builder();

        PiAction.Builder actionBuilder = PiAction.builder()
                .withParameters(Arrays.asList(
                        new PiActionParam(CTR_ID, pdr.counterId()),
                        new PiActionParam(FAR_ID, fabricUpfStore.globalFarIdOf(pdr.sessionId(), pdr.farId())),
                        new PiActionParam(NEEDS_GTPU_DECAP, pdr.matchesEncapped() ?
                                TRUE : FALSE),
                        new PiActionParam(TC, DEFAULT_TC)
                ));
        PiActionId actionId = FABRIC_INGRESS_SPGW_LOAD_PDR;
        if (pdr.matchesEncapped()) {
            tableId = FABRIC_INGRESS_SPGW_UPLINK_PDRS;
            matchBuilder.matchExact(HDR_TEID, pdr.teid().asArray())
                    .matchExact(HDR_TUNNEL_IPV4_DST, pdr.tunnelDest().toInt());
            if (pdr.matchQfi()) {
                matchBuilder.matchExact(HDR_HAS_QFI, TRUE)
                        .matchExact(HDR_QFI, pdr.qfi());
            } else {
                matchBuilder.matchExact(HDR_HAS_QFI, FALSE)
                        .matchExact(HDR_QFI, DEFAULT_QFI);
                if (pdr.hasQfi()) {
                    actionId = FABRIC_INGRESS_SPGW_LOAD_PDR_QOS;
                    actionBuilder.withParameter(new PiActionParam(QFI, pdr.qfi()))
                            .withParameter(new PiActionParam(NEEDS_QFI_PUSH, FALSE));
                }
            }
        } else if (pdr.matchesUnencapped()) {
            tableId = FABRIC_INGRESS_SPGW_DOWNLINK_PDRS;
            matchBuilder.matchExact(HDR_UE_ADDR, pdr.ueAddress().toInt());
            if (pdr.hasQfi()) {
                actionBuilder.withParameter(new PiActionParam(QFI, pdr.qfi()));
                actionId = FABRIC_INGRESS_SPGW_LOAD_PDR_QOS;
            }
            actionBuilder.withParameter(
                    new PiActionParam(NEEDS_QFI_PUSH, pdr.pushQfi() ? TRUE : FALSE));
        } else {
            throw new UpfProgrammableException("Flexible PDRs not yet supported! Cannot translate " + pdr);
        }
        match = matchBuilder.build();
        action = actionBuilder.withId(actionId)
                .build();
        return DefaultFlowRule.builder()
                .forDevice(deviceId).fromApp(appId).makePermanent()
                .forTable(tableId)
                .withSelector(DefaultTrafficSelector.builder().matchPi(match).build())
                .withTreatment(DefaultTrafficTreatment.builder().piTableAction(action).build())
                .withPriority(priority)
                .build();
    }

    /**
     * Translate a UpfInterface to a FlowRule to be inserted into the fabric.p4 pipeline.
     *
     * @param upfInterface The interface to be translated
     * @param deviceId     the ID of the device the FlowRule should be installed on
     * @param appId        the ID of the application that will insert the FlowRule
     * @param priority     the FlowRule's priority
     * @return the UPF interface translated to a FlowRule
     * @throws UpfProgrammableException if the interface cannot be translated
     */
    public FlowRule interfaceToFabricEntry(UpfInterface upfInterface, DeviceId deviceId,
                                           ApplicationId appId, int priority)
            throws UpfProgrammableException {
        int interfaceTypeInt;
        int gtpuValidity;
        if (upfInterface.isDbufReceiver()) {
            interfaceTypeInt = INTERFACE_DBUF;
            gtpuValidity = 1;
        } else if (upfInterface.isAccess()) {
            interfaceTypeInt = INTERFACE_ACCESS;
            gtpuValidity = 1;
        } else {
            interfaceTypeInt = INTERFACE_CORE;
            gtpuValidity = 0;
        }

        PiCriterion match = PiCriterion.builder()
                .matchLpm(HDR_IPV4_DST_ADDR,
                          upfInterface.prefix().address().toInt(),
                          upfInterface.prefix().prefixLength())
                .matchExact(HDR_GTPU_IS_VALID, gtpuValidity)
                .build();
        PiAction action = PiAction.builder()
                .withId(FABRIC_INGRESS_SPGW_LOAD_IFACE)
                .withParameter(new PiActionParam(SRC_IFACE, interfaceTypeInt))
                .withParameter(new PiActionParam(SLICE_ID, DEFAULT_SLICE_ID))
                .build();
        return DefaultFlowRule.builder()
                .forDevice(deviceId).fromApp(appId).makePermanent()
                .forTable(FABRIC_INGRESS_SPGW_INTERFACES)
                .withSelector(DefaultTrafficSelector.builder().matchPi(match).build())
                .withTreatment(DefaultTrafficTreatment.builder().piTableAction(action).build())
                .withPriority(priority)
                .build();
    }
}
