/*
 * Copyright 2019-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.Ethernet;
import org.onlab.packet.IpPrefix;
import org.onlab.packet.MacAddress;
import org.onlab.packet.VlanId;
import org.onosproject.net.driver.Driver;
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.EthCriterion;
import org.onosproject.net.flow.criteria.EthTypeCriterion;
import org.onosproject.net.flow.criteria.ExtensionCriterion;
import org.onosproject.net.flow.criteria.ExtensionSelector;
import org.onosproject.net.flow.criteria.IPCriterion;
import org.onosproject.net.flow.criteria.MplsBosCriterion;
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.flow.instructions.L2ModificationInstruction.L2SubType;
import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModTunnelIdInstruction;
import org.onosproject.net.flowobjective.FilteringObjective;
import org.onosproject.net.flowobjective.ForwardingObjective;
import org.onosproject.net.flowobjective.Objective;
import org.onosproject.net.flowobjective.ObjectiveError;

import static org.onosproject.net.behaviour.Pipeliner.ACCUMULATOR_ENABLED;
import static org.onosproject.net.flow.criteria.Criterion.Type.ETH_TYPE;
import static org.onosproject.net.flow.criteria.Criterion.Type.MPLS_BOS;
import static org.onosproject.net.flow.instructions.Instruction.Type.L2MODIFICATION;
import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModVlanIdInstruction;
import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModEtherInstruction;

public final class OfdpaPipelineUtility {

    private OfdpaPipelineUtility() {
        // Utility classes should not have a public or default constructor.
    }

    // Ofdpa specific tables number
    static final int PORT_TABLE = 0;
    static final int VLAN_TABLE = 10;
    static final int VLAN_1_TABLE = 11;
    static final int MPLS_L2_PORT_FLOW_TABLE = 13;
    static final int MPLS_L2_PORT_PCP_TRUST_FLOW_TABLE = 16;
    static final int TMAC_TABLE = 20;
    static final int UNICAST_ROUTING_TABLE = 30;
    static final int MULTICAST_ROUTING_TABLE = 40;
    static final int MPLS_TABLE_0 = 23;
    static final int MPLS_TABLE_1 = 24;
    static final int MPLS_L3_TYPE_TABLE = 27;
    static final int MPLS_TYPE_TABLE = 29;
    static final int BRIDGING_TABLE = 50;
    public static final int ACL_TABLE = 60;
    static final int MAC_LEARNING_TABLE = 254;

    // OF max port number
    static final long OFPP_MAX = 0xffffff00L;

    // Priority values
    static final int HIGHEST_PRIORITY = 0xffff;
    static final int DEFAULT_PRIORITY = 0x8000;
    static final int LOWEST_PRIORITY = 0x0;

    // MPLS L2 table values
    static final int MPLS_L2_PORT_PRIORITY = 2;
    static final int MPLS_TUNNEL_ID_BASE = 0x10000;
    static final int MPLS_TUNNEL_ID_MAX = 0x1FFFF;
    static final int MPLS_UNI_PORT_MAX = 0x0000FFFF;
    static final int MPLS_NNI_PORT_BASE = 0x00020000;
    static final int MPLS_NNI_PORT_MAX = 0x0002FFFF;

    // Flow retry values
    static final int MAX_RETRY_ATTEMPTS = 10;
    static final int RETRY_MS = 1000;

    //////////////////////////////
    // Helper and utility methods
    //////////////////////////////

    /**
     * Check whether the accumulator is enabled or not.
     * @param pipeline the pipeline
     * @return true if the accumulator is enabled. Otherwise not
     */
    static boolean isAccumulatorEnabled(Ofdpa2Pipeline pipeline) {
        Driver driver = pipeline.data().driver();
        // we cannot determine the property
        if (driver == null) {
            return false;
        }
        return Boolean.parseBoolean(driver.getProperty(ACCUMULATOR_ENABLED));
    }

    static void pass(Objective obj) {
        obj.context().ifPresent(context -> context.onSuccess(obj));
    }

    static void fail(Objective obj, ObjectiveError error) {
        obj.context().ifPresent(context -> context.onError(obj, error));
    }

    /**
     * Returns true iff the given selector matches on BOS==true, indicating that
     * the selector is trying to match on a label that is bottom-of-stack.
     *
     * @param selector the given match
     * @return true iff BoS==true; false if BOS==false, or BOS matching is not
     *         expressed in the given selector
     */
    static boolean isMplsBos(TrafficSelector selector) {
        MplsBosCriterion bosCriterion = (MplsBosCriterion) selector.getCriterion(MPLS_BOS);
        return bosCriterion != null && bosCriterion.mplsBos();
    }

    /**
     * Returns true iff the given selector matches on BOS==false, indicating
     * that the selector is trying to match on a label that is not the
     * bottom-of-stack label.
     *
     * @param selector the given match
     * @return true iff BoS==false;
     *         false if BOS==true, or BOS matching is not expressed in the given selector
     */
    static boolean isNotMplsBos(TrafficSelector selector) {
        MplsBosCriterion bosCriterion = (MplsBosCriterion) selector.getCriterion(MPLS_BOS);
        return bosCriterion != null && !bosCriterion.mplsBos();
    }

    /**
     * Returns true iff the forwarding objective includes a treatment to pop the
     * MPLS label.
     *
     * @param fwd the given forwarding objective
     * @return true iff mpls pop treatment exists
     */
    static boolean isMplsPop(ForwardingObjective fwd) {
        if (fwd.treatment() != null) {
            for (Instruction instr : fwd.treatment().allInstructions()) {
                if (instr instanceof L2ModificationInstruction
                        && ((L2ModificationInstruction) instr)
                        .subtype() == L2SubType.MPLS_POP) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * Returns true iff the given selector matches on ethtype==ipv6, indicating
     * that the selector is trying to match on ipv6 traffic.
     *
     * @param selector the given match
     * @return true iff ethtype==ipv6; false otherwise
     */
    static boolean isIpv6(TrafficSelector selector) {
        EthTypeCriterion ethTypeCriterion = (EthTypeCriterion) selector.getCriterion(ETH_TYPE);
        return ethTypeCriterion != null && ethTypeCriterion.ethType().toShort() == Ethernet.TYPE_IPV6;
    }

    /**
     * Reads vlan id from selector.
     *
     * @param selector the given match
     * @return the vlan id if found. null otherwise
     */
    static VlanId readVlanFromSelector(TrafficSelector selector) {
        if (selector == null) {
            return null;
        }
        Criterion criterion = selector.getCriterion(Criterion.Type.VLAN_VID);
        return (criterion == null)
                ? null : ((VlanIdCriterion) criterion).vlanId();
    }

    /**
     * Reads eth dst from selector.
     *
     * @param selector the given match
     * @return the eth dst if found. null otherwise
     */
    static MacAddress readEthDstFromSelector(TrafficSelector selector) {
        if (selector == null) {
            return null;
        }
        Criterion criterion = selector.getCriterion(Criterion.Type.ETH_DST);
        return (criterion == null)
                ? null : ((EthCriterion) criterion).mac();
    }

    /**
     * Reads ipv4 dst from selector.
     *
     * @param selector the given match
     * @return the ipv4 dst if found. null otherwise
     */
    static IpPrefix readIpDstFromSelector(TrafficSelector selector) {
        if (selector == null) {
            return null;
        }
        Criterion criterion = selector.getCriterion(Criterion.Type.IPV4_DST);
        return (criterion == null) ? null : ((IPCriterion) criterion).ip();
    }

    /**
     * Reads vlan id from treatment.
     *
     * @param treatment the given actions
     * @return the vlan id if found. null otherwise
     */
    static VlanId readVlanFromTreatment(TrafficTreatment treatment) {
        if (treatment == null) {
            return null;
        }
        for (Instruction i : treatment.allInstructions()) {
            if (i instanceof ModVlanIdInstruction) {
                return ((ModVlanIdInstruction) i).vlanId();
            }
        }
        return null;
    }

    /**
     * Reads eth dst from treatment.
     *
     * @param treatment the given actions
     * @return the eth dst if found. null otherwise
     */
    static MacAddress readEthDstFromTreatment(TrafficTreatment treatment) {
        if (treatment == null) {
            return null;
        }
        for (Instruction i : treatment.allInstructions()) {
            if (i instanceof ModEtherInstruction) {
                ModEtherInstruction modEtherInstruction = (ModEtherInstruction) i;
                if (modEtherInstruction.subtype() == L2SubType.ETH_DST) {
                    return modEtherInstruction.mac();
                }
            }
        }
        return null;
    }

    /**
     * Reads extensions from selector.
     * @param selector the given match
     * @return the extensions if found. null otherwise
     */
    static ExtensionSelector readExtensionFromSelector(TrafficSelector selector) {
        if (selector == null) {
            return null;
        }
        ExtensionCriterion criterion = (ExtensionCriterion) selector.getCriterion(Criterion.Type.EXTENSION);
        return (criterion == null) ? null : criterion.extensionSelector();
    }

    /**
     * Determines if the filtering objective will be used for a pseudowire.
     *
     * @param filteringObjective the filtering objective
     * @return True if objective was created for a pseudowire, false otherwise.
     */
    static boolean isPseudowire(FilteringObjective filteringObjective) {
        if (filteringObjective.meta() != null) {
            TrafficTreatment treatment = filteringObjective.meta();
            for (Instruction instr : treatment.immediate()) {
                if (instr.type().equals(Instruction.Type.L2MODIFICATION)) {

                    L2ModificationInstruction l2Instr = (L2ModificationInstruction) instr;
                    if (l2Instr.subtype().equals(L2SubType.TUNNEL_ID)) {
                        return true;
                    }
                }
            }
        }
        return false;
    }

    /**
     * Utility function to get the mod tunnel id instruction
     * if present.
     *
     * @param treatment the treatment to analyze
     * @return the mod tunnel id instruction if present,
     * otherwise null
     */
    static ModTunnelIdInstruction getModTunnelIdInstruction(TrafficTreatment treatment) {
        if (treatment == null) {
            return null;
        }
        L2ModificationInstruction l2ModificationInstruction;
        for (Instruction instruction : treatment.allInstructions()) {
            if (instruction.type() == L2MODIFICATION) {
                l2ModificationInstruction = (L2ModificationInstruction) instruction;
                if (l2ModificationInstruction.subtype() == L2SubType.TUNNEL_ID) {
                    return (ModTunnelIdInstruction) l2ModificationInstruction;
                }
            }
        }
        return null;
    }

    /**
     * Utility function to get the output instruction
     * if present.
     *
     * @param treatment the treatment to analyze
     * @return the output instruction if present,
     * otherwise null
     */
    static Instructions.OutputInstruction getOutputInstruction(TrafficTreatment treatment) {
        if (treatment == null) {
            return null;
        }
        for (Instruction instruction : treatment.allInstructions()) {
            if (instruction.type() == Instruction.Type.OUTPUT) {
                return (Instructions.OutputInstruction) instruction;
            }
        }
        return null;
    }

}
