/*
 *    Copyright (c) 2022 Project CHIP Authors
 *    All rights reserved.
 *
 *    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.
 */

#pragma once

#include <atomic>
#include <inet/EndpointQueueFilter.h>
#include <inet/IPPacketInfo.h>
#include <lib/support/CodeUtils.h>
#include <system/SystemPacketBuffer.h>

namespace chip {
namespace Inet {

/**
 * @brief Basic filter that counts how many pending (not yet dequeued) packets
 *        are accumulated that match a predicate function, and drops those that
 *        would cause crossing of the threshold.
 */
class DropIfTooManyQueuedPacketsFilter : public chip::Inet::EndpointQueueFilter
{
public:
    typedef bool (*PacketMatchPredicateFunc)(void * context, const void * endpoint, const chip::Inet::IPPacketInfo & pktInfo,
                                             const chip::System::PacketBufferHandle & pktPayload);

    /**
     * @brief Initialize the packet filter with a starting limit
     *
     * @param maxAllowedQueuedPackets - max number of pending-in-queue not yet processed predicate-matching packets
     */
    DropIfTooManyQueuedPacketsFilter(size_t maxAllowedQueuedPackets) : mMaxAllowedQueuedPackets(maxAllowedQueuedPackets) {}

    /**
     * @brief Set the predicate to use for filtering
     *
     * @warning DO NOT modify at runtime while the filter is being called. If you do so, the queue accounting could
     *          get out of sync, and cause the filtering to fail to properly work.
     *
     * @param predicateFunc - Predicate function to apply. If nullptr, no filtering will take place
     * @param context - Pointer to predicate-specific context that will be provided to predicate at every call. May be nullptr.
     */
    void SetPredicate(PacketMatchPredicateFunc predicateFunc, void * context)
    {
        mPredicate = predicateFunc;
        mContext   = context;
    }

    /**
     * @brief Set the ceiling for max allowed packets queued up that matched the predicate.
     *
     * @note Changing this at runtime while packets are coming only affects future dropping, and
     *       does not remove packets from the queue if the limit is lowered below the currently-in-queue
     *       count.
     *
     * @param maxAllowedQueuedPackets - number of packets currently pending allowed.
     */
    void SetMaxQueuedPacketsLimit(int maxAllowedQueuedPackets) { mMaxAllowedQueuedPackets.store(maxAllowedQueuedPackets); }

    /**
     * @return the total number of packets dropped so far by the filter
     */
    size_t GetNumDroppedPackets() const { return mNumDroppedPackets.load(); }

    /**
     * @brief Reset the counter of dropped packets.
     */
    void ClearNumDroppedPackets() { mNumDroppedPackets.store(0); }

    /**
     * @brief Method called when a packet is dropped due to high watermark getting reached, based on predicate.
     *
     * Subclasses may use this to implement additional behavior or diagnostics.
     *
     * This is called once for every dropped packet. If there is no filter predicate, this is not called.
     *
     * @param endpoint - pointer to endpoint instance (platform-dependent, which is why it's void)
     * @param pktInfo - info about source/dest of packet
     * @param pktPayload - payload content of packet
     */
    virtual void OnDropped(const void * endpoint, const chip::Inet::IPPacketInfo & pktInfo,
                           const chip::System::PacketBufferHandle & pktPayload)
    {}

    /**
     * @brief Method called whenever queue of accumulated packets is now empty, based on predicate.
     *
     * Subclasses may use this to implement additional behavior or diagnostics.
     *
     * This is possibly called repeatedly in a row, if the queue actually never gets above one.
     *
     * This is only called for packets that had matched the filtering rule, where they had
     * been explicitly allowed in the past. If there is no filter predicate, this is not called.
     *
     * @param endpoint - pointer to endpoint instance (platform-dependent, which is why it's void)
     * @param pktInfo - info about source/dest of packet
     * @param pktPayload - payload content of packet
     */
    virtual void OnLastMatchDequeued(const void * endpoint, const chip::Inet::IPPacketInfo & pktInfo,
                                     const chip::System::PacketBufferHandle & pktPayload)
    {}

    /**
     * @brief Implementation of filtering before queueing that applies the predicate.
     *
     * See base class for arguments
     */
    FilterOutcome FilterBeforeEnqueue(const void * endpoint, const chip::Inet::IPPacketInfo & pktInfo,
                                      const chip::System::PacketBufferHandle & pktPayload) override
    {
        // WARNING: This is likely called in a different context than `FilterAfterDequeue`. We use an atomic for the counter.

        // Non-matching is never accounted, always allowed. Lack of predicate is equivalent to non-matching.
        if ((mPredicate == nullptr) || !mPredicate(mContext, endpoint, pktInfo, pktPayload))
        {
            return FilterOutcome::kAllowPacket;
        }

        if (mNumQueuedPackets.load() >= mMaxAllowedQueuedPackets)
        {
            ++mNumDroppedPackets;
            OnDropped(endpoint, pktInfo, pktPayload);
            return FilterOutcome::kDropPacket;
        }

        ++mNumQueuedPackets;

        return FilterOutcome::kAllowPacket;
    }

    /**
     * @brief Implementation of filtering after dequeueing that applies the predicate.
     *
     * See base class for arguments
     */
    FilterOutcome FilterAfterDequeue(const void * endpoint, const chip::Inet::IPPacketInfo & pktInfo,
                                     const chip::System::PacketBufferHandle & pktPayload) override
    {
        // WARNING: This is likely called in a different context than `FilterBeforeEnqueue`. We use an atomic for the counter.
        // NOTE: This is always called from Matter platform event loop

        // Non-matching is never accounted, always allowed. Lack of predicate is equivalent to non-matching.
        if ((mPredicate == nullptr) || !mPredicate(mContext, endpoint, pktInfo, pktPayload))
        {
            return FilterOutcome::kAllowPacket;
        }

        --mNumQueuedPackets;
        int numQueuedPackets = mNumQueuedPackets.load();
        if (numQueuedPackets == 0)
        {
            OnLastMatchDequeued(endpoint, pktInfo, pktPayload);
        }

        // If we ever go negative, we have mismatch ingress/egress filter via predicate and
        // device may eventually starve.
        VerifyOrDie(numQueuedPackets >= 0);

        // We always allow the packet and just do accounting, since all dropping is prior to queue entry.
        return FilterOutcome::kAllowPacket;
    }

protected:
    PacketMatchPredicateFunc mPredicate = nullptr;
    void * mContext                     = nullptr;
    std::atomic_int mNumQueuedPackets{ 0 };
    std::atomic_int mMaxAllowedQueuedPackets{ 0 };
    std::atomic_size_t mNumDroppedPackets{ 0u };
};

} // namespace Inet
} // namespace chip
