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

#include <app/CASESessionManager.h>
#include <lib/address_resolve/AddressResolve.h>

namespace chip {

CHIP_ERROR CASESessionManager::Init(chip::System::Layer * systemLayer, const CASESessionManagerConfig & params)
{
    ReturnErrorOnFailure(params.sessionInitParams.Validate());
    mConfig = params;
    params.sessionInitParams.exchangeMgr->GetReliableMessageMgr()->RegisterSessionUpdateDelegate(this);
    return AddressResolve::Resolver::Instance().Init(systemLayer);
}

void CASESessionManager::Shutdown()
{
    AddressResolve::Resolver::Instance().Shutdown();
}

void CASESessionManager::FindOrEstablishSession(const ScopedNodeId & peerId, Callback::Callback<OnDeviceConnected> * onConnection,
                                                Callback::Callback<OnDeviceConnectionFailure> * onFailure,
#if CHIP_DEVICE_CONFIG_ENABLE_AUTOMATIC_CASE_RETRIES
                                                uint8_t attemptCount, Callback::Callback<OnDeviceConnectionRetry> * onRetry,
#endif // CHIP_DEVICE_CONFIG_ENABLE_AUTOMATIC_CASE_RETRIES
                                                TransportPayloadCapability transportPayloadCapability,
                                                const Optional<AddressResolve::ResolveResult> & fallbackResolveResult)
{
    FindOrEstablishSessionHelper(peerId, onConnection, onFailure, nullptr,
#if CHIP_DEVICE_CONFIG_ENABLE_AUTOMATIC_CASE_RETRIES
                                 attemptCount, onRetry,
#endif
                                 transportPayloadCapability, fallbackResolveResult);
}

void CASESessionManager::FindOrEstablishSession(const ScopedNodeId & peerId, Callback::Callback<OnDeviceConnected> * onConnection,
                                                Callback::Callback<OperationalSessionSetup::OnSetupFailure> * onSetupFailure,
#if CHIP_DEVICE_CONFIG_ENABLE_AUTOMATIC_CASE_RETRIES
                                                uint8_t attemptCount, Callback::Callback<OnDeviceConnectionRetry> * onRetry,
#endif
                                                TransportPayloadCapability transportPayloadCapability)
{
    FindOrEstablishSessionHelper(peerId, onConnection, nullptr, onSetupFailure,
#if CHIP_DEVICE_CONFIG_ENABLE_AUTOMATIC_CASE_RETRIES
                                 attemptCount, onRetry,
#endif
                                 transportPayloadCapability);
}

void CASESessionManager::FindOrEstablishSession(const ScopedNodeId & peerId, Callback::Callback<OnDeviceConnected> * onConnection,
                                                std::nullptr_t,
#if CHIP_DEVICE_CONFIG_ENABLE_AUTOMATIC_CASE_RETRIES
                                                uint8_t attemptCount, Callback::Callback<OnDeviceConnectionRetry> * onRetry,
#endif
                                                TransportPayloadCapability transportPayloadCapability)
{
    FindOrEstablishSessionHelper(peerId, onConnection, nullptr, nullptr,
#if CHIP_DEVICE_CONFIG_ENABLE_AUTOMATIC_CASE_RETRIES
                                 attemptCount, onRetry,
#endif
                                 transportPayloadCapability);
}

void CASESessionManager::FindOrEstablishSession(const ScopedNodeId & peerId, Callback::Callback<OnDeviceConnected> * onConnection,
                                                Callback::Callback<OnDeviceConnectionFailure> * onFailure,
                                                TransportPayloadCapability transportPayloadCapability)
{
    FindOrEstablishSessionHelper(peerId, onConnection, onFailure, nullptr,
#if CHIP_DEVICE_CONFIG_ENABLE_AUTOMATIC_CASE_RETRIES
                                 1 /* attemptCount */, nullptr /* onRetry */,
#endif
                                 transportPayloadCapability);
}

void CASESessionManager::FindOrEstablishSessionHelper(const ScopedNodeId & peerId,
                                                      Callback::Callback<OnDeviceConnected> * onConnection,
                                                      Callback::Callback<OnDeviceConnectionFailure> * onFailure,
                                                      Callback::Callback<OperationalSessionSetup::OnSetupFailure> * onSetupFailure,
#if CHIP_DEVICE_CONFIG_ENABLE_AUTOMATIC_CASE_RETRIES
                                                      uint8_t attemptCount, Callback::Callback<OnDeviceConnectionRetry> * onRetry,
#endif
                                                      TransportPayloadCapability transportPayloadCapability,
                                                      const Optional<AddressResolve::ResolveResult> & fallbackResolveResult)
{
    ChipLogDetail(CASESessionManager, "FindOrEstablishSession: PeerId = [%d:" ChipLogFormatX64 "]", peerId.GetFabricIndex(),
                  ChipLogValueX64(peerId.GetNodeId()));

    bool forAddressUpdate             = false;
    OperationalSessionSetup * session = FindExistingSessionSetup(peerId, forAddressUpdate);
    if (session == nullptr)
    {
        ChipLogDetail(CASESessionManager, "FindOrEstablishSession: No existing OperationalSessionSetup instance found");
        session = mConfig.sessionSetupPool->Allocate(mConfig.sessionInitParams, mConfig.clientPool, peerId, this);

        if (session == nullptr)
        {
            if (onFailure != nullptr)
            {
                onFailure->mCall(onFailure->mContext, peerId, CHIP_ERROR_NO_MEMORY);
            }

            if (onSetupFailure != nullptr)
            {
                OperationalSessionSetup::ConnectionFailureInfo failureInfo(peerId, CHIP_ERROR_NO_MEMORY,
                                                                           SessionEstablishmentStage::kUnknown);
                onSetupFailure->mCall(onSetupFailure->mContext, failureInfo);
            }
            return;
        }
    }

#if CHIP_DEVICE_CONFIG_ENABLE_AUTOMATIC_CASE_RETRIES
    session->UpdateAttemptCount(attemptCount);
    if (onRetry)
    {
        session->AddRetryHandler(onRetry);
    }
#endif // CHIP_DEVICE_CONFIG_ENABLE_AUTOMATIC_CASE_RETRIES

#if CHIP_CONFIG_ENABLE_ADDRESS_RESOLVE_FALLBACK
    // Set fallback resolve result if provided
    if (fallbackResolveResult.HasValue())
    {
        session->SetFallbackResolveResult(fallbackResolveResult.Value());
    }
#endif // CHIP_CONFIG_ENABLE_ADDRESS_RESOLVE_FALLBACK

    if (onFailure != nullptr)
    {
        session->Connect(onConnection, onFailure, transportPayloadCapability);
    }

    if (onSetupFailure != nullptr)
    {
        session->Connect(onConnection, onSetupFailure, transportPayloadCapability);
    }
}

void CASESessionManager::ReleaseSessionsForFabric(FabricIndex fabricIndex)
{
    mConfig.sessionSetupPool->ReleaseAllSessionSetupsForFabric(fabricIndex);
}

void CASESessionManager::ReleaseAllSessions()
{
    mConfig.sessionSetupPool->ReleaseAllSessionSetup();
}

CHIP_ERROR CASESessionManager::GetPeerAddress(const ScopedNodeId & peerId, Transport::PeerAddress & addr,
                                              TransportPayloadCapability transportPayloadCapability)
{
    ReturnErrorOnFailure(mConfig.sessionInitParams.Validate());
    auto optionalSessionHandle = FindExistingSession(peerId, transportPayloadCapability);
    VerifyOrReturnError(optionalSessionHandle.HasValue(), CHIP_ERROR_NOT_CONNECTED);
    addr = optionalSessionHandle.Value()->AsSecureSession()->GetPeerAddress();
    return CHIP_NO_ERROR;
}

void CASESessionManager::UpdatePeerAddress(ScopedNodeId peerId)
{
    bool forAddressUpdate             = true;
    OperationalSessionSetup * session = FindExistingSessionSetup(peerId, forAddressUpdate);
    if (session == nullptr)
    {
        ChipLogDetail(CASESessionManager, "UpdatePeerAddress: No existing OperationalSessionSetup instance found");

        session = mConfig.sessionSetupPool->Allocate(mConfig.sessionInitParams, mConfig.clientPool, peerId, this);
        if (session == nullptr)
        {
            ChipLogDetail(CASESessionManager, "UpdatePeerAddress: Failed to allocate OperationalSessionSetup instance");
            return;
        }
    }
    else
    {
        ChipLogDetail(CASESessionManager,
                      "UpdatePeerAddress: Found existing OperationalSessionSetup instance for peerId[" ChipLogFormatX64 "]",
                      ChipLogValueX64(peerId.GetNodeId()));
    }

    session->PerformAddressUpdate();
}

OperationalSessionSetup * CASESessionManager::FindExistingSessionSetup(const ScopedNodeId & peerId, bool forAddressUpdate) const
{
    return mConfig.sessionSetupPool->FindSessionSetup(peerId, forAddressUpdate);
}

Optional<SessionHandle> CASESessionManager::FindExistingSession(const ScopedNodeId & peerId,
                                                                const TransportPayloadCapability transportPayloadCapability) const
{
    return mConfig.sessionInitParams.sessionManager->FindSecureSessionForNode(
        peerId, MakeOptional(Transport::SecureSession::Type::kCASE), transportPayloadCapability);
}

void CASESessionManager::ReleaseSession(const ScopedNodeId & peerId)
{
    auto * session = mConfig.sessionSetupPool->FindSessionSetup(peerId, false);
    ReleaseSession(session);
}

void CASESessionManager::ReleaseSession(OperationalSessionSetup * session)
{
    if (session != nullptr)
    {
        mConfig.sessionSetupPool->Release(session);
    }
}

} // namespace chip
