/*
 *
 *    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.
 */

/**
 * @brief Defines state relevant for an active connection to a peer.
 */

#pragma once

#include <app/util/basic-types.h>
#include <ble/Ble.h>
#include <lib/core/ReferenceCounted.h>
#include <messaging/ReliableMessageProtocolConfig.h>
#include <transport/CryptoContext.h>
#include <transport/Session.h>
#include <transport/SessionMessageCounter.h>
#include <transport/raw/PeerAddress.h>

namespace chip {
namespace Transport {

class SecureSessionTable;
class SecureSessionDeleter
{
public:
    static void Release(SecureSession * entry);
};

/**
 * Defines state of a peer connection at a transport layer.
 *
 * Information contained within the state:
 *   - SecureSessionType represents CASE or PASE session
 *   - PeerAddress represents how to talk to the peer
 *   - PeerNodeId is the unique ID of the peer
 *   - PeerCATs represents CASE Authenticated Tags
 *   - SendMessageIndex is an ever increasing index for sending messages
 *   - LastActivityTime is a monotonic timestamp of when this connection was
 *     last used. Inactive connections can expire.
 *   - CryptoContext contains the encryption context of a connection
 */
class SecureSession : public Session, public ReferenceCounted<SecureSession, SecureSessionDeleter, 0, uint16_t>
{
public:
    /**
     *  @brief
     *    Defines SecureSession Type. Currently supported types are PASE and CASE.
     */
    enum class Type : uint8_t
    {
        kPASE = 1,
        kCASE = 2,
    };

    // Test-only: inject a session in Active state.
    // TODO: Tests should allocate a pending session and then call Activate(), just like non-test code does.
    SecureSession(SecureSessionTable & table, Type secureSessionType, uint16_t localSessionId, NodeId localNodeId,
                  NodeId peerNodeId, CATValues peerCATs, uint16_t peerSessionId, FabricIndex fabric,
                  const ReliableMessageProtocolConfig & config) :
        mTable(table),
        mState(State::kEstablishing), mSecureSessionType(secureSessionType), mLocalNodeId(localNodeId), mPeerNodeId(peerNodeId),
        mPeerCATs(peerCATs), mLocalSessionId(localSessionId), mPeerSessionId(peerSessionId), mRemoteSessionParams(config)
    {
        MoveToState(State::kActive);
        Retain(); // Put the test session in Active state. This ref is released inside MarkForEviction
        SetFabricIndex(fabric);
        ChipLogDetail(Inet, "SecureSession[%p]: Allocated for Test Type:%d LSID:%d", this, to_underlying(mSecureSessionType),
                      mLocalSessionId);
    }

    /**
     * @brief
     *   Construct a secure session object to associate with a pending secure
     *   session establishment attempt.  The object for the pending session
     *   receives a local session ID, but no other state.
     */
    SecureSession(SecureSessionTable & table, Type secureSessionType, uint16_t localSessionId) :
        mTable(table), mState(State::kEstablishing), mSecureSessionType(secureSessionType), mLocalSessionId(localSessionId)
    {
        ChipLogDetail(Inet, "SecureSession[%p]: Allocated Type:%d LSID:%d", this, to_underlying(mSecureSessionType),
                      mLocalSessionId);
    }

    /**
     * @brief
     *   Activate a pending Secure Session that had been reserved during CASE or
     *   PASE, setting internal state according to the parameters used and
     *   discovered during session establishment.
     */
    void Activate(const ScopedNodeId & localNode, const ScopedNodeId & peerNode, CATValues peerCATs, uint16_t peerSessionId,
                  const SessionParameters & sessionParameters);

    ~SecureSession() override
    {
        ChipLogDetail(Inet, "SecureSession[%p]: Released - Type:%d LSID:%d", this, to_underlying(mSecureSessionType),
                      mLocalSessionId);
    }

    SecureSession(SecureSession &&)                  = delete;
    SecureSession(const SecureSession &)             = delete;
    SecureSession & operator=(const SecureSession &) = delete;
    SecureSession & operator=(SecureSession &&)      = delete;

    void Retain() override;
    void Release() override;

    bool IsActiveSession() const override { return mState == State::kActive; }
    bool IsEstablishing() const { return mState == State::kEstablishing; }
    bool IsPendingEviction() const { return mState == State::kPendingEviction; }
    bool IsDefunct() const { return mState == State::kDefunct; }
    const char * GetStateStr() const { return StateToString(mState); }

    /*
     * This marks the session for eviction. It will first detach all SessionHolders attached to this
     * session by calling 'OnSessionReleased' on each of them. This will force them to release their reference
     * to the session. If there are no more references left, the session will then be de-allocated.
     *
     * Once marked for eviction, the session SHALL NOT ever become active again.
     *
     */
    void MarkForEviction();

    /*
     * This marks a previously active session as defunct to temporarily prevent it from being used with
     * new exchanges to send or receive messages on this session. This should be called when there is suspicion of
     * a loss-of-sync with the session state on the associated peer. This could arise if there is evidence
     * of transport failure.
     *
     * If messages are received thereafter on this session, the session SHALL be put back into the Active state.
     *
     * This SHALL only be callable on an active session.
     * This SHALL NOT detach any existing SessionHolders.
     *
     */
    void MarkAsDefunct();

    Session::SessionType GetSessionType() const override { return Session::SessionType::kSecure; }

    ScopedNodeId GetPeer() const override { return ScopedNodeId(mPeerNodeId, GetFabricIndex()); }

    ScopedNodeId GetLocalScopedNodeId() const override { return ScopedNodeId(mLocalNodeId, GetFabricIndex()); }

    Access::SubjectDescriptor GetSubjectDescriptor() const override;

    bool IsCommissioningSession() const override;

    bool AllowsMRP() const override
    {
        return ((GetPeerAddress().GetTransportType() == Transport::Type::kUdp) ||
                (GetPeerAddress().GetTransportType() == Transport::Type::kWiFiPAF));
    }

    bool AllowsLargePayload() const override { return GetPeerAddress().GetTransportType() == Transport::Type::kTcp; }

    System::Clock::Milliseconds32 GetAckTimeout() const override
    {
        switch (mPeerAddress.GetTransportType())
        {
        case Transport::Type::kUdp: {
            const ReliableMessageProtocolConfig & remoteMRPConfig = mRemoteSessionParams.GetMRPConfig();
            return GetRetransmissionTimeout(remoteMRPConfig.mActiveRetransTimeout, remoteMRPConfig.mIdleRetransTimeout,
                                            GetLastPeerActivityTime(), remoteMRPConfig.mActiveThresholdTime);
        }
        case Transport::Type::kTcp:
            return System::Clock::Seconds16(30);
        case Transport::Type::kBle:
            return System::Clock::Milliseconds32(BTP_ACK_TIMEOUT_MS);
        default:
            break;
        }
        return System::Clock::Timeout();
    }

    System::Clock::Milliseconds32 GetMessageReceiptTimeout(System::Clock::Timestamp ourLastActivity) const override
    {
        switch (mPeerAddress.GetTransportType())
        {
        case Transport::Type::kUdp: {
            const auto & maybeLocalMRPConfig = GetLocalMRPConfig();
            const auto & defaultMRRPConfig   = GetDefaultMRPConfig();
            const auto & localMRPConfig      = maybeLocalMRPConfig.ValueOr(defaultMRRPConfig);
            return GetRetransmissionTimeout(localMRPConfig.mActiveRetransTimeout, localMRPConfig.mIdleRetransTimeout,
                                            ourLastActivity, localMRPConfig.mActiveThresholdTime);
        }
        case Transport::Type::kTcp:
            return System::Clock::Seconds16(30);
        case Transport::Type::kBle:
            return System::Clock::Milliseconds32(BTP_ACK_TIMEOUT_MS);
        default:
            break;
        }
        return System::Clock::Timeout();
    }

    const PeerAddress & GetPeerAddress() const { return mPeerAddress; }
    void SetPeerAddress(const PeerAddress & address) { mPeerAddress = address; }

    Type GetSecureSessionType() const { return mSecureSessionType; }
    bool IsCASESession() const { return GetSecureSessionType() == Type::kCASE; }
    bool IsPASESession() const { return GetSecureSessionType() == Type::kPASE; }
    NodeId GetPeerNodeId() const { return mPeerNodeId; }
    NodeId GetLocalNodeId() const { return mLocalNodeId; }

    const CATValues & GetPeerCATs() const { return mPeerCATs; }

    void SetRemoteSessionParameters(const SessionParameters & sessionParams) { mRemoteSessionParams = sessionParams; }

    const SessionParameters & GetRemoteSessionParameters() const override { return mRemoteSessionParams; }

    uint16_t GetLocalSessionId() const { return mLocalSessionId; }
    uint16_t GetPeerSessionId() const { return mPeerSessionId; }

    // Called when AddNOC has gone through sufficient success that we need to switch the
    // session to reflect a new fabric if it was a PASE session
    CHIP_ERROR AdoptFabricIndex(FabricIndex fabricIndex)
    {
        // It's not legal to augment session type for non-PASE
        if (mSecureSessionType != Type::kPASE)
        {
            return CHIP_ERROR_INVALID_ARGUMENT;
        }
        SetFabricIndex(fabricIndex);
        return CHIP_NO_ERROR;
    }

    System::Clock::Timestamp GetLastActivityTime() const { return mLastActivityTime; }
    System::Clock::Timestamp GetLastPeerActivityTime() const { return mLastPeerActivityTime; }
    void MarkActive() { mLastActivityTime = System::SystemClock().GetMonotonicTimestamp(); }
    void MarkActiveRx()
    {
        mLastPeerActivityTime = System::SystemClock().GetMonotonicTimestamp();
        MarkActive();

        if (mState == State::kDefunct)
        {
            MoveToState(State::kActive);
        }
    }

    void SetCaseCommissioningSessionStatus(bool isCaseCommissioningSession)
    {
        VerifyOrDie(GetSecureSessionType() == Type::kCASE);
        mIsCaseCommissioningSession = isCaseCommissioningSession;
    }

    bool IsPeerActive() const
    {
        return ((System::SystemClock().GetMonotonicTimestamp() - GetLastPeerActivityTime()) <
                GetRemoteMRPConfig().mActiveThresholdTime);
    }

    System::Clock::Timestamp GetMRPBaseTimeout() const override
    {
        return IsPeerActive() ? GetRemoteMRPConfig().mActiveRetransTimeout : GetRemoteMRPConfig().mIdleRetransTimeout;
    }

    CryptoContext & GetCryptoContext() { return mCryptoContext; }

    const CryptoContext & GetCryptoContext() const { return mCryptoContext; }

    SessionMessageCounter & GetSessionMessageCounter() { return mSessionMessageCounter; }

    // This should be a private API, only meant to be called by SecureSessionTable
    // Session holders to this session may shift to the target session regarding SessionDelegate::GetNewSessionHandlingPolicy.
    // It requires that the target sessoin is also a CASE session, having the same peer and CATs as this session.
    void NewerSessionAvailable(const SessionHandle & session);

private:
    enum class State : uint8_t
    {
        //
        // Denotes a secure session object that is internally
        // reserved by the stack before and during session establishment.
        //
        // Although the stack can tolerate eviction of these (releasing one
        // out from under the holder would exhibit as CHIP_ERROR_INCORRECT_STATE
        // during CASE or PASE), intent is that we should not and would leave
        // these untouched until CASE or PASE complete.
        //
        // In this state, the reference count is held by the PairingSession.
        //
        kEstablishing = 1,

        //
        // The session is active, ready for use. When transitioning to this state via Activate, the
        // reference count is incremented by 1, and will subsequently be decremented
        // by 1 when MarkForEviction is called. This ensures the session remains resident
        // and active for future use even if there currently are no references to it.
        //
        kActive = 2,

        //
        // The session is temporarily disabled due to suspicion of a loss of synchronization
        // with the session state on the peer (e.g transport failure).
        // In this state, no new outbound exchanges can be created. However, if we receive valid messages
        // again on this session, we CAN mark this session as being active again.
        //
        // Transitioning to this state does not detach any existing SessionHolders.
        //
        // In addition to any existing SessionHolders holding a reference to this session, the SessionManager
        // maintains a reference as well to the session that will only be relinquished when MarkForEviction is called.
        //
        kDefunct = 3,

        //
        // The session has been marked for eviction and is pending deallocation. All SessionHolders would have already
        // been detached in a previous call to MarkForEviction. Future SessionHolders will not be able to attach to
        // this session.
        //
        // When all SessionHandles go out of scope, the session will be released automatically.
        //
        kPendingEviction = 4,
    };

    const char * StateToString(State state) const;
    void MoveToState(State targetState);

    friend class SecureSessionDeleter;
    friend class TestSecureSessionTable;

    SecureSessionTable & mTable;
    State mState;
    const Type mSecureSessionType;
    bool mIsCaseCommissioningSession = false;
    NodeId mLocalNodeId              = kUndefinedNodeId;
    NodeId mPeerNodeId               = kUndefinedNodeId;
    CATValues mPeerCATs              = CATValues{};
    const uint16_t mLocalSessionId;
    uint16_t mPeerSessionId = 0;

    PeerAddress mPeerAddress;

    /// Timestamp of last tx or rx. @see SessionTimestamp in the spec
    System::Clock::Timestamp mLastActivityTime = System::SystemClock().GetMonotonicTimestamp();

    /// Timestamp of last rx. @see ActiveTimestamp in the spec
    System::Clock::Timestamp mLastPeerActivityTime = System::SystemClock().GetMonotonicTimestamp();

    SessionParameters mRemoteSessionParams;
    CryptoContext mCryptoContext;
    SessionMessageCounter mSessionMessageCounter;
};

} // namespace Transport
} // namespace chip
