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

#include <app-common/zap-generated/attributes/Accessors.h>
#include <app-common/zap-generated/ids/Attributes.h>
#include <app-common/zap-generated/ids/Clusters.h>
#include <app/icd/server/ICDConfigurationData.h>
#include <app/icd/server/ICDManager.h>
#include <app/icd/server/ICDServerConfig.h>
#include <lib/core/ClusterEnums.h>
#include <lib/support/CodeUtils.h>
#include <lib/support/logging/CHIPLogging.h>
#include <platform/ConnectivityManager.h>
#include <platform/LockTracker.h>
#include <platform/internal/CHIPDeviceLayerInternal.h>

namespace {
enum class ICDTestEventTriggerEvent : uint64_t
{
    kAddActiveModeReq            = 0x0046'0000'00000001,
    kRemoveActiveModeReq         = 0x0046'0000'00000002,
    kInvalidateHalfCounterValues = 0x0046'0000'00000003,
    kInvalidateAllCounterValues  = 0x0046'0000'00000004,
};
} // namespace

namespace chip {
namespace app {

using namespace chip::app;
using namespace chip::app::Clusters;
using namespace chip::app::Clusters::IcdManagement;
using namespace System::Clock;

using chip::Protocols::InteractionModel::Status;

static_assert(UINT8_MAX >= CHIP_CONFIG_MAX_EXCHANGE_CONTEXTS,
              "ICDManager::mOpenExchangeContextCount cannot hold count for the max exchange count");

void ICDManager::Init(PersistentStorageDelegate * storage, FabricTable * fabricTable, Crypto::SymmetricKeystore * symmetricKeystore,
                      Messaging::ExchangeManager * exchangeManager, SubscriptionsInfoProvider * subInfoProvider)
{
#if CHIP_CONFIG_ENABLE_ICD_CIP
    VerifyOrDie(storage != nullptr);
    VerifyOrDie(fabricTable != nullptr);
    VerifyOrDie(symmetricKeystore != nullptr);
    VerifyOrDie(exchangeManager != nullptr);
    VerifyOrDie(subInfoProvider != nullptr);
#endif // CHIP_CONFIG_ENABLE_ICD_CIP

#if CHIP_CONFIG_ENABLE_ICD_LIT
    // LIT ICD Verification Checks
    if (SupportsFeature(Feature::kLongIdleTimeSupport))
    {
        VerifyOrDieWithMsg(SupportsFeature(Feature::kCheckInProtocolSupport), AppServer,
                           "The CheckIn protocol feature is required for LIT support.");
        VerifyOrDieWithMsg(SupportsFeature(Feature::kUserActiveModeTrigger), AppServer,
                           "The user ActiveMode trigger feature is required for LIT support.");
        VerifyOrDieWithMsg(ICDConfigurationData::GetInstance().GetMinLitActiveModeThreshold() <=
                               ICDConfigurationData::GetInstance().GetActiveModeThreshold(),
                           AppServer, "The minimum ActiveModeThreshold value for a LIT ICD is 5 seconds.");
        // Disabling check until LIT support is compelte
        // VerifyOrDieWithMsg((GetSlowPollingInterval() <= GetSITPollingThreshold()) , AppServer,
        //                    "LIT support is required for slow polling intervals superior to 15 seconds");
    }
#endif // CHIP_CONFIG_ENABLE_ICD_LIT

    VerifyOrDie(ICDNotifier::GetInstance().Subscribe(this) == CHIP_NO_ERROR);

#if CHIP_CONFIG_ENABLE_ICD_CIP
    mStorage           = storage;
    mFabricTable       = fabricTable;
    mSymmetricKeystore = symmetricKeystore;
    mExchangeManager   = exchangeManager;
    mSubInfoProvider   = subInfoProvider;

    VerifyOrDie(ICDConfigurationData::GetInstance().GetICDCounter().Init(mStorage, DefaultStorageKeyAllocator::ICDCheckInCounter(),
                                                                         ICDConfigurationData::kICDCounterPersistenceIncrement) ==
                CHIP_NO_ERROR);
#endif // CHIP_CONFIG_ENABLE_ICD_CIP

    UpdateICDMode();
    UpdateOperationState(OperationalState::IdleMode);
}

void ICDManager::Shutdown()
{
    ICDNotifier::GetInstance().Unsubscribe(this);

    // cancel any running timer of the icd
    DeviceLayer::SystemLayer().CancelTimer(OnIdleModeDone, this);
    DeviceLayer::SystemLayer().CancelTimer(OnActiveModeDone, this);
    DeviceLayer::SystemLayer().CancelTimer(OnTransitionToIdle, this);

    ICDConfigurationData::GetInstance().SetICDMode(ICDConfigurationData::ICDMode::SIT);
    mOperationalState = OperationalState::ActiveMode;
    mStateObserverPool.ReleaseAll();

#if CHIP_CONFIG_ENABLE_ICD_CIP
    mStorage         = nullptr;
    mFabricTable     = nullptr;
    mSubInfoProvider = nullptr;
    mICDSenderPool.ReleaseAll();

#if CHIP_CONFIG_PERSIST_SUBSCRIPTIONS && !CHIP_CONFIG_SUBSCRIPTION_TIMEOUT_RESUMPTION
    mIsBootUpResumeSubscriptionExecuted = false;
#endif // CHIP_CONFIG_PERSIST_SUBSCRIPTIONS && !CHIP_CONFIG_SUBSCRIPTION_TIMEOUT_RESUMPTION
#endif // CHIP_CONFIG_ENABLE_ICD_CIP
}

bool ICDManager::SupportsFeature(Feature feature)
{
    // Can't use attribute accessors/Attributes::FeatureMap::Get in unit tests
#if !CONFIG_BUILD_FOR_HOST_UNIT_TEST
    uint32_t featureMap = 0;
    bool success        = (Attributes::FeatureMap::Get(kRootEndpointId, &featureMap) == Status::Success);
    return success ? ((featureMap & to_underlying(feature)) != 0) : false;
#else
    return ((mFeatureMap & to_underlying(feature)) != 0);
#endif // !CONFIG_BUILD_FOR_HOST_UNIT_TEST
}

uint32_t ICDManager::StayActiveRequest(uint32_t stayActiveDuration)
{
    // This should only be called when the device is in ActiveMode
    VerifyOrReturnValue(mOperationalState == OperationalState::ActiveMode, 0);

    uint32_t promisedActiveDuration =
        std::min(ICDConfigurationData::GetInstance().GetGuaranteedStayActiveDuration().count(), stayActiveDuration);

    // If the device is already in ActiveMode, we need to extend the active mode duration
    // for whichever is smallest between 30000 milliseconds and stayActiveDuration, taking in account the remaining active time.
    ExtendActiveMode(System::Clock::Milliseconds16(promisedActiveDuration));
    promisedActiveDuration = DeviceLayer::SystemLayer().GetRemainingTime(OnActiveModeDone, this).count();

    return promisedActiveDuration;
}

#if CHIP_CONFIG_ENABLE_ICD_CIP
void ICDManager::SendCheckInMsgs()
{
#if !CONFIG_BUILD_FOR_HOST_UNIT_TEST
    VerifyOrDie(mStorage != nullptr);
    VerifyOrDie(mFabricTable != nullptr);

    uint32_t counterValue   = ICDConfigurationData::GetInstance().GetICDCounter().GetNextCheckInCounterValue();
    bool counterIncremented = false;

    for (const auto & fabricInfo : *mFabricTable)
    {
        uint16_t supported_clients = ICDConfigurationData::GetInstance().GetClientsSupportedPerFabric();

        ICDMonitoringTable table(*mStorage, fabricInfo.GetFabricIndex(), supported_clients /*Table entry limit*/,
                                 mSymmetricKeystore);

        if (table.IsEmpty())
        {
            continue;
        }

        for (uint16_t i = 0; i < table.Limit(); i++)
        {
            ICDMonitoringEntry entry(mSymmetricKeystore);
            CHIP_ERROR err = table.Get(i, entry);
            if (err == CHIP_ERROR_NOT_FOUND)
            {
                break;
            }

            if (err != CHIP_NO_ERROR)
            {
                // Try to fetch the next entry upon failure (should not happen).
                ChipLogError(AppServer, "Failed to retrieved ICDMonitoring entry for Check-In msg, will try next entry.");
                continue;
            }

            if (entry.clientType == ClientTypeEnum::kEphemeral)
            {
                // If the registered client is ephemeral, do not send a Check-In message
                // continue to next entry
                continue;
            }

            if (!ShouldCheckInMsgsBeSentAtActiveModeFunction(entry.fabricIndex, entry.monitoredSubject))
            {
                continue;
            }

            // Increment counter only once to prevent depletion of the available range.
            if (!counterIncremented)
            {
                counterIncremented = true;

                if (CHIP_NO_ERROR != ICDConfigurationData::GetInstance().GetICDCounter().Advance())
                {
                    ChipLogError(AppServer, "Incremented ICDCounter but failed to access/save to Persistent storage");
                }
            }

            // SenderPool will be released upon transition from active to idle state
            // This will happen when all ICD Check-In messages are sent on the network
            ICDCheckInSender * sender = mICDSenderPool.CreateObject(mExchangeManager);
            VerifyOrReturn(sender != nullptr, ChipLogError(AppServer, "Failed to allocate ICDCheckinSender"));

            if (CHIP_NO_ERROR != sender->RequestResolve(entry, mFabricTable, counterValue))
            {
                ChipLogError(AppServer, "Failed to send ICD Check-In");
            }
        }
    }
#endif // CONFIG_BUILD_FOR_HOST_UNIT_TEST
}

bool ICDManager::CheckInMessagesWouldBeSent(const std::function<ShouldCheckInMsgsBeSentFunction> & shouldCheckInMsgsBeSentFunction)
{
    VerifyOrReturnValue(shouldCheckInMsgsBeSentFunction, false);

    for (const auto & fabricInfo : *mFabricTable)
    {
        uint16_t supported_clients = ICDConfigurationData::GetInstance().GetClientsSupportedPerFabric();

        ICDMonitoringTable table(*mStorage, fabricInfo.GetFabricIndex(), supported_clients /*Table entry limit*/,
                                 mSymmetricKeystore);
        if (table.IsEmpty())
        {
            continue;
        }

        for (uint16_t i = 0; i < table.Limit(); i++)
        {
            ICDMonitoringEntry entry(mSymmetricKeystore);
            CHIP_ERROR err = table.Get(i, entry);
            if (err == CHIP_ERROR_NOT_FOUND)
            {
                break;
            }

            if (err != CHIP_NO_ERROR)
            {
                // Try to fetch the next entry upon failure (should not happen).
                ChipLogError(AppServer, "Failed to retrieved ICDMonitoring entry, will try next entry.");
                continue;
            }

            if (entry.clientType == ClientTypeEnum::kEphemeral)
            {
                // If the registered client is ephemeral, no Check-In message would be sent to this client
                continue;
            }

            // At least one registration would require a Check-In message
            VerifyOrReturnValue(!shouldCheckInMsgsBeSentFunction(entry.fabricIndex, entry.monitoredSubject), true);
        }
    }

    // None of the registrations would require a Check-In message
    return false;
}

/**
 * ShouldCheckInMsgsBeSentAtActiveModeFunction is used to determine if a Check-In message is required for a given registration.
 * Due to how the ICD Check-In use-case interacts with the persistent subscription and subscription timeout resumption features,
 * having a single implementation of the function renders the implementation very difficult to understand and maintain.
 * Because of this, each valid feature combination has its own implementation of the function.
 */
#if CHIP_CONFIG_PERSIST_SUBSCRIPTIONS
#if CHIP_CONFIG_SUBSCRIPTION_TIMEOUT_RESUMPTION
/**
 * @brief Implementation for when the persistent subscription and subscription timeout resumption feature are present.
 *        Function checks that there are no active or persisted subscriptions for a given fabricIndex or subjectID.
 *
 * @note When the persistent subscription and subscription timeout resumption feature are present, we need to check for
 *       persisted subscription at each transition to ActiveMode since there will be persisted subscriptions during normal
 *       operation for the subscription timeout resumption feature. Once we have finished all our subscription resumption attempts
 *       for a given subscription, the entry is deleted from persisted storage which will enable us to send Check-In messages for
 *       the client registration. This logic avoids the device sending a Check-In message while trying to resume subscriptions.
 *
 * @param aFabricIndex
 * @param subjectID subjectID to check. Can be an operational node id or a CAT
 *
 * @return true Returns true if the fabricIndex and subjectId combination does not have an active or a persisted subscription.
 * @return false Returns false if the fabricIndex and subjectId combination has an active or persisted subscription.
 */
bool ICDManager::ShouldCheckInMsgsBeSentAtActiveModeFunction(FabricIndex aFabricIndex, NodeId subjectID)
{
    return !(mSubInfoProvider->SubjectHasActiveSubscription(aFabricIndex, subjectID) ||
             mSubInfoProvider->SubjectHasPersistedSubscription(aFabricIndex, subjectID));
}
#else
/**
 * @brief Implementation for when the persistent subscription feature is present without the subscription timeout resumption
 * feature. Function checks that there are no active subscriptions. If the boot up subscription resumption has not been completed,
 *        function also checks if there are persisted subscriptions.
 *
 * @note The persistent subscriptions feature tries to resume subscriptions at the highest min interval
 *       of all the persisted subscriptions. As such, it is possible for the ICD to return to Idle Mode
 *       until the timer elaspses. We do not want to send Check-In messages to clients with persisted subscriptions
 *       until we have tried to resubscribe.
 *
 * @param aFabricIndex
 * @param subjectID subjectID to check. Can be an opperationnal node id or a CAT
 *
 * @return true Returns true if the fabricIndex and subjectId combination does not have an active subscription.
 *              If the boot up subscription resumption has not been completed, there must not be a persisted subscription either.
 * @return false Returns false if the fabricIndex and subjectId combination has an active subscription.
 *               If the boot up subscription resumption has not been completed,
 *               returns false if the fabricIndex and subjectId combination has a persisted subscription.
 */
bool ICDManager::ShouldCheckInMsgsBeSentAtActiveModeFunction(FabricIndex aFabricIndex, NodeId subjectID)
{
    bool mightHaveSubscription = mSubInfoProvider->SubjectHasActiveSubscription(aFabricIndex, subjectID);
    if (!mightHaveSubscription && !mIsBootUpResumeSubscriptionExecuted)
    {
        mightHaveSubscription = mSubInfoProvider->SubjectHasPersistedSubscription(aFabricIndex, subjectID);
    }

    return !mightHaveSubscription;
}
#endif // CHIP_CONFIG_SUBSCRIPTION_TIMEOUT_RESUMPTION
#else
/**
 * @brief Implementation for when neither the persistent subscription nor the subscription timeout resumption features are present.
 *        Function checks that there no active sbuscriptions for a given fabricIndex and subjectId combination.
 *
 * @note When neither the persistent subscription nor the subscription timeout resumption features are present, we only need to
 *       check for active subscription since we will never have any persisted subscription.
 *
 * @param aFabricIndex
 * @param subjectID subjectID to check. Can be an opperationnal node id or a CAT
 *
 * @return true Returns true if the fabricIndex and subjectId combination does not have an active subscription.
 * @return false Returns false if the fabricIndex and subjectId combination has an active subscription.
 */
bool ICDManager::ShouldCheckInMsgsBeSentAtActiveModeFunction(FabricIndex aFabricIndex, NodeId subjectID)
{
    return !(mSubInfoProvider->SubjectHasActiveSubscription(aFabricIndex, subjectID));
}
#endif // CHIP_CONFIG_PERSIST_SUBSCRIPTIONS

void ICDManager::TriggerCheckInMessages(const std::function<ShouldCheckInMsgsBeSentFunction> & verifier)
{
    VerifyOrReturn(SupportsFeature(Feature::kCheckInProtocolSupport));

    // Only trigger Check-In messages when we are in IdleMode.
    // If we are already in ActiveMode, Check-In messages have already been sent.
    VerifyOrReturn(mOperationalState == OperationalState::IdleMode);

    // If we don't have any Check-In messages to send, do nothing
    VerifyOrReturn(CheckInMessagesWouldBeSent(verifier));
    UpdateOperationState(OperationalState::ActiveMode);
}
#endif // CHIP_CONFIG_ENABLE_ICD_CIP

void ICDManager::UpdateICDMode()
{
    assertChipStackLockedByCurrentThread();

    ICDConfigurationData::ICDMode tempMode = ICDConfigurationData::ICDMode::SIT;

#if CHIP_CONFIG_ENABLE_ICD_LIT
    // Device can only switch to the LIT operating mode if LIT support is present
    if (SupportsFeature(Feature::kLongIdleTimeSupport))
    {
        VerifyOrDie(mStorage != nullptr);
        VerifyOrDie(mFabricTable != nullptr);
        // We can only get to LIT Mode, if at least one client is registered with the ICD device
        for (const auto & fabricInfo : *mFabricTable)
        {
            // We only need 1 valid entry to ensure LIT compliance
            ICDMonitoringTable table(*mStorage, fabricInfo.GetFabricIndex(), 1 /*Table entry limit*/, mSymmetricKeystore);
            if (!table.IsEmpty())
            {
                tempMode = ICDConfigurationData::ICDMode::LIT;
                break;
            }
        }
    }
#endif // CHIP_CONFIG_ENABLE_ICD_LIT

    if (ICDConfigurationData::GetInstance().GetICDMode() != tempMode)
    {
        ICDConfigurationData::GetInstance().SetICDMode(tempMode);

        // Can't use attribute accessors/Attributes::OperatingMode::Set in unit tests
#if !CONFIG_BUILD_FOR_HOST_UNIT_TEST
        Attributes::OperatingMode::Set(kRootEndpointId, static_cast<OperatingModeEnum>(tempMode));
#endif

        postObserverEvent(ObserverEventType::ICDModeChange);
    }

    // When in SIT mode, the slow poll interval SHOULDN'T be greater than the SIT mode polling threshold, per spec.
    if (ICDConfigurationData::GetInstance().GetICDMode() == ICDConfigurationData::ICDMode::SIT &&
        ICDConfigurationData::GetInstance().GetSlowPollingInterval() > ICDConfigurationData::GetInstance().GetSITPollingThreshold())
    {
        ChipLogDetail(AppServer, "The Slow Polling Interval of an ICD in SIT mode should be <= %" PRIu32 " seconds",
                      (ICDConfigurationData::GetInstance().GetSITPollingThreshold().count() / 1000));
    }
}

void ICDManager::UpdateOperationState(OperationalState state)
{
    assertChipStackLockedByCurrentThread();
    // Active mode can be re-triggered.
    VerifyOrReturn(mOperationalState != state || state == OperationalState::ActiveMode);

    if (state == OperationalState::IdleMode)
    {
        mOperationalState = OperationalState::IdleMode;

#if CHIP_CONFIG_ENABLE_ICD_CIP
        std::function<ShouldCheckInMsgsBeSentFunction> sendCheckInMessagesOnActiveMode =
            std::bind(&ICDManager::ShouldCheckInMsgsBeSentAtActiveModeFunction, this, std::placeholders::_1, std::placeholders::_2);
#endif // CHIP_CONFIG_ENABLE_ICD_CIP

        // When the active mode interval is 0, we stay in idleMode until a notification brings the icd into active mode
        // unless the device would need to send Check-In messages
        if (ICDConfigurationData::GetInstance().GetActiveModeDuration() > kZero
#if CHIP_CONFIG_ENABLE_ICD_CIP
            || CheckInMessagesWouldBeSent(sendCheckInMessagesOnActiveMode)
#endif // CHIP_CONFIG_ENABLE_ICD_CIP
        )
        {
            DeviceLayer::SystemLayer().StartTimer(ICDConfigurationData::GetInstance().GetIdleModeDuration(), OnIdleModeDone, this);
        }

        Milliseconds32 slowPollInterval = ICDConfigurationData::GetInstance().GetSlowPollingInterval();

#if CHIP_CONFIG_ENABLE_ICD_CIP
        // Going back to Idle, all Check-In messages are sent
        mICDSenderPool.ReleaseAll();
#endif // CHIP_CONFIG_ENABLE_ICD_CIP

        CHIP_ERROR err = DeviceLayer::ConnectivityMgr().SetPollingInterval(slowPollInterval);
        if (err != CHIP_NO_ERROR)
        {
            ChipLogError(AppServer, "Failed to set Slow Polling Interval: err %" CHIP_ERROR_FORMAT, err.Format());
        }

        postObserverEvent(ObserverEventType::EnterIdleMode);
    }
    else if (state == OperationalState::ActiveMode)
    {
        if (mOperationalState == OperationalState::IdleMode)
        {
            // An event could have brought us to the active mode.
            // Make sure the idle mode timer is stopped
            DeviceLayer::SystemLayer().CancelTimer(OnIdleModeDone, this);

            mOperationalState                 = OperationalState::ActiveMode;
            Milliseconds32 activeModeDuration = ICDConfigurationData::GetInstance().GetActiveModeDuration();

            if (activeModeDuration == kZero && !mKeepActiveFlags.HasAny())
            {
                // Network Activity triggered the active mode and activeModeDuration is 0.
                // Stay active for at least Active Mode Threshold.
                activeModeDuration = ICDConfigurationData::GetInstance().GetActiveModeThreshold();
            }

            DeviceLayer::SystemLayer().StartTimer(activeModeDuration, OnActiveModeDone, this);

            Milliseconds32 activeModeJitterInterval = Milliseconds32(ICD_ACTIVE_TIME_JITTER_MS);
            // TODO(#33074): Edge case when we transition to IdleMode with this condition being true
            // (activeModeDuration == kZero && !mKeepActiveFlags.HasAny())
            activeModeJitterInterval =
                (activeModeDuration >= activeModeJitterInterval) ? activeModeDuration - activeModeJitterInterval : kZero;

            // Reset this flag when we enter ActiveMode to avoid having a feedback loop that keeps us indefinitly in
            // ActiveMode.
            mTransitionToIdleCalled = false;
            DeviceLayer::SystemLayer().StartTimer(activeModeJitterInterval, OnTransitionToIdle, this);

            CHIP_ERROR err =
                DeviceLayer::ConnectivityMgr().SetPollingInterval(ICDConfigurationData::GetInstance().GetFastPollingInterval());
            if (err != CHIP_NO_ERROR)
            {
                ChipLogError(AppServer, "Failed to set Fast Polling Interval: err %" CHIP_ERROR_FORMAT, err.Format());
            }

#if CHIP_CONFIG_ENABLE_ICD_CIP
            if (SupportsFeature(Feature::kCheckInProtocolSupport))
            {
                SendCheckInMsgs();
            }
#endif // CHIP_CONFIG_ENABLE_ICD_CIP

            postObserverEvent(ObserverEventType::EnterActiveMode);
        }
        else
        {
            ExtendActiveMode(ICDConfigurationData::GetInstance().GetActiveModeThreshold());
        }
    }
}

void ICDManager::SetKeepActiveModeRequirements(KeepActiveFlags flag, bool state)
{
    assertChipStackLockedByCurrentThread();

    mKeepActiveFlags.Set(flag, state);
    if (mOperationalState == OperationalState::IdleMode && mKeepActiveFlags.HasAny())
    {
        UpdateOperationState(OperationalState::ActiveMode);
    }
    else if (mOperationalState == OperationalState::ActiveMode && !mKeepActiveFlags.HasAny() &&
             !DeviceLayer::SystemLayer().IsTimerActive(OnActiveModeDone, this))
    {
        // The normal active period had ended and nothing else requires the system to be active.
        UpdateOperationState(OperationalState::IdleMode);
    }
}

void ICDManager::OnIdleModeDone(System::Layer * aLayer, void * appState)
{
    ICDManager * pICDManager = reinterpret_cast<ICDManager *>(appState);
    pICDManager->UpdateOperationState(OperationalState::ActiveMode);
}

void ICDManager::OnActiveModeDone(System::Layer * aLayer, void * appState)
{
    ICDManager * pICDManager = reinterpret_cast<ICDManager *>(appState);

    // Don't go to idle mode when we have a keep active requirement
    if (!pICDManager->mKeepActiveFlags.HasAny())
    {
        pICDManager->UpdateOperationState(OperationalState::IdleMode);
    }
}

void ICDManager::OnTransitionToIdle(System::Layer * aLayer, void * appState)
{
    ICDManager * pICDManager = reinterpret_cast<ICDManager *>(appState);

    // OnTransitionToIdle will trigger a report message if reporting is needed, which should extend the active mode until the
    // ack for the report is received.
    pICDManager->mTransitionToIdleCalled = true;
    pICDManager->postObserverEvent(ObserverEventType::TransitionToIdle);
}

/* ICDListener functions. */

void ICDManager::OnKeepActiveRequest(KeepActiveFlags request)
{
    assertChipStackLockedByCurrentThread();
    VerifyOrReturn(request < KeepActiveFlagsValues::kInvalidFlag);

    if (request.Has(KeepActiveFlag::kExchangeContextOpen))
    {
        // There can be multiple open exchange contexts at the same time.
        // Keep track of the requests count.
        this->mOpenExchangeContextCount++;
    }

#if CHIP_CONFIG_ENABLE_ICD_CIP
    if (request.Has(KeepActiveFlag::kCheckInInProgress))
    {
        // There can be multiple check-in at the same time.
        // Keep track of the requests count.
        this->mCheckInRequestCount++;
    }
#endif // CHIP_CONFIG_ENABLE_ICD_CIP

    this->SetKeepActiveModeRequirements(request, true /* state */);
}

void ICDManager::OnActiveRequestWithdrawal(KeepActiveFlags request)
{
    assertChipStackLockedByCurrentThread();
    VerifyOrReturn(request < KeepActiveFlagsValues::kInvalidFlag);

    if (request.Has(KeepActiveFlag::kExchangeContextOpen))
    {
        // There can be multiple open exchange contexts at the same time.
        // Keep track of the requests count.
        if (this->mOpenExchangeContextCount > 0)
        {
            this->mOpenExchangeContextCount--;
        }
        else
        {
            ChipLogError(DeviceLayer, "The ICD Manager did not account for ExchangeContext closure");
        }

        if (this->mOpenExchangeContextCount == 0)
        {
            this->SetKeepActiveModeRequirements(KeepActiveFlag::kExchangeContextOpen, false /* state */);
        }
    }

#if CHIP_CONFIG_ENABLE_ICD_CIP
    if (request.Has(KeepActiveFlag::kCheckInInProgress))
    {
        // There can be multiple open exchange contexts at the same time.
        // Keep track of the requests count.
        if (this->mCheckInRequestCount > 0)
        {
            this->mCheckInRequestCount--;
        }
        else
        {
            ChipLogError(DeviceLayer, "The ICD Manager did not account for Check-In Sender start");
        }

        if (this->mCheckInRequestCount == 0)
        {
            this->SetKeepActiveModeRequirements(KeepActiveFlag::kCheckInInProgress, false /* state */);
        }
    }
#endif // CHIP_CONFIG_ENABLE_ICD_CIP

    if (request.Has(KeepActiveFlag::kCommissioningWindowOpen) || request.Has(KeepActiveFlag::kFailSafeArmed))
    {
        // Only 1 request per type (kCommissioningWindowOpen, kFailSafeArmed)
        // remove requirement directly
        this->SetKeepActiveModeRequirements(request, false /* state */);
    }
}

void ICDManager::OnNetworkActivity()
{
    this->UpdateOperationState(OperationalState::ActiveMode);
}

void ICDManager::OnICDManagementServerEvent(ICDManagementEvents event)
{
    switch (event)
    {
    case ICDManagementEvents::kTableUpdated:
        this->UpdateICDMode();
        break;
    default:
        break;
    }
}

void ICDManager::OnSubscriptionReport()
{
    // If the device is already in ActiveMode, that means that all active subscriptions have already been marked dirty.
    // Since we only mark them dirty when we enter ActiveMode, it is not necessary to update the operational state a second time.
    // Doing so will only add an ActiveModeThreshold to the active time which we don't want to do here.
    VerifyOrReturn(mOperationalState == OperationalState::IdleMode);
    this->UpdateOperationState(OperationalState::ActiveMode);
}

void ICDManager::ExtendActiveMode(Milliseconds16 extendDuration)
{
    DeviceLayer::SystemLayer().ExtendTimerTo(extendDuration, OnActiveModeDone, this);

    Milliseconds32 activeModeJitterThreshold = Milliseconds32(ICD_ACTIVE_TIME_JITTER_MS);
    activeModeJitterThreshold = (extendDuration >= activeModeJitterThreshold) ? extendDuration - activeModeJitterThreshold : kZero;

    if (!mTransitionToIdleCalled)
    {
        DeviceLayer::SystemLayer().ExtendTimerTo(activeModeJitterThreshold, OnTransitionToIdle, this);
    }
}

CHIP_ERROR ICDManager::HandleEventTrigger(uint64_t eventTrigger)
{
    ICDTestEventTriggerEvent trigger = static_cast<ICDTestEventTriggerEvent>(eventTrigger);
    CHIP_ERROR err                   = CHIP_NO_ERROR;

    switch (trigger)
    {
    case ICDTestEventTriggerEvent::kAddActiveModeReq:
        SetKeepActiveModeRequirements(KeepActiveFlag::kTestEventTriggerActiveMode, true);
        break;
    case ICDTestEventTriggerEvent::kRemoveActiveModeReq:
        SetKeepActiveModeRequirements(KeepActiveFlag::kTestEventTriggerActiveMode, false);
        break;
#if CHIP_CONFIG_ENABLE_ICD_CIP
    case ICDTestEventTriggerEvent::kInvalidateHalfCounterValues:
        err = ICDConfigurationData::GetInstance().GetICDCounter().InvalidateHalfCheckInCounterValues();
        break;
    case ICDTestEventTriggerEvent::kInvalidateAllCounterValues:
        err = ICDConfigurationData::GetInstance().GetICDCounter().InvalidateAllCheckInCounterValues();
        break;
#endif // CHIP_CONFIG_ENABLE_ICD_CIP
    default:
        err = CHIP_ERROR_INVALID_ARGUMENT;
        break;
    }

    return err;
}

ICDManager::ObserverPointer * ICDManager::RegisterObserver(ICDStateObserver * observer)
{
    return mStateObserverPool.CreateObject(observer);
}

void ICDManager::ReleaseObserver(ICDStateObserver * observer)
{
    mStateObserverPool.ForEachActiveObject([this, observer](ObserverPointer * obs) {
        if (obs->mObserver == observer)
        {
            mStateObserverPool.ReleaseObject(obs);
            return Loop::Break;
        }
        return Loop::Continue;
    });
}

void ICDManager::postObserverEvent(ObserverEventType event)
{
    mStateObserverPool.ForEachActiveObject([event](ObserverPointer * obs) {
        switch (event)
        {
        case ObserverEventType::EnterActiveMode: {
            obs->mObserver->OnEnterActiveMode();
            return Loop::Continue;
        }
        case ObserverEventType::EnterIdleMode: {
            obs->mObserver->OnEnterIdleMode();
            return Loop::Continue;
        }
        case ObserverEventType::TransitionToIdle: {
            obs->mObserver->OnTransitionToIdle();
            return Loop::Continue;
        }
        case ObserverEventType::ICDModeChange: {
            obs->mObserver->OnICDModeChange();
            return Loop::Continue;
        }
        default: {
            ChipLogError(DeviceLayer, "Invalid ICD Observer event type");
            return Loop::Break;
        }
        }
    });
}

} // namespace app
} // namespace chip
