/*
 *    Copyright (c) 2021 Project CHIP Authors
 *
 *    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 <lib/core/Optional.h>
#include <lib/support/IntrusiveList.h>
#include <messaging/ExchangeContext.h>

namespace chip {
namespace Messaging {

/**
 * @brief
 *   This provides a RAII'fied wrapper for an ExchangeContext that automatically manages
 *   cleaning up the EC when the holder ceases to exist, or acquires a new exchange. This is
 *   meant to be used by application and protocol logic code that would otherwise need to closely
 *   manage their internal pointers to an ExchangeContext and correctly
 *   null-it out/abort it depending on the circumstances. This relies on clear rules
 *   established by ExchangeContext and the transfer of ownership at various points
 *   in its lifetime.
 *
 *   An equivalent but simplified version of the rules around exchange management as specified in
 *   ExchangeDelegate.h are provided here for consumers:
 *
 *   1. When an exchange is allocated, the holder takes over ownership of the exchange when Grab() is invoked.
 *      Until a message is sent successfully, the holder will automatically manage the exchange until its
 *      destructor or Release() is invoked.
 *
 *   2. If you send a message successfully that doesn't require a response, invoking Get() on the holder there-after will return
 *      nullptr.
 *
 *   3. If you send a message successfully that does require a response, invoking Get() on the holder will return a valid
 *      pointer until the response is received or times out.
 *
 *   4. On reception of a message on an exchange, if you return from OnMessageReceived() and no messages were sent on that exchange,
 *      invoking Get() on the holder will return a nullptr.
 *
 *   5. If you invoke WillSendMessage() on the exchange in your implementation of OnMessageReceived indicating a desire to send a
 *      message later on the exchange, invoking Get() on the holder will return a valid exchange until SendMessage() on the exchange
 *      is called, at which point, rules 2 and 3 apply.
 *
 *   6. This is a delegate forwarder -  consumers can still register to be an ExchangeDelegate
 *      and get notified of all relevant happenings on that delegate interface.
 *
 *   7. At no point shall you call Abort/Close/Release/Retain on the exchange tracked by the holder.
 *
 */
class ExchangeHolder : public ExchangeDelegate
{
public:
    /**
     * @brief
     *    Constructor that takes an ExchangeDelegate that is forwarded all relevant
     *    calls from the underlying exchange.
     */
    ExchangeHolder(ExchangeDelegate & delegate) : mpExchangeDelegate(delegate) {}

    virtual ~ExchangeHolder()
    {
#if CHIP_EXCHANGE_HOLDER_DETAIL_LOGGING
        ChipLogDetail(ExchangeManager, "[%p] ~ExchangeHolder", this);
#endif
        Release();
    }

    bool Contains(const ExchangeContext * exchange) const { return mpExchangeCtx == exchange; }

    /**
     * @brief
     *    Replaces the held exchange and associated delegate to instead track the given ExchangeContext, aborting
     *    and dereferencing any previously held exchange as necessary. This method should be called whenever protocol logic
     *    that is managing this holder is transitioning from an outdated Exchange to a new one, often during
     *    the start of a new transaction.
     */
    void Grab(ExchangeContext * exchange)
    {
        VerifyOrDie(exchange != nullptr);

        Release();

        mpExchangeCtx = exchange;
        mpExchangeCtx->SetDelegate(this);

#if CHIP_EXCHANGE_HOLDER_DETAIL_LOGGING
        ChipLogDetail(ExchangeManager, "[%p] ExchangeHolder::Grab: Acquired EC %p", this, exchange);
#endif
    }

    /*
     * @brief
     *    This shuts down the exchange (if a valid one is being tracked) and releases our reference to it.
     */
    void Release()
    {
#if CHIP_EXCHANGE_HOLDER_DETAIL_LOGGING
        ChipLogDetail(ExchangeManager, "[%p] ExchangeHolder::Release: mpExchangeCtx = %p", this, mpExchangeCtx);
#endif

        if (mpExchangeCtx)
        {
            mpExchangeCtx->SetDelegate(nullptr);

            /**
             * Shutting down the exchange requires calling Abort() on the exchange selectively in the following scenarios:
             *      1. The exchange is currently awaiting a response. This would have happened if our consumer just sent a message
             * on the exchange and is awaiting a response. Since we no longer care to wait for the response, we don't care about
             * doing MRP retries for the send we just did, so abort the exchange.
             *
             *      2. Our consumer has signaled an interest in sending a message. This could have been signaled right at exchange
             * creation time as the initiator, or when handling a message and the consumer intends to send a response, albeit,
             * asynchronously. In both cases, the stack expects the exchange consumer to close/abort the EC if it no longer has
             * interest in it. Since we don't have a pending message at this point, calling Abort is OK here as well.
             *
             */
            if (mpExchangeCtx->IsResponseExpected() || mpExchangeCtx->IsSendExpected())
            {
#if CHIP_EXCHANGE_HOLDER_DETAIL_LOGGING
                ChipLogDetail(ExchangeManager, "[%p] ExchangeHolder::Release: Aborting!", this);
#endif
                mpExchangeCtx->Abort();
            }
        }

        mpExchangeCtx = nullptr;
    }

    explicit operator bool() const { return mpExchangeCtx != nullptr; }
    ExchangeContext * Get() const { return mpExchangeCtx; }

    ExchangeContext * operator->() const
    {
        VerifyOrDie(mpExchangeCtx != nullptr);
        return mpExchangeCtx;
    }

private:
    CHIP_ERROR OnMessageReceived(ExchangeContext * ec, const PayloadHeader & payloadHeader,
                                 System::PacketBufferHandle && payload) override
    {
        return mpExchangeDelegate.OnMessageReceived(ec, payloadHeader, std::move(payload));
    }

    void OnResponseTimeout(ExchangeContext * ec) override { return mpExchangeDelegate.OnResponseTimeout(ec); }

    void OnExchangeClosing(ExchangeContext * ec) override
    {
#if CHIP_EXCHANGE_HOLDER_DETAIL_LOGGING
        ChipLogDetail(ExchangeManager, "[%p] ExchangeHolder::OnExchangeClosing: mpExchangeCtx: %p", this, mpExchangeCtx);
#endif

        if (mpExchangeCtx)
        {
            mpExchangeCtx->SetDelegate(nullptr);

            /**
             * Unless our consumer has signalled an intention to send a message in the future, the exchange
             * is owned by the exchange layer and it will automatically handle releasing the ref. So, just null
             * out our reference to it.
             */
            if (!mpExchangeCtx->IsSendExpected())
            {
#if CHIP_EXCHANGE_HOLDER_DETAIL_LOGGING
                ChipLogDetail(ExchangeManager, "[%p] ExchangeHolder::OnExchangeClosing: nulling out ref...", this);
#endif
                mpExchangeCtx = nullptr;
            }
        }

        mpExchangeDelegate.OnExchangeClosing(ec);
    }

    ExchangeMessageDispatch & GetMessageDispatch() override { return mpExchangeDelegate.GetMessageDispatch(); }

    ExchangeDelegate & mpExchangeDelegate;
    ExchangeContext * mpExchangeCtx = nullptr;
};

} // namespace Messaging
} // namespace chip
