/*
 *
 *    Copyright (c) 2020-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.
 */

/**
 *    @file
 *      This file defines the classes corresponding to CHIP Exchange Context.
 *
 */

#pragma once

#include <lib/core/ReferenceCounted.h>
#include <lib/support/BitFlags.h>
#include <lib/support/DLLUtil.h>
#include <lib/support/ReferenceCountedHandle.h>
#include <lib/support/TypeTraits.h>
#include <messaging/ExchangeDelegate.h>
#include <messaging/Flags.h>
#include <messaging/ReliableMessageContext.h>
#include <protocols/Protocols.h>
#include <transport/SessionManager.h>

namespace chip {

namespace Messaging {

class ExchangeManager;
class ExchangeContext;
class ExchangeMessageDispatch;
using ExchangeHandle = ReferenceCountedHandle<ExchangeContext>;

class ExchangeContextDeletor
{
public:
    static void Release(ExchangeContext * obj);
};

/**
 *  @brief
 *    This class represents an ongoing conversation (ExchangeContext) between two or more nodes.
 *    It defines methods for encoding and communicating CHIP messages within an ExchangeContext
 *    over various transport mechanisms, for example, TCP, UDP, or CHIP Reliable Messaging.
 *
 */
class DLL_EXPORT ExchangeContext : public ReliableMessageContext,
                                   public ReferenceCounted<ExchangeContext, ExchangeContextDeletor>,
                                   public SessionDelegate
{
    friend class ExchangeManager;
    friend class ExchangeContextDeletor;

public:
    typedef System::Clock::Timeout Timeout; // Type used to express the timeout in this ExchangeContext

    ExchangeContext(ExchangeManager * em, uint16_t ExchangeId, const SessionHandle & session, bool Initiator,
                    ExchangeDelegate * delegate, bool isEphemeralExchange = false);

    ~ExchangeContext() override;

    /**
     *  Determine whether the context is the initiator of the exchange.
     *
     *  @return Returns 'true' if it is the initiator, else 'false'.
     */
    bool IsInitiator() const;

    bool IsEncryptionRequired() const { return mDispatch.IsEncryptionRequired(); }

    bool IsGroupExchangeContext() const { return mSession && mSession->IsGroupSession(); }

    // Implement SessionDelegate
    NewSessionHandlingPolicy GetNewSessionHandlingPolicy() override { return NewSessionHandlingPolicy::kStayAtOldSession; }
    void OnSessionReleased() override;

#if INET_CONFIG_ENABLE_TCP_ENDPOINT
    void OnSessionConnectionClosed(CHIP_ERROR conErr) override;
#endif // INET_CONFIG_ENABLE_TCP_ENDPOINT
    /**
     *  Send a CHIP message on this exchange.
     *
     *  If SendMessage returns success and the message was not expecting a
     *  response, the exchange will close itself before returning, unless the
     *  message being sent is a standalone ack.  If SendMessage returns failure,
     *  the caller is responsible for deciding what to do (e.g. closing the
     *  exchange, trying to re-establish a secure session, etc).
     *
     *  @param[in]    protocolId    The protocol identifier of the CHIP message to be sent.
     *
     *  @param[in]    msgType       The message type of the corresponding protocol.
     *
     *  @param[in]    msgPayload    A handle to the packet buffer holding the CHIP message.
     *
     *  @param[in]    sendFlags     Flags set by the application for the CHIP message being sent.
     *
     *  @retval  #CHIP_ERROR_INVALID_ARGUMENT               if an invalid argument was passed to this SendMessage API.
     *  @retval  #CHIP_ERROR_NOT_CONNECTED                  if the context was associated with a connection that is now
     *                                                       closed.
     *  @retval  #CHIP_ERROR_INCORRECT_STATE                if the state of the exchange context is incorrect.
     *  @retval  #CHIP_NO_ERROR                             if the CHIP layer successfully sent the message down to the
     *                                                       network layer.
     */
    CHIP_ERROR SendMessage(Protocols::Id protocolId, uint8_t msgType, System::PacketBufferHandle && msgPayload,
                           const SendFlags & sendFlags = SendFlags(SendMessageFlags::kNone));

    /**
     * A strongly-message-typed version of SendMessage.
     */
    template <typename MessageType, typename = std::enable_if_t<std::is_enum<MessageType>::value>>
    CHIP_ERROR SendMessage(MessageType msgType, System::PacketBufferHandle && msgPayload,
                           const SendFlags & sendFlags = SendFlags(SendMessageFlags::kNone))
    {
        return SendMessage(Protocols::MessageTypeTraits<MessageType>::ProtocolId(), to_underlying(msgType), std::move(msgPayload),
                           sendFlags);
    }

    /**
     * A notification that we will have SendMessage called on us in the future
     * (and should stay open until that happens).
     */
    void WillSendMessage() { mFlags.Set(Flags::kFlagWillSendMessage); }

    /**
     *  Handle a received CHIP message on this exchange.
     *
     *  @param[in]    messageCounter  The message counter of the packet.
     *  @param[in]    payloadHeader   A reference to the PayloadHeader object.
     *  @param[in]    msgFlags        The message flags corresponding to the received message
     *  @param[in]    msgBuf          A handle to the packet buffer holding the CHIP message.
     *
     *  @retval  #CHIP_ERROR_INVALID_ARGUMENT               if an invalid argument was passed to this HandleMessage API.
     *  @retval  #CHIP_ERROR_INCORRECT_STATE                if the state of the exchange context is incorrect.
     *  @retval  #CHIP_NO_ERROR                             if the CHIP layer successfully delivered the message up to the
     *                                                       protocol layer.
     */
    CHIP_ERROR HandleMessage(uint32_t messageCounter, const PayloadHeader & payloadHeader, MessageFlags msgFlags,
                             System::PacketBufferHandle && msgBuf);

    ExchangeDelegate * GetDelegate() const { return mDelegate; }
    void SetDelegate(ExchangeDelegate * delegate) { mDelegate = delegate; }

    ExchangeManager * GetExchangeMgr() const { return mExchangeMgr; }

    ReliableMessageContext * GetReliableMessageContext() { return static_cast<ReliableMessageContext *>(this); };

    SessionHandle GetSessionHandle() const
    {
        VerifyOrDie(mSession);
        auto sessionHandle = mSession.Get();
        return std::move(sessionHandle.Value());
    }

    bool HasSessionHandle() const { return mSession; }

    uint16_t GetExchangeId() const { return mExchangeId; }

    /*
     * In order to use reference counting (see refCount below) we use a hold/free paradigm where users of the exchange
     * can hold onto it while it's out of their direct control to make sure it isn't closed before everyone's ready.
     * A customized version of reference counting is used since there are some extra stuff to do within Release.
     */
    void Close();
    void Abort();

    // Applies a suggested response timeout value based on the session type and the given upper layer processing time for
    // the next message to the exchange. The exchange context must have a valid session when calling this function.
    //
    // This function is an equivalent of SetResponseTimeout(mSession->ComputeRoundTripTimeout(applicationProcessingTimeout))
    void UseSuggestedResponseTimeout(Timeout applicationProcessingTimeout);

    // Set the response timeout for the exchange context, regardless of the underlying session type. Using
    // UseSuggestedResponseTimeout to set a timeout based on the type of the session and the application processing time instead of
    // using this function is recommended.
    //
    // If a timeout of 0 is provided, it implies no response is expected. Consequently, ExchangeDelegate::OnResponseTimeout will not
    // be called.
    //
    void SetResponseTimeout(Timeout timeout);

    // This API is used by commands that need to shut down all existing
    // sessions/exchanges on a fabric but need to make sure the response to the
    // command still goes out on the exchange the command came in on.  This API
    // will ensure that all secure sessions for the fabric this exchanges is on
    // are released except the one this exchange is using, and will release
    // that session once this exchange is done sending the response.
    //
    // This API is a no-op if called on an exchange that is not using a
    // SecureSession.
    void AbortAllOtherCommunicationOnFabric();

    /**
     *  Determine whether a response is currently expected for a message that was sent over
     *  this exchange.  While this is true, attempts to send other messages that expect a response
     *  will fail.
     *
     *  @return Returns 'true' if response expected, else 'false'.
     */
    bool IsResponseExpected() const;

    /**
     * Determine whether we are expecting our consumer to send a message on
     * this exchange (i.e. WillSendMessage was called and the message has not
     * yet been sent).
     */
    bool IsSendExpected() const { return mFlags.Has(Flags::kFlagWillSendMessage); }

    /**
     * Tracks whether we have received at least one application level message
     * during the life-time of this exchange
     *
     * @return Returns 'true' if we have received at least one message, else 'false'
     */
    inline bool HasReceivedAtLeastOneMessage() { return mFlags.Has(Flags::kFlagReceivedAtLeastOneMessage); }

#if CONFIG_BUILD_FOR_HOST_UNIT_TEST
    SessionHolder & GetSessionHolder() { return mSession; }

    enum class InjectedFailureType : uint8_t
    {
        kFailOnSend = 0x01
    };

    void InjectFailure(InjectedFailureType failureType) { mInjectedFailures.Set(failureType); }

    void ClearInjectedFailures() { mInjectedFailures.ClearAll(); }
#endif

private:
#if CONFIG_BUILD_FOR_HOST_UNIT_TEST
    BitFlags<InjectedFailureType> mInjectedFailures;
#endif

    class ExchangeSessionHolder : public SessionHolderWithDelegate
    {
    public:
        ExchangeSessionHolder(ExchangeContext & exchange) : SessionHolderWithDelegate(exchange) {}
        void GrabExpiredSession(const SessionHandle & session);
    };

    Timeout mResponseTimeout{ 0 }; // Maximum time to wait for response (in milliseconds); 0 disables response timeout.
    ExchangeDelegate * mDelegate   = nullptr;
    ExchangeManager * mExchangeMgr = nullptr;

    ExchangeMessageDispatch & mDispatch;

    ExchangeSessionHolder mSession; // The connection state
    uint16_t mExchangeId;           // Assigned exchange ID.

    /**
     *  Track whether we are now expecting a response to a message sent via this exchange (because that
     *  message had the kExpectResponse flag set in its sendFlags).
     *
     *  @param[in]  inResponseExpected  A Boolean indicating whether (true) or not
     *                                  (false) a response is currently expected on this
     *                                  exchange.
     */
    void SetResponseExpected(bool inResponseExpected);

    /**
     *  Search for an existing exchange that the message applies to.
     *
     *  @param[in]    session       The secure session of the received message.
     *
     *  @param[in]    packetHeader  A reference to the PacketHeader object.
     *
     *  @param[in]    payloadHeader A reference to the PayloadHeader object.
     *
     *  @retval  true                                       If a match is found.
     *  @retval  false                                      If a match is not found.
     */
    bool MatchExchange(const SessionHandle & session, const PacketHeader & packetHeader, const PayloadHeader & payloadHeader);

    /**
     * Notify our delegate, if any, that we have timed out waiting for a
     * response.  If aCloseIfNeeded is true, check whether the exchange needs to
     * be closed.
     */
    void NotifyResponseTimeout(bool aCloseIfNeeded);

    CHIP_ERROR StartResponseTimer();

    void CancelResponseTimer();
    static void HandleResponseTimeout(System::Layer * aSystemLayer, void * aAppState);

    void DoClose(bool clearRetransTable);

    /**
     * We have handled an application-level message in some way and should
     * re-evaluate out state to see whether we should still be open.
     */
    void MessageHandled();

    static ExchangeMessageDispatch & GetMessageDispatch(bool isEphemeralExchange, ExchangeDelegate * delegate);

    // If SetAutoReleaseSession() is called, this exchange must be using a SecureSession, and should
    // evict it when the exchange is done with all its work (including any MRP traffic).
    inline void SetIgnoreSessionRelease(bool ignore) { mFlags.Set(Flags::kFlagIgnoreSessionRelease, ignore); }

    inline bool ShouldIgnoreSessionRelease() { return mFlags.Has(Flags::kFlagIgnoreSessionRelease); }

    inline void SetHasReceivedAtLeastOneMessage(bool hasReceivedMessage)
    {
        mFlags.Set(Flags::kFlagReceivedAtLeastOneMessage, hasReceivedMessage);
    }
};

} // namespace Messaging
} // namespace chip
