/*
 *    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, DataModel::AttributeChangeType type)
{
    IncreaseDataVersion();

    VerifyOrReturn(mContext != nullptr);
    mContext->provider.NotifyAttributeChanged({ mPath.mEndpointId, mPath.mClusterId, attributeId }, type);
}

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,
                                                                                    DataModel::AttributeChangeType type)
{
    if (status.IsSuccess() && !status.IsNoOpSuccess())
    {
        NotifyAttributeChanged(attributeId, type);
    }
    return status;
}

} // namespace app
} // namespace chip
