/*
 *    Copyright (c) 2025 Project CHIP Authors
 *    All rights reserved.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */
#pragma once

#include <app/CommandHandlerInterface.h>
#include <app/ConcreteCommandPath.h>
#include <app/data-model-provider/ActionReturnStatus.h>
#include <app/data-model-provider/MetadataTypes.h>
#include <app/data-model-provider/Provider.h>
#include <app/persistence/AttributePersistenceProvider.h>
#include <app/server-cluster/ServerClusterInterface.h>
#include <app/server-cluster/ServerClusterInterfaceRegistry.h>
#include <data-model-providers/codedriven/endpoint/EndpointInterface.h>
#include <data-model-providers/codedriven/endpoint/EndpointInterfaceRegistry.h>
#include <lib/support/ReadOnlyBuffer.h>

namespace chip {
namespace app {
/**
 * @brief An implementation of DataModel::Provider that constructs the data model
 *        programmatically by aggregating EndpointInterface instances.
 *
 * This provider allows applications to define their Matter device data model (endpoints,
 * clusters, attributes, commands) dynamically at runtime. It manages a list of EndpointInterface
 * objects, each representing an endpoint on the device.
 *
 * The expected usage pattern by the application is as follows:
 * 1. Instantiate ServerClusterInterface(s) and ServerClusterRegistration(s).
 * 2. Instantiate EndpointInterface(s) and EndpointInterfaceRegistration(s).
 * 2. Instantiate the CodeDrivenDataModelProvider.
 * 3. Register ServerClusterInterfaceRegistration(s) to the CodeDrivenDataModelProvider using AddCluster().
 * 4. Register EndpointInterfaceRegistration(s) to the CodeDrivenDataModelProvider using AddEndpoint().
 *    Note: Step 4 MUST come after Step 3 (Endpoint needs to know about its clusters).
 * 5. Call Startup() on the CodeDrivenDataModelProvider.
 *
 * Note: if the CodeDrivenDataModelProvider has already been started (runtime change to add/remove Endpoints/Clusters),
 *       the Startup() method on each ServerClusterInterface will be called when the EndpointInterface is added (Step 4).
 *       If the provider hasn't been started, the Startup() method will be called when the provider is started (Step 5).
 *
 * TODO: Notify composition changes when the provider is started up and endpoints are added/removed at runtime.
 *       For now, applications are responsible for handling composition changes and calling markDirty() when needed.
 *
 * Lifecycle:
 * - The CodeDrivenDataModelProvider stores raw pointers to EndpointInterface and ServerClusterInterface.
 *   It does NOT take ownership. Callers must ensure these instances outlive the provider.
 */
class CodeDrivenDataModelProvider : public DataModel::Provider
{
public:
    CodeDrivenDataModelProvider(PersistentStorageDelegate & storage, AttributePersistenceProvider & attributeStorage) :
        mPersistentStorageDelegate(storage), mAttributePersistenceProvider(attributeStorage)
    {}

    /* DataModel::Provider implementation */
    CHIP_ERROR Startup(DataModel::InteractionModelContext context) override;
    CHIP_ERROR Shutdown() override;

    DataModel::ActionReturnStatus ReadAttribute(const DataModel::ReadAttributeRequest & request,
                                                AttributeValueEncoder & encoder) override;
    DataModel::ActionReturnStatus WriteAttribute(const DataModel::WriteAttributeRequest & request,
                                                 AttributeValueDecoder & decoder) override;

    void ListAttributeWriteNotification(const ConcreteAttributePath & path, DataModel::ListWriteOperation opType,
                                        FabricIndex accessingFabric) override;
    std::optional<DataModel::ActionReturnStatus> InvokeCommand(const DataModel::InvokeRequest & request,
                                                               TLV::TLVReader & input_arguments, CommandHandler * handler) override;

    /* ProviderMetadataTree implementation */
    CHIP_ERROR Endpoints(ReadOnlyBufferBuilder<DataModel::EndpointEntry> & out) override;
    CHIP_ERROR DeviceTypes(EndpointId endpointId, ReadOnlyBufferBuilder<DataModel::DeviceTypeEntry> & out) override;
    CHIP_ERROR ClientClusters(EndpointId endpointId, ReadOnlyBufferBuilder<ClusterId> & out) override;
    CHIP_ERROR ServerClusters(EndpointId endpointId, ReadOnlyBufferBuilder<DataModel::ServerClusterEntry> & out) override;
    CHIP_ERROR GeneratedCommands(const ConcreteClusterPath & path, ReadOnlyBufferBuilder<CommandId> & out) override;
    CHIP_ERROR AcceptedCommands(const ConcreteClusterPath & path,
                                ReadOnlyBufferBuilder<DataModel::AcceptedCommandEntry> & out) override;
    CHIP_ERROR Attributes(const ConcreteClusterPath & path, ReadOnlyBufferBuilder<DataModel::AttributeEntry> & builder) override;
    CHIP_ERROR EventInfo(const ConcreteEventPath & path, DataModel::EventEntry & eventInfo) override;
    void Temporary_ReportAttributeChanged(const AttributePathParams & path) override;

#if CHIP_CONFIG_USE_ENDPOINT_UNIQUE_ID
    CHIP_ERROR EndpointUniqueID(EndpointId endpointId, MutableCharSpan & EndpointUniqueId) override;
#endif

    /**
     * @brief Adds an endpoint to the data model provider.
     *
     * This method registers an endpoint, making it part of the device's data model.
     * If the provider has already been started, this may trigger a Startup() call on
     * each ServerClusterInterface associated with the endpoint.
     * The Startup() call on the associated clusters will ONLY happen if this is the first
     * endpoint associated with the cluster (i.e. ServerClusterInterface.GetPaths() returns
     * at least one path with endpoint ID == registration.endpointEntry.id, and none
     * of the other endpoints in GetPaths() are registered yet). This ensures
     * the cluster is only started once, even if it is associated with multiple endpoints.
     *
     * Prerequisites:
     *   - It MUST be called after all clusters for the endpoint have been registered with
     *     AddCluster().
     *   - The provided `registration` (EndpointInterfaceRegistration) must not already be
     *     part of another list (i.e., `registration.next` must be nullptr).
     *   - The EndpointInterface within the `registration` must be valid (i.e.,
     *     `registration.endpointInterface` must not be nullptr).
     *   - The `registration.endpointEntry.id` must be valid (not `kInvalidEndpointId` and
     *     not used by another endpoint).
     *   - The LIFETIME of `registration` must outlive the provider (or the registration must
     *     be removed using `RemoveEndpoint` before it goes away).
     *
     * @param registration The registration object for the endpoint, containing a valid
     *                     EndpointInterface and Endpoint ID.
     * @return CHIP_NO_ERROR on success.
     *         CHIP_ERROR_INVALID_ARGUMENT if `registration.next` is not nullptr or
     *                                     `registration.endpointInterface` is nullptr or
     *                                     `registration.endpointEntry.id` is kInvalidEndpointId.
     *         CHIP_ERROR_DUPLICATE_KEY_ID if `registration.endpointEntry.id` is already in use.
     */
    CHIP_ERROR AddEndpoint(EndpointInterfaceRegistration & registration);

    /**
     * @brief Removes an endpoint from the data model provider.
     *
     * This method unregisters an endpoint, removing it from the device's data model.
     * If the provider has already been started, this might trigger a Shutdown() call on
     * each ServerClusterInterface associated with the endpoint.
     * The Shutdown() call on the associated clusters will ONLY happen if this is the last
     * endpoint associated with the cluster (i.e. ServerClusterInterface.GetPaths() returns
     * no paths with valid Endpoint IDs).
     *
     * Note: Removing an Endpoint does not remove any clusters associated with the endpoint.
     *       Those can be removed using RemoveCluster() AFTER the endpoint has been removed.

     * Prerequisites:
     *   - It MUST be called BEFORE removing associted clusters with RemoveCluster() to guarantee
     *     the endpoint removal is atomic.
     *   - The endpoint ID must be valid.
     *
     * @param endpointId The ID of the endpoint to remove.
     * @return CHIP_NO_ERROR on success.
     *         CHIP_ERROR_NOT_FOUND if no endpoint with the given ID is registered.
     *         CHIP_ERROR_INVALID_ARGUMENT if endpointId is kInvalidEndpointId.
     */
    CHIP_ERROR RemoveEndpoint(EndpointId endpointId, ClusterShutdownType shutdownType = ClusterShutdownType::kClusterShutdown);

    /**
     * @brief Add a ServerClusterInterface to the Data Model Provider.
     *
     * Requirements:
     *   - entry MUST NOT be part of any other registration
     *   - paths MUST NOT be part of any other ServerClusterInterface (i.e. only a single
     *     registration for a given `endpointId/clusterId` path).
     *   - The LIFETIME of entry must outlive the provider (or the entry must be unregistered
     *     via RemoveCluster before it goes away).
     *   - If the provider has already been started, this method must be called prior to
     *     calling AddEndpoint() (i.e. the `endpointId` of all paths in `entry.GetPaths()`
     *     must NOT be registered in the provider yet), otherwise this would cause non-atomic
     *     changes to an endpoint, which is not allowed.
     *
     * @param entry The ServerClusterRegistration containing the cluster to register.
     * @return CHIP_NO_ERROR on success.
     *         CHIP_ERROR_INVALID_ARGUMENT if `entry.next` is not `nullptr` or
     *                                     `entry.serverClusterInterface` is `nullptr` or
     *                                     `entry.serverClusterInterface.GetPaths()` is empty/invalid.
     *         CHIP_ERROR_DUPLICATE_KEY_ID if the cluster is already registered.
     *         CHIP_ERROR_INCORRECT_STATE if the provider has been started and an endpoint for
     *                                    one of the cluster paths has already been registered.
     */
    CHIP_ERROR AddCluster(ServerClusterRegistration & entry);

    /**
     * @brief Remove a ServerClusterInterface from the Data Model Provider.
     *
     * To avoid violating the requirement of non-atomic changes to endpoints, this SHALL only be
     * called after all endpoints associated with the cluster have been removed using RemoveEndpoint().
     *
     * Requirements:
     *   - entry MUST be valid
     *   - The `endpointId` of all paths in `entry.GetPaths()` are no longer registered in the provider.
     *
     * @param entry The ServerClusterInterface to remove.
     * @return CHIP_NO_ERROR on success.
     *         CHIP_ERROR_INVALID_ARGUMENT if `entry` is nullptr.
     *         CHIP_ERROR_NOT_FOUND if the entry is not registered.
     *         CHIP_ERROR_INCORRECT_STATE if an endpoint for one of the cluster paths is still registered.
     */
    CHIP_ERROR RemoveCluster(ServerClusterInterface * entry,
                             ClusterShutdownType shutdownType = ClusterShutdownType::kClusterShutdown);

private:
    EndpointInterfaceRegistry mEndpointInterfaceRegistry;
    ServerClusterInterfaceRegistry mServerClusterRegistry;
    std::optional<ServerClusterContext> mServerClusterContext;
    std::optional<DataModel::InteractionModelContext> mInteractionModelContext;
    PersistentStorageDelegate & mPersistentStorageDelegate;
    AttributePersistenceProvider & mAttributePersistenceProvider;

    /// Return the interface registered for the given endpoint ID or nullptr if one does not exist
    EndpointInterface * GetEndpointInterface(EndpointId endpointId);

    /// Return the interface registered for the given cluster path or nullptr if one does not exist
    ServerClusterInterface * GetServerClusterInterface(const ConcreteClusterPath & path);
};

} // namespace app
} // namespace chip
