/*
 *
 *    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/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 (!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;
            }

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