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

#pragma once

#include <app/AppConfig.h>
#include <app/icd/server/ICDServerConfig.h>

#include <access/AccessControl.h>
#include <access/GroupAuxiliaryAccessControlDelegate.h>
#include <access/examples/ExampleAccessControlDelegate.h>
#include <access/examples/GroupAuxiliaryAccessControlDelegateImpl.h>
#include <app/CASEClientPool.h>
#include <app/CASESessionManager.h>
#include <app/DefaultSafeAttributePersistenceProvider.h>
#include <app/FailSafeContext.h>
#include <app/OperationalSessionSetupPool.h>
#include <app/SimpleSubscriptionResumptionStorage.h>
#include <app/TestEventTriggerDelegate.h>
#include <app/server/AclStorage.h>
#include <app/server/AppDelegate.h>
#include <app/server/CommissioningWindowManager.h>
#include <app/server/DefaultAclStorage.h>
#include <credentials/CertificateValidityPolicy.h>
#include <credentials/FabricTable.h>
#include <credentials/GroupDataProvider.h>
#include <credentials/GroupDataProviderImpl.h>
#include <credentials/OperationalCertificateStore.h>
#include <credentials/PersistentStorageOpCertStore.h>
#include <crypto/DefaultSessionKeystore.h>
#include <crypto/OperationalKeystore.h>
#include <crypto/PersistentStorageOperationalKeystore.h>
#include <inet/InetConfig.h>
#include <lib/core/CHIPConfig.h>
#include <lib/support/AutoRelease.h>
#include <lib/support/SafeInt.h>
#include <messaging/ExchangeMgr.h>
#include <platform/DefaultTimerDelegate.h>
#include <platform/DeviceInstanceInfoProvider.h>
#include <platform/KeyValueStoreManager.h>
#include <platform/KvsPersistentStorageDelegate.h>
#include <protocols/secure_channel/CASEServer.h>
#include <protocols/secure_channel/MessageCounterManager.h>
#include <protocols/secure_channel/PASESession.h>
#include <protocols/secure_channel/RendezvousParameters.h>
#include <protocols/secure_channel/UnsolicitedStatusHandler.h>
#if CHIP_CONFIG_ENABLE_SESSION_RESUMPTION
#include <protocols/secure_channel/SimpleSessionResumptionStorage.h>
#endif
#include <protocols/user_directed_commissioning/UserDirectedCommissioning.h>
#include <system/SystemClock.h>
#include <transport/SessionManager.h>
#include <transport/TransportMgr.h>
#include <transport/TransportMgrBase.h>
#if CONFIG_NETWORK_LAYER_BLE
#include <transport/raw/BLE.h>
#endif
#if CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF
#include <transport/raw/WiFiPAF.h>
#endif
#include <app/reporting/ReportSchedulerImpl.h>
#include <transport/raw/UDP.h>
#if CHIP_DEVICE_CONFIG_ENABLE_NFC_BASED_COMMISSIONING
#include <transport/raw/NFC.h>
#endif

#if CHIP_CONFIG_ENABLE_ICD_SERVER
#include <app/icd/server/ICDManager.h> // nogncheck

#if CHIP_CONFIG_ENABLE_ICD_CIP
#include <app/icd/server/DefaultICDCheckInBackOffStrategy.h> // nogncheck
#include <app/icd/server/ICDCheckInBackOffStrategy.h>        // nogncheck
#endif                                                       // CHIP_CONFIG_ENABLE_ICD_CIP
#endif                                                       // CHIP_CONFIG_ENABLE_ICD_SERVER

#if CHIP_DEVICE_CONFIG_ENABLE_JOINT_FABRIC
#include <app/server/JointFabricAdministrator.h> //nogncheck
#include <app/server/JointFabricDatastore.h>     //nogncheck
#endif                                           // CHIP_DEVICE_CONFIG_ENABLE_JOINT_FABRIC

namespace chip {

inline constexpr size_t kMaxBlePendingPackets = 1;

#if INET_CONFIG_ENABLE_TCP_ENDPOINT
inline constexpr size_t kMaxTcpActiveConnectionCount = CHIP_CONFIG_MAX_ACTIVE_TCP_CONNECTIONS;

inline constexpr size_t kMaxTcpPendingPackets = CHIP_CONFIG_MAX_TCP_PENDING_PACKETS;
#endif // INET_CONFIG_ENABLE_TCP_ENDPOINT

//
// NOTE: Please do not alter the order of template specialization here as the logic
//       in the Server impl depends on this.
//
using ServerTransportMgr = chip::TransportMgr<chip::Transport::UDP
#if INET_CONFIG_ENABLE_IPV4
                                              ,
                                              chip::Transport::UDP
#endif
#if CONFIG_NETWORK_LAYER_BLE
                                              ,
                                              chip::Transport::BLE<kMaxBlePendingPackets>
#endif
#if INET_CONFIG_ENABLE_TCP_ENDPOINT
                                              ,
                                              chip::Transport::TCP<kMaxTcpActiveConnectionCount, kMaxTcpPendingPackets>
#if INET_CONFIG_ENABLE_IPV4
                                              ,
                                              chip::Transport::TCP<kMaxTcpActiveConnectionCount, kMaxTcpPendingPackets>
#endif
#endif
#if CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF
                                              ,
                                              chip::Transport::WiFiPAFBase
#endif
#if CHIP_DEVICE_CONFIG_ENABLE_NFC_BASED_COMMISSIONING
                                              ,
                                              chip::Transport::NFC
#endif
                                              >;

#if CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY_CLIENT
using UdcTransportMgr = TransportMgr<Transport::UDP /* IPv6 */
#if INET_CONFIG_ENABLE_IPV4
                                     ,
                                     Transport::UDP /* IPv4 */
#endif
                                     >;
#endif

struct ServerInitParams
{
    ServerInitParams() = default;

    // Not copyable
    ServerInitParams(const ServerInitParams &)             = delete;
    ServerInitParams & operator=(const ServerInitParams &) = delete;

    // Application delegate to handle some commissioning lifecycle events
    AppDelegate * appDelegate = nullptr;
    // device discovery timeout
    System::Clock::Seconds32 discoveryTimeout = System::Clock::Seconds32(CHIP_DEVICE_CONFIG_DISCOVERY_TIMEOUT_SECS);
    // Port to use for Matter commissioning/operational traffic
    uint16_t operationalServicePort = CHIP_PORT;
    // Port to use for UDC if supported
    uint16_t userDirectedCommissioningPort = CHIP_UDC_PORT;
    // Interface on which to run daemon
    Inet::InterfaceId interfaceId = Inet::InterfaceId::Null();

#if CHIP_DEVICE_CONFIG_ENABLE_PORT_RETRY
    // Number of sequential port retries if binding fails with "address in use"
    // When > 0, if binding to operationalServicePort (or userDirectedCommissioningPort) fails,
    // the system will automatically try portRetryCount additional sequential ports.
    // For example: if operationalServicePort=5540 and portRetryCount=10, it will try
    // ports 5540, 5541, 5542, ... up to 5550 until one succeeds.
    // When set to 0 (default), no retry is attempted - implements single port behavior.
    uint16_t portRetryCount = CHIP_DEVICE_CONFIG_PORT_RETRY_COUNT;
#endif // CHIP_DEVICE_CONFIG_ENABLE_PORT_RETRY

    // Persistent storage delegate: MUST be injected. Used to maintain storage by much common code.
    // Must be initialized before being provided.
    PersistentStorageDelegate * persistentStorageDelegate = nullptr;
    // Session resumption storage: Optional. Support session resumption when provided.
    // Must be initialized before being provided.
    SessionResumptionStorage * sessionResumptionStorage = nullptr;
    // Session resumption storage: Optional. Support session resumption when provided.
    // Must be initialized before being provided.
    app::SubscriptionResumptionStorage * subscriptionResumptionStorage = nullptr;
    // Certificate validity policy: Optional. If none is injected, CHIPCert
    // enforces a default policy.
    Credentials::CertificateValidityPolicy * certificateValidityPolicy = nullptr;
    // Group data provider: MUST be injected. Used to maintain critical keys such as the Identity
    // Protection Key (IPK) for CASE. Must be initialized before being provided.
    Credentials::GroupDataProvider * groupDataProvider = nullptr;
    // Session keystore: MUST be injected. Used to derive and manage lifecycle of symmetric keys.
    Crypto::SessionKeystore * sessionKeystore = nullptr;
    // Access control delegate: MUST be injected. Used to look up access control rules. Must be
    // initialized before being provided.
    Access::AccessControl::Delegate * accessDelegate = nullptr;
    // Access control auxiliary delegate: Optional. Used to look up auxiliary access control rules.
    // May be either pre-initialized (Initialize already called) or default-constructed:
    // Server::Init will call Initialize with its own FabricTable on a not-yet-initialized
    // delegate before registering it. Applications may substitute their own subclass of
    // Access::GroupAuxiliaryAccessControlDelegate rather than reusing the default Impl.
    Access::GroupAuxiliaryAccessControlDelegate * groupAuxiliaryAccessControlDelegate = nullptr;
    // ACL storage: MUST be injected. Used to store ACL entries in persistent storage. Must NOT
    // be initialized before being provided.
    app::AclStorage * aclStorage = nullptr;

#if CHIP_CONFIG_USE_ACCESS_RESTRICTIONS
    // Access Restriction implementation: MUST be injected if MNGD feature enabled. Used to enforce
    // access restrictions that are managed by the device.
    Access::AccessRestrictionProvider * accessRestrictionProvider = nullptr;
#endif

    // Network native params can be injected depending on the
    // selected Endpoint implementation
    void * endpointNativeParams = nullptr;
    // Optional. Support test event triggers when provided. Must be initialized before being
    // provided.
    TestEventTriggerDelegate * testEventTriggerDelegate = nullptr;
    // Operational keystore with access to the operational keys: MUST be injected.
    Crypto::OperationalKeystore * operationalKeystore = nullptr;
    // Operational certificate store with access to the operational certs in persisted storage:
    // must not be null at timne of Server::Init().
    Credentials::OperationalCertificateStore * opCertStore = nullptr;
    // Required, if not provided, the Server::Init() WILL fail.
    app::reporting::ReportScheduler * reportScheduler = nullptr;
#if CHIP_CONFIG_ENABLE_ICD_CIP
    // Optional. Support for the ICD Check-In BackOff strategy. Must be initialized before being provided.
    // If the ICD Check-In protocol use-case is supported and no strategy is provided, server will use the default strategy.
    app::ICDCheckInBackOffStrategy * icdCheckInBackOffStrategy = nullptr;
#endif // CHIP_CONFIG_ENABLE_ICD_CIP

    // MUST NOT be null during initialization: every application must define the
    // data model it wants to use. Backwards-compatibility can use `CodegenDataModelProviderInstance`
    // for ember/zap-generated models.
    chip::app::DataModel::Provider * dataModelProvider = nullptr;

    bool advertiseCommissionableIfNoFabrics = CHIP_DEVICE_CONFIG_ENABLE_PAIRING_AUTOSTART;
};

/**
 * Transitional version of ServerInitParams to assist SDK integrators in
 * transitioning to injecting product/platform-owned resources. This version
 * of `ServerInitParams` owns and initializes (via the `InitializeStaticResourcesBeforeServerInit()`
 * method) the persistent storage delegate, the group data provider, and the access control delegate.
 * This is to reduce the amount of copied boilerplate in all the example initializations
 * (e.g. AppTask.cpp, main.cpp).
 *
 * This version SHOULD BE USED ONLY FOR THE IN-TREE EXAMPLES.
 *
 * IMPORTANT: Instances of this class MUST outlive the Server because Server::Init()
 *            stores pointers to resources owned by this class.
 *
 * ACTION ITEMS FOR TRANSITION from a example in-tree to a product:
 *
 * While this could be used indefinitely, it does not exemplify orderly management of
 * application-injected resources. It is recommended for actual products to instead:
 *   - Use the basic ServerInitParams in the application
 *   - Have the application own an instance of the resources being injected in its own
 *     state (e.g. an implementation of PersistentStorageDelegate and GroupDataProvider
 *     interfaces).
 *   - Initialize the injected resources prior to calling Server::Init()
 *   - De-initialize the injected resources after calling Server::Shutdown()
 *
 * WARNING: DO NOT replicate the pattern shown here of having a subclass of ServerInitParams
 *          own the resources outside of examples. This was done to reduce the amount of change
 *          to existing examples while still supporting non-example versions of the
 *          resources to be injected.
 */
struct CommonCaseDeviceServerInitParams : public ServerInitParams
{
    CommonCaseDeviceServerInitParams() = default;

    // Not copyable
    CommonCaseDeviceServerInitParams(const CommonCaseDeviceServerInitParams &)             = delete;
    CommonCaseDeviceServerInitParams & operator=(const CommonCaseDeviceServerInitParams &) = delete;

    /**
     * Call this before Server::Init() to initialize the internally-owned resources.
     * Server::Init() will fail if this is not done, since several params required to
     * be non-null will be null without calling this method. ** See the transition method
     * in the outer comment of this class **.
     *
     * @return CHIP_NO_ERROR on success or a CHIP_ERROR value from APIs called to initialize
     *         resources on failure.
     */
    CHIP_ERROR InitializeStaticResourcesBeforeServerInit()
    {
        // KVS-based persistent storage delegate injection
        if (persistentStorageDelegate == nullptr)
        {
            chip::DeviceLayer::PersistedStorage::KeyValueStoreManager & kvsManager =
                DeviceLayer::PersistedStorage::KeyValueStoreMgr();
            ReturnErrorOnFailure(mKvsPersistentStorageDelegate.Init(&kvsManager));
            this->persistentStorageDelegate = &mKvsPersistentStorageDelegate;
        }

        // PersistentStorageDelegate "software-based" operational key access injection
        if (this->operationalKeystore == nullptr)
        {
            // WARNING: PersistentStorageOperationalKeystore::Finish() is never called. It's fine for
            //          for examples and for now.
            ReturnErrorOnFailure(mPersistentStorageOperationalKeystore.Init(this->persistentStorageDelegate));
            this->operationalKeystore = &mPersistentStorageOperationalKeystore;
        }

        // OpCertStore can be injected but default to persistent storage default
        // for simplicity of the examples.
        if (this->opCertStore == nullptr)
        {
            // WARNING: PersistentStorageOpCertStore::Finish() is never called. It's fine for
            //          for examples and for now, since all storage is immediate for that impl.
            ReturnErrorOnFailure(mPersistentStorageOpCertStore.Init(this->persistentStorageDelegate));
            this->opCertStore = &mPersistentStorageOpCertStore;
        }

        // Injection of report scheduler WILL lead to two schedulers being allocated. As recommended above, this should only be used
        // for IN-TREE examples. If a default scheduler is desired, the basic ServerInitParams should be used by the application and
        // CommonCaseDeviceServerInitParams should not be allocated.
        if (this->reportScheduler == nullptr)
        {
            this->reportScheduler = &mReportScheduler;
        }

        // Session Keystore injection
        if (this->sessionKeystore == nullptr)
        {
            this->sessionKeystore = &mSessionKeystore;
        }

        // Group Data provider injection
        if (this->groupDataProvider == nullptr)
        {
            mGroupDataProvider.SetStorageDelegate(this->persistentStorageDelegate);
            mGroupDataProvider.SetSessionKeystore(this->sessionKeystore);
            ReturnErrorOnFailure(mGroupDataProvider.Init());
            this->groupDataProvider = &mGroupDataProvider;
        }

#if CHIP_CONFIG_ENABLE_SESSION_RESUMPTION
        if (this->sessionResumptionStorage == nullptr)
        {
            ChipLogProgress(AppServer, "Initializing session resumption storage...");
            ReturnErrorOnFailure(mSessionResumptionStorage.Init(this->persistentStorageDelegate));
            this->sessionResumptionStorage = &mSessionResumptionStorage;
        }
#endif

        // Inject access control delegate
        if (this->accessDelegate == nullptr)
        {
            this->accessDelegate = Access::Examples::GetAccessControlDelegate();
        }

        if (this->aclStorage == nullptr)
        {
            // Inject ACL storage. (Don't initialize it.)
            this->aclStorage = &mAclStorage;
        }

#if CHIP_CONFIG_PERSIST_SUBSCRIPTIONS
        if (this->subscriptionResumptionStorage == nullptr)
        {
            ChipLogProgress(AppServer, "Initializing subscription resumption storage...");
            ReturnErrorOnFailure(mSubscriptionResumptionStorage.Init(this->persistentStorageDelegate));
            this->subscriptionResumptionStorage = &mSubscriptionResumptionStorage;
        }
#endif

#if CHIP_CONFIG_ENABLE_ICD_CIP
        if (this->icdCheckInBackOffStrategy == nullptr)
        {
            this->icdCheckInBackOffStrategy = &mICDCheckInBackOffStrategy;
        }
#endif

#if CHIP_CONFIG_ENABLE_GROUPCAST
        if (this->groupAuxiliaryAccessControlDelegate == nullptr)
        {
            // The delegate is left uninitialized here on purpose: Server::Init will call
            // Initialize on it with the Server-owned FabricTable, which is not reachable
            // from this scope.
            this->groupAuxiliaryAccessControlDelegate = &mGroupAuxiliaryAccessControlDelegate;
        }
#endif // CHIP_CONFIG_ENABLE_GROUPCAST

        return CHIP_NO_ERROR;
    }

private:
    // Owned resources - these are instance members (not static) so each
    // CommonCaseDeviceServerInitParams instance owns its own copy.
    // They must outlive Server::Init() because that method stores pointers to them.
    KvsPersistentStorageDelegate mKvsPersistentStorageDelegate;
    PersistentStorageOperationalKeystore mPersistentStorageOperationalKeystore;
    Credentials::PersistentStorageOpCertStore mPersistentStorageOpCertStore;
    Credentials::GroupDataProviderImpl mGroupDataProvider;
    app::DefaultTimerDelegate mTimerDelegate;
    app::reporting::ReportSchedulerImpl mReportScheduler{ &mTimerDelegate };

#if CHIP_CONFIG_ENABLE_SESSION_RESUMPTION
    SimpleSessionResumptionStorage mSessionResumptionStorage;
#endif

#if CHIP_CONFIG_PERSIST_SUBSCRIPTIONS
    app::SimpleSubscriptionResumptionStorage mSubscriptionResumptionStorage;
#endif

    app::DefaultAclStorage mAclStorage;
    Crypto::DefaultSessionKeystore mSessionKeystore;

#if CHIP_CONFIG_ENABLE_ICD_CIP
    app::DefaultICDCheckInBackOffStrategy mICDCheckInBackOffStrategy;
#endif

#if CHIP_CONFIG_ENABLE_GROUPCAST
    // Default delegate used when the application does not provide its own. Concrete Impl,
    // exposed through the abstract base via groupAuxiliaryAccessControlDelegate above.
    Access::Examples::GroupAuxiliaryAccessControlDelegateImpl mGroupAuxiliaryAccessControlDelegate;
#endif
};

/**
 * The `Server` singleton class is an aggregate for all the resources needed to run a
 * Node that is both Commissionable and mainly used as an end-node with server clusters.
 * In other words, it aggregates the state needed for the type of Node used for most
 * products that are not mainly controller/administrator role.
 *
 * This sington class expects `ServerInitParams` initialization parameters but does not
 * own the resources injected from `ServerInitParams`. Any object pointers/references
 * passed in ServerInitParams must be pre-initialized externally, and shutdown/finalized
 * after `Server::Shutdown()` is called.
 *
 * TODO: Separate lifecycle ownership for some more capabilities that should not belong to
 *       common logic, such as `GenerateShutDownEvent`.
 *
 * TODO: Replace all uses of GetInstance() to "reach in" to this state from all cluster
 *       server common logic that deal with global node state with either a common NodeState
 *       compatible with OperationalDeviceProxy/DeviceProxy, or with injection at common
 *       SDK logic init.
 */
class Server
{
public:
    CHIP_ERROR Init(const ServerInitParams & initParams);

#if CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY_CLIENT
    CHIP_ERROR
    SendUserDirectedCommissioningRequest(chip::Transport::PeerAddress commissioner,
                                         Protocols::UserDirectedCommissioning::IdentificationDeclaration & id);

    Protocols::UserDirectedCommissioning::UserDirectedCommissioningClient * GetUserDirectedCommissioningClient()
    {
        return gUDCClient;
    }
#endif // CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY_CLIENT

    /**
     * @brief Call this function to rejoin existing groups found in the GroupDataProvider
     */
    void RejoinExistingMulticastGroups();

    FabricTable & GetFabricTable() { return mFabrics; }

    Access::AccessControl & GetAccessControl() { return mAccessControl; }

    CASESessionManager * GetCASESessionManager() { return &mCASESessionManager; }

    Messaging::ExchangeManager & GetExchangeManager() { return mExchangeMgr; }

    SessionManager & GetSecureSessionManager() { return mSessions; }

    SessionResumptionStorage * GetSessionResumptionStorage() { return mSessionResumptionStorage; }

    app::SubscriptionResumptionStorage * GetSubscriptionResumptionStorage() { return mSubscriptionResumptionStorage; }

    TransportMgrBase & GetTransportManager() { return mTransports; }

    Credentials::GroupDataProvider * GetGroupDataProvider() { return mGroupsProvider; }

    Crypto::SessionKeystore * GetSessionKeystore() const { return mSessionKeystore; }

#if CONFIG_NETWORK_LAYER_BLE
    Ble::BleLayer * GetBleLayerObject() { return mBleLayer; }
#endif

    CommissioningWindowManager & GetCommissioningWindowManager() { return mCommissioningWindowManager; }

    PersistentStorageDelegate & GetPersistentStorage() { return *mDeviceStorage; }

    app::FailSafeContext & GetFailSafeContext() { return mFailSafeContext; }

    TestEventTriggerDelegate * GetTestEventTriggerDelegate() { return mTestEventTriggerDelegate; }

    Crypto::OperationalKeystore * GetOperationalKeystore() { return mOperationalKeystore; }

    Credentials::OperationalCertificateStore * GetOpCertStore() { return mOpCertStore; }

    app::DefaultSafeAttributePersistenceProvider & GetDefaultAttributePersister() { return mAttributePersister; }

    app::reporting::ReportScheduler * GetReportScheduler() { return mReportScheduler; }

#if CHIP_DEVICE_CONFIG_ENABLE_JOINT_FABRIC
    app::JointFabricDatastore & GetJointFabricDatastore() { return mJointFabricDatastore; }
    app::JointFabricAdministrator & GetJointFabricAdministrator() { return mJointFabricAdministrator; }
#endif // CHIP_DEVICE_CONFIG_ENABLE_JOINT_FABRIC

#if CHIP_CONFIG_ENABLE_ICD_SERVER
    app::ICDManager & GetICDManager() { return mICDManager; }

#if CHIP_CONFIG_ENABLE_ICD_CIP
    /**
     * @brief Function to determine if a Check-In message would be sent at Boot up
     *
     * @param aFabricIndex client fabric index
     * @param subjectID client subject ID
     * @return true Check-In message would be sent on boot up.
     * @return false Device has a persisted subscription with the client. See CHIP_CONFIG_PERSIST_SUBSCRIPTIONS.
     */
    bool ShouldCheckInMsgsBeSentAtBootFunction(FabricIndex aFabricIndex, NodeId subjectID);
#endif // CHIP_CONFIG_ENABLE_ICD_CIP
#endif // CHIP_CONFIG_ENABLE_ICD_SERVER

    /**
     * This function causes the ShutDown event to be generated async on the
     * Matter event loop.  Should be called before stopping the event loop.
     */
    void GenerateShutDownEvent();

    void Shutdown();

    void ScheduleFactoryReset();

    System::Clock::Microseconds64 TimeSinceInit() const
    {
        return System::SystemClock().GetMonotonicMicroseconds64() - mInitTimestamp;
    }

    static Server & GetInstance() { return sServer; }

private:
    Server() {}

    static Server sServer;

    void InitFailSafe();
    void OnPlatformEvent(const DeviceLayer::ChipDeviceEvent & event);
    void CheckServerReadyEvent();

    void PostFactoryResetEvent();

    static void OnPlatformEventWrapper(const DeviceLayer::ChipDeviceEvent * event, intptr_t);

#if CHIP_CONFIG_PERSIST_SUBSCRIPTIONS
    /**
     * @brief Called at Server::Init time to resume persisted subscriptions if the feature flag is enabled
     */
    void ResumeSubscriptions();
#endif

    class GroupDataProviderListener final : public Credentials::GroupDataProvider::GroupListener
    {
    public:
        GroupDataProviderListener() {}

        CHIP_ERROR Init(Server * server)
        {
            VerifyOrReturnError(server != nullptr, CHIP_ERROR_INVALID_ARGUMENT);

            mServer = server;
            return CHIP_NO_ERROR;
        };

        void OnGroupAdded(chip::FabricIndex fabric_index, const Credentials::GroupDataProvider::GroupInfo & new_group) override
        {
            const FabricInfo * fabric = mServer->GetFabricTable().FindFabricWithIndex(fabric_index);
            if (fabric == nullptr)
            {
                ChipLogError(AppServer, "Group added to nonexistent fabric?");
                return;
            }

            const Transport::PeerAddress & address = new_group.UsePerGroupAddress()
                ? Transport::PeerAddress::BuildMatterPerGroupMulticastAddress(fabric->GetFabricId(), new_group.group_id)
                : Transport::PeerAddress::BuildMatterIanaMulticastAddress();

            if (CHIP_NO_ERROR != mServer->GetTransportManager().MulticastGroupJoinLeave(address, true))
            {
                ChipLogError(AppServer, "Unable to listen to group");
            }
        };

        void OnGroupRemoved(chip::FabricIndex fabric_index, const Credentials::GroupDataProvider::GroupInfo & old_group) override
        {
            if (old_group.UsePerGroupAddress())
            {
                // Per group address no longer in use, unsubscribe
                const FabricInfo * fabric = mServer->GetFabricTable().FindFabricWithIndex(fabric_index);
                if (fabric == nullptr)
                {
                    ChipLogError(AppServer, "Group removed from nonexistent fabric?");
                    return;
                }
                const Transport::PeerAddress & address =
                    Transport::PeerAddress::BuildMatterPerGroupMulticastAddress(fabric->GetFabricId(), old_group.group_id);
                VerifyOrReturn(CHIP_NO_ERROR == mServer->GetTransportManager().MulticastGroupJoinLeave(address, false));
            }
            else
            {
                // Check if the address is still in use
                Credentials::GroupDataProvider * provider = mServer->GetGroupDataProvider();
                bool in_use                               = false;
                if (nullptr != provider)
                {
                    // Check all groups from all fabrics
                    Credentials::GroupDataProvider::GroupInfo group;
                    for (const FabricInfo & fabric : mServer->GetFabricTable())
                    {
                        chip::AutoRelease iter(provider->IterateGroupInfo(fabric.GetFabricIndex()));
                        while (!iter.IsNull() && iter->Next(group) && !in_use)
                        {
                            in_use = !group.UsePerGroupAddress();
                        }
                        if (in_use)
                            break;
                    }
                }
                if (!in_use)
                {
                    // Groupcast address no longer in use, unsubscribe
                    const Transport::PeerAddress & address = Transport::PeerAddress::BuildMatterIanaMulticastAddress();
                    VerifyOrReturn(CHIP_NO_ERROR == mServer->GetTransportManager().MulticastGroupJoinLeave(address, false));
                }
            }
        };

    private:
        Server * mServer;
    };

    class ServerFabricDelegate final : public chip::FabricTable::Delegate
    {
    public:
        ServerFabricDelegate() {}

        CHIP_ERROR Init(Server * server)
        {
            VerifyOrReturnError(server != nullptr, CHIP_ERROR_INVALID_ARGUMENT);

            mServer = server;
            return CHIP_NO_ERROR;
        }

        void OnFabricRemoved(const FabricTable & fabricTable, FabricIndex fabricIndex) override
        {
            (void) fabricTable;
            ClearCASEResumptionStateOnFabricChange(fabricIndex);
            ClearSubscriptionResumptionStateOnFabricChange(fabricIndex);

            Credentials::GroupDataProvider * groupDataProvider = mServer->GetGroupDataProvider();
            if (groupDataProvider != nullptr)
            {
                CHIP_ERROR err = groupDataProvider->RemoveFabric(fabricIndex);
                if (err != CHIP_NO_ERROR)
                {
                    ChipLogError(AppServer,
                                 "Warning, failed to delete GroupDataProvider state for fabric index 0x%x: %" CHIP_ERROR_FORMAT,
                                 static_cast<unsigned>(fabricIndex), err.Format());
                }
            }

            // Remove access control entries in reverse order (it could be any order, but reverse order
            // will cause less churn in persistent storage).
            CHIP_ERROR aclErr = Access::GetAccessControl().DeleteAllEntriesForFabric(fabricIndex);
            if (aclErr != CHIP_NO_ERROR)
            {
                ChipLogError(AppServer, "Warning, failed to delete access control state for fabric index 0x%x: %" CHIP_ERROR_FORMAT,
                             static_cast<unsigned>(fabricIndex), aclErr.Format());
            }

            //  Remove ACL extension entry for the given fabricIndex.
            auto & storage = mServer->GetPersistentStorage();
            aclErr = storage.SyncDeleteKeyValue(DefaultStorageKeyAllocator::AccessControlExtensionEntry(fabricIndex).KeyName());

            if (aclErr != CHIP_NO_ERROR && aclErr != CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND)
            {
                ChipLogError(AppServer, "Warning, failed to delete ACL extension entry for fabric index 0x%x: %" CHIP_ERROR_FORMAT,
                             static_cast<unsigned>(fabricIndex), aclErr.Format());
            }

            mServer->GetCommissioningWindowManager().OnFabricRemoved(fabricIndex);

#if CHIP_DEVICE_CONFIG_ENABLE_JOINT_FABRIC
            // Clear any cached Joint Fabric VID-verification state tied to the removed fabric so it
            // cannot be honored for a different fabric that later reuses this FabricIndex.
            mServer->GetJointFabricAdministrator().OnFabricRemoved(fabricIndex);

            // If the removed fabric is the joint (anchor) fabric, purge the Joint Fabric Datastore:
            // all of its records belong to that fabric, and its anchor identity is no longer valid.
            mServer->GetJointFabricDatastore().OnFabricRemoved(fabricIndex);
#endif // CHIP_DEVICE_CONFIG_ENABLE_JOINT_FABRIC
        }

        void OnFabricUpdated(const FabricTable & fabricTable, chip::FabricIndex fabricIndex) override
        {
            (void) fabricTable;
            ClearCASEResumptionStateOnFabricChange(fabricIndex);
        }

    private:
        void ClearCASEResumptionStateOnFabricChange(chip::FabricIndex fabricIndex)
        {
            auto * sessionResumptionStorage = mServer->GetSessionResumptionStorage();
            VerifyOrReturn(sessionResumptionStorage != nullptr);
            CHIP_ERROR err = sessionResumptionStorage->DeleteAll(fabricIndex);
            if (err != CHIP_NO_ERROR)
            {
                ChipLogError(AppServer,
                             "Warning, failed to delete session resumption state for fabric index 0x%x: %" CHIP_ERROR_FORMAT,
                             static_cast<unsigned>(fabricIndex), err.Format());
            }
        }

        void ClearSubscriptionResumptionStateOnFabricChange(chip::FabricIndex fabricIndex)
        {
            auto * subscriptionResumptionStorage = mServer->GetSubscriptionResumptionStorage();
            VerifyOrReturn(subscriptionResumptionStorage != nullptr);
            CHIP_ERROR err = subscriptionResumptionStorage->DeleteAll(fabricIndex);
            if (err != CHIP_NO_ERROR)
            {
                ChipLogError(AppServer,
                             "Warning, failed to delete subscription resumption state for fabric index 0x%x: %" CHIP_ERROR_FORMAT,
                             static_cast<unsigned>(fabricIndex), err.Format());
            }
        }

        Server * mServer = nullptr;
    };

    /**
     * Since root certificates for Matter nodes cannot be updated in a reasonable
     * way, it doesn't make sense to enforce expiration time on root certificates.
     * This policy allows through root certificates, even if they're expired, and
     * otherwise delegates to the provided policy, or to the default policy if no
     * policy is provided.
     */
    class IgnoreRootExpirationValidityPolicy : public Credentials::CertificateValidityPolicy
    {
    public:
        IgnoreRootExpirationValidityPolicy() {}

        void Init(Credentials::CertificateValidityPolicy * providedPolicy) { mProvidedPolicy = providedPolicy; }

        CHIP_ERROR ApplyCertificateValidityPolicy(const Credentials::ChipCertificateData * cert, uint8_t depth,
                                                  Credentials::CertificateValidityResult result) override
        {
            switch (result)
            {
            case Credentials::CertificateValidityResult::kExpired:
            case Credentials::CertificateValidityResult::kExpiredAtLastKnownGoodTime:
            case Credentials::CertificateValidityResult::kTimeUnknown: {
                Credentials::CertType certType;
                ReturnErrorOnFailure(cert->mSubjectDN.GetCertType(certType));
                if (certType == Credentials::CertType::kRoot)
                {
                    return CHIP_NO_ERROR;
                }

                break;
            }
            default:
                break;
            }

            if (mProvidedPolicy)
            {
                return mProvidedPolicy->ApplyCertificateValidityPolicy(cert, depth, result);
            }

            return Credentials::CertificateValidityPolicy::ApplyDefaultPolicy(cert, depth, result);
        }

    private:
        Credentials::CertificateValidityPolicy * mProvidedPolicy = nullptr;
    };

#if CONFIG_NETWORK_LAYER_BLE
    Ble::BleLayer * mBleLayer = nullptr;
#endif

    // By default, use a certificate validation policy compatible with non-wall-clock-time-synced
    // embedded systems.
    static Credentials::IgnoreCertificateValidityPeriodPolicy sDefaultCertValidityPolicy;

    ServerTransportMgr mTransports;
    SessionManager mSessions;
    CASEServer mCASEServer;

    CASESessionManager mCASESessionManager;
    CASEClientPool<CHIP_CONFIG_DEVICE_MAX_ACTIVE_CASE_CLIENTS> mCASEClientPool;
    OperationalSessionSetupPool<CHIP_CONFIG_DEVICE_MAX_ACTIVE_DEVICES> mSessionSetupPool;

    Protocols::SecureChannel::UnsolicitedStatusHandler mUnsolicitedStatusHandler;
    Messaging::ExchangeManager mExchangeMgr;
    FabricTable mFabrics;
    secure_channel::MessageCounterManager mMessageCounterManager;
#if CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY_CLIENT
    Protocols::UserDirectedCommissioning::UserDirectedCommissioningClient * gUDCClient = nullptr;
    // mUdcTransportMgr is for insecure communication (ex. user directed commissioning)
    // specifically, the commissioner declaration message (sent by commissioner to commissionee)
    UdcTransportMgr * mUdcTransportMgr = nullptr;
    uint16_t mCdcListenPort            = CHIP_UDC_COMMISSIONEE_PORT;
#endif // CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY_CLIENT
    CommissioningWindowManager mCommissioningWindowManager;

    IgnoreRootExpirationValidityPolicy mCertificateValidityPolicy;

    PersistentStorageDelegate * mDeviceStorage;
    SessionResumptionStorage * mSessionResumptionStorage;
    app::SubscriptionResumptionStorage * mSubscriptionResumptionStorage;
    Credentials::GroupDataProvider * mGroupsProvider;
    Crypto::SessionKeystore * mSessionKeystore;
    app::DefaultSafeAttributePersistenceProvider mAttributePersister;
    GroupDataProviderListener mListener;
    ServerFabricDelegate mFabricDelegate;
    app::reporting::ReportScheduler * mReportScheduler;

    Access::AccessControl mAccessControl;
    app::AclStorage * mAclStorage;

#if CHIP_DEVICE_CONFIG_ENABLE_JOINT_FABRIC
    app::JointFabricDatastore mJointFabricDatastore;
    app::JointFabricAdministrator mJointFabricAdministrator;
#endif // CHIP_DEVICE_CONFIG_ENABLE_JOINT_FABRIC

    TestEventTriggerDelegate * mTestEventTriggerDelegate;
    Crypto::OperationalKeystore * mOperationalKeystore;
    Credentials::OperationalCertificateStore * mOpCertStore;
    app::FailSafeContext mFailSafeContext;

    bool mIsDnssdReady = false;
    uint16_t mOperationalServicePort;
    uint16_t mUserDirectedCommissioningPort;
    Inet::InterfaceId mInterfaceId;

    System::Clock::Microseconds64 mInitTimestamp;
#if CHIP_CONFIG_ENABLE_ICD_SERVER
    app::ICDManager mICDManager;
#endif // CHIP_CONFIG_ENABLE_ICD_SERVER
};

} // namespace chip
