/*
 *    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.
 */
#include "ServerClusterInterface.h"
#include <app/server-cluster/DefaultServerCluster.h>

#include <access/Privilege.h>
#include <app-common/zap-generated/ids/Attributes.h>
#include <app/ConcreteClusterPath.h>
#include <app/data-model-provider/MetadataTypes.h>
#include <crypto/RandUtils.h>
#include <lib/support/BitFlags.h>
#include <optional>
#include <protocols/interaction_model/StatusCode.h>

namespace chip {
namespace app {
namespace {

using namespace chip::app::Clusters;
using namespace chip::app::DataModel;

constexpr std::array<AttributeEntry, 5> kGlobalAttributeEntries{ {
    {
        Globals::Attributes::FeatureMap::Id,
        BitFlags<AttributeQualityFlags>(),
        Access::Privilege::kView,
        std::nullopt,
    },
    {
        Globals::Attributes::ClusterRevision::Id,
        BitFlags<AttributeQualityFlags>(),
        Access::Privilege::kView,
        std::nullopt,
    },
    {
        Globals::Attributes::GeneratedCommandList::Id,
        BitFlags<AttributeQualityFlags>(AttributeQualityFlags::kListAttribute),
        Access::Privilege::kView,
        std::nullopt,
    },
    {
        Globals::Attributes::AcceptedCommandList::Id,
        BitFlags<AttributeQualityFlags>(AttributeQualityFlags::kListAttribute),
        Access::Privilege::kView,
        std::nullopt,
    },
    {
        Globals::Attributes::AttributeList::Id,
        BitFlags<AttributeQualityFlags>(AttributeQualityFlags::kListAttribute),
        Access::Privilege::kView,
        std::nullopt,
    },
} };

} // namespace

Span<const DataModel::AttributeEntry> DefaultServerCluster::GlobalAttributes()
{
    return { kGlobalAttributeEntries.data(), kGlobalAttributeEntries.size() };
}

CHIP_ERROR DefaultServerCluster::Attributes(const ConcreteClusterPath & path, ReadOnlyBufferBuilder<AttributeEntry> & builder)
{

    return builder.ReferenceExisting(GlobalAttributes());
}

CHIP_ERROR DefaultServerCluster::Startup(ServerClusterContext & context)
{
    VerifyOrReturnError(mContext == nullptr, CHIP_ERROR_ALREADY_INITIALIZED);

    mContext = &context;

    // SPEC - 7.10.3. Cluster Data Version
    //   A cluster data version SHALL be initialized randomly when it is first published.
    mDataVersion = Crypto::GetRandU32();

    return CHIP_NO_ERROR;
}

void DefaultServerCluster::Shutdown(ClusterShutdownType)
{
    mContext = nullptr;
}

void DefaultServerCluster::NotifyAttributeChanged(AttributeId attributeId)
{
    IncreaseDataVersion();

    VerifyOrReturn(mContext != nullptr);
    mContext->interactionContext.dataModelChangeListener.MarkDirty({ mPath.mEndpointId, mPath.mClusterId, attributeId });
}

BitFlags<ClusterQualityFlags> DefaultServerCluster::GetClusterFlags(const ConcreteClusterPath &) const
{
    return {};
}

ActionReturnStatus DefaultServerCluster::WriteAttribute(const WriteAttributeRequest & request, AttributeValueDecoder & decoder)
{
    return Protocols::InteractionModel::Status::UnsupportedWrite;
}

std::optional<ActionReturnStatus>
DefaultServerCluster::InvokeCommand(const InvokeRequest & request, chip::TLV::TLVReader & input_arguments, CommandHandler * handler)
{
    return Protocols::InteractionModel::Status::UnsupportedCommand;
}

CHIP_ERROR DefaultServerCluster::AcceptedCommands(const ConcreteClusterPath & path,
                                                  ReadOnlyBufferBuilder<AcceptedCommandEntry> & builder)
{
    return CHIP_NO_ERROR;
}

CHIP_ERROR DefaultServerCluster::GeneratedCommands(const ConcreteClusterPath & path, ReadOnlyBufferBuilder<CommandId> & builder)
{
    return CHIP_NO_ERROR;
}

DataModel::ActionReturnStatus DefaultServerCluster::NotifyAttributeChangedIfSuccess(AttributeId attributeId,
                                                                                    DataModel::ActionReturnStatus status)
{
    if (status.IsSuccess() && !status.IsNoOpSuccess())
    {
        NotifyAttributeChanged(attributeId);
    }
    return status;
}

} // namespace app
} // namespace chip
