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

#include "app/util/common.h"
#include <app/AttributePersistenceProvider.h>
#include <app/InteractionModelEngine.h>
#include <app/reporting/reporting.h>
#include <app/util/af.h>
#include <app/util/attribute-storage.h>
#include <app/util/generic-callbacks.h>
#include <lib/support/CodeUtils.h>
#include <lib/support/logging/CHIPLogging.h>
#include <platform/LockTracker.h>

// Attribute storage depends on knowing the current layout/setup of attributes
// and corresponding callbacks. Specifically:
//   - zap-generated/callback.h is needed because endpoint_config will call the
//     corresponding callbacks (via GENERATED_FUNCTION_ARRAYS) and the include
//     for it is:
//       util/common.h
//           -> util/af.h
//           -> util/config.h
//           -> zap-generated/endpoint_config.h
#include <app-common/zap-generated/callback.h>

using namespace chip;

//------------------------------------------------------------------------------
// Globals
// This is not declared CONST in order to handle dynamic endpoint information
// retrieved from tokens.
EmberAfDefinedEndpoint emAfEndpoints[MAX_ENDPOINT_COUNT];

#if (ATTRIBUTE_MAX_SIZE == 0)
#define ACTUAL_ATTRIBUTE_SIZE 1
#else
#define ACTUAL_ATTRIBUTE_SIZE ATTRIBUTE_MAX_SIZE
#endif

uint8_t attributeData[ACTUAL_ATTRIBUTE_SIZE];

namespace {

#if (!defined(ATTRIBUTE_SINGLETONS_SIZE)) || (ATTRIBUTE_SINGLETONS_SIZE == 0)
#define ACTUAL_SINGLETONS_SIZE 1
#else
#define ACTUAL_SINGLETONS_SIZE ATTRIBUTE_SINGLETONS_SIZE
#endif
uint8_t singletonAttributeData[ACTUAL_SINGLETONS_SIZE];

uint16_t emberEndpointCount = 0;

// If we have attributes that are more than 4 bytes, then
// we need this data block for the defaults
#if (defined(GENERATED_DEFAULTS) && GENERATED_DEFAULTS_COUNT)
constexpr const uint8_t generatedDefaults[] = GENERATED_DEFAULTS;
#endif // GENERATED_DEFAULTS

#if (defined(GENERATED_MIN_MAX_DEFAULTS) && GENERATED_MIN_MAX_DEFAULT_COUNT)
constexpr const EmberAfAttributeMinMaxValue minMaxDefaults[] = GENERATED_MIN_MAX_DEFAULTS;
#endif // GENERATED_MIN_MAX_DEFAULTS

#ifdef GENERATED_FUNCTION_ARRAYS
GENERATED_FUNCTION_ARRAYS
#endif

#ifdef GENERATED_COMMANDS
constexpr const chip::CommandId generatedCommands[] = GENERATED_COMMANDS;
#endif // GENERATED_COMMANDS

constexpr const EmberAfAttributeMetadata generatedAttributes[]      = GENERATED_ATTRIBUTES;
constexpr const EmberAfCluster generatedClusters[]                  = GENERATED_CLUSTERS;
constexpr const EmberAfEndpointType generatedEmberAfEndpointTypes[] = GENERATED_ENDPOINT_TYPES;
constexpr const EmberAfDeviceType fixedDeviceTypeList[]             = FIXED_DEVICE_TYPES;

// Not const, because these need to mutate.
DataVersion fixedEndpointDataVersions[ZAP_FIXED_ENDPOINT_DATA_VERSION_COUNT];

#if !defined(EMBER_SCRIPTED_TEST)
#define endpointNumber(x) fixedEndpoints[x]
#define endpointDeviceTypeList(x)                                                                                                  \
    Span<const EmberAfDeviceType>(&fixedDeviceTypeList[fixedDeviceTypeListOffsets[x]], fixedDeviceTypeListLengths[x])
// Added 'Macro' to silence MISRA warning about conflict with synonymous vars.
#define endpointTypeMacro(x) (&(generatedEmberAfEndpointTypes[fixedEmberAfEndpointTypes[x]]))
#endif

app::AttributeAccessInterface * gAttributeAccessOverrides = nullptr;
} // anonymous namespace

//------------------------------------------------------------------------------
// Forward declarations

// Returns endpoint index within a given cluster
static uint16_t findClusterEndpointIndex(EndpointId endpoint, ClusterId clusterId, uint8_t mask);

//------------------------------------------------------------------------------

// Initial configuration
void emberAfEndpointConfigure()
{
    uint16_t ep;

    static_assert(FIXED_ENDPOINT_COUNT <= std::numeric_limits<decltype(ep)>::max(),
                  "FIXED_ENDPOINT_COUNT must not exceed the size of the endpoint data type");

#if !defined(EMBER_SCRIPTED_TEST)
    uint16_t fixedEndpoints[]             = FIXED_ENDPOINT_ARRAY;
    uint16_t fixedDeviceTypeListLengths[] = FIXED_DEVICE_TYPE_LENGTHS;
    uint16_t fixedDeviceTypeListOffsets[] = FIXED_DEVICE_TYPE_OFFSETS;
    uint8_t fixedEmberAfEndpointTypes[]   = FIXED_ENDPOINT_TYPES;
#endif

#if ZAP_FIXED_ENDPOINT_DATA_VERSION_COUNT > 0
    // Initialize our data version storage.  If
    // ZAP_FIXED_ENDPOINT_DATA_VERSION_COUNT == 0, gcc complains about a memset
    // with size equal to number of elements without multiplication by element
    // size, because the sizeof() is also 0 in that case...
    if (Crypto::DRBG_get_bytes(reinterpret_cast<uint8_t *>(fixedEndpointDataVersions), sizeof(fixedEndpointDataVersions)) !=
        CHIP_NO_ERROR)
    {
        // Now what?  At least 0-init it.
        memset(fixedEndpointDataVersions, 0, sizeof(fixedEndpointDataVersions));
    }
#endif // ZAP_FIXED_ENDPOINT_DATA_VERSION_COUNT > 0

    emberEndpointCount                = FIXED_ENDPOINT_COUNT;
    DataVersion * currentDataVersions = fixedEndpointDataVersions;
    for (ep = 0; ep < FIXED_ENDPOINT_COUNT; ep++)
    {
        emAfEndpoints[ep].endpoint       = endpointNumber(ep);
        emAfEndpoints[ep].deviceTypeList = endpointDeviceTypeList(ep);
        emAfEndpoints[ep].endpointType   = endpointTypeMacro(ep);
        emAfEndpoints[ep].dataVersions   = currentDataVersions;
        emAfEndpoints[ep].bitmask        = EMBER_AF_ENDPOINT_ENABLED;

        // Increment currentDataVersions by 1 (slot) for every server cluster
        // this endpoint has.
        currentDataVersions += emberAfClusterCountByIndex(ep, /* server = */ true);
    }

#if CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT
    if (MAX_ENDPOINT_COUNT > FIXED_ENDPOINT_COUNT)
    {
        //
        // Reset instances tracking dynamic endpoints to safe defaults.
        //
        for (ep = FIXED_ENDPOINT_COUNT; ep < MAX_ENDPOINT_COUNT; ep++)
        {
            emAfEndpoints[ep] = EmberAfDefinedEndpoint();
        }
    }
#endif
}

void emberAfSetDynamicEndpointCount(uint16_t dynamicEndpointCount)
{
    emberEndpointCount = static_cast<uint16_t>(FIXED_ENDPOINT_COUNT + dynamicEndpointCount);
}

uint16_t emberAfGetDynamicIndexFromEndpoint(EndpointId id)
{
    if (id == kInvalidEndpointId)
    {
        return kEmberInvalidEndpointIndex;
    }

    uint16_t index;
    for (index = FIXED_ENDPOINT_COUNT; index < MAX_ENDPOINT_COUNT; index++)
    {
        if (emAfEndpoints[index].endpoint == id)
        {
            return static_cast<uint8_t>(index - FIXED_ENDPOINT_COUNT);
        }
    }
    return kEmberInvalidEndpointIndex;
}

EmberAfStatus emberAfSetDynamicEndpoint(uint16_t index, EndpointId id, const EmberAfEndpointType * ep,
                                        const chip::Span<chip::DataVersion> & dataVersionStorage,
                                        chip::Span<const EmberAfDeviceType> deviceTypeList, EndpointId parentEndpointId)
{
    auto realIndex = index + FIXED_ENDPOINT_COUNT;

    if (realIndex >= MAX_ENDPOINT_COUNT)
    {
        return EMBER_ZCL_STATUS_INSUFFICIENT_SPACE;
    }
    if (id == kInvalidEndpointId)
    {
        return EMBER_ZCL_STATUS_CONSTRAINT_ERROR;
    }

    auto serverClusterCount = emberAfClusterCountForEndpointType(ep, /* server = */ true);
    if (dataVersionStorage.size() < serverClusterCount)
    {
        return EMBER_ZCL_STATUS_INSUFFICIENT_SPACE;
    }

    index = static_cast<uint16_t>(realIndex);
    for (uint16_t i = FIXED_ENDPOINT_COUNT; i < MAX_ENDPOINT_COUNT; i++)
    {
        if (emAfEndpoints[i].endpoint == id)
        {
            return EMBER_ZCL_STATUS_DUPLICATE_EXISTS;
        }
    }

    emAfEndpoints[index].endpoint       = id;
    emAfEndpoints[index].deviceTypeList = deviceTypeList;
    emAfEndpoints[index].endpointType   = ep;
    emAfEndpoints[index].dataVersions   = dataVersionStorage.data();
    // Start the endpoint off as disabled.
    emAfEndpoints[index].bitmask          = EMBER_AF_ENDPOINT_DISABLED;
    emAfEndpoints[index].parentEndpointId = parentEndpointId;

    emberAfSetDynamicEndpointCount(MAX_ENDPOINT_COUNT - FIXED_ENDPOINT_COUNT);

    // Initialize the data versions.
    size_t dataSize = sizeof(DataVersion) * serverClusterCount;
    if (dataSize != 0)
    {
        if (Crypto::DRBG_get_bytes(reinterpret_cast<uint8_t *>(dataVersionStorage.data()), dataSize) != CHIP_NO_ERROR)
        {
            // Now what?  At least 0-init it.
            memset(dataVersionStorage.data(), 0, dataSize);
        }
    }

    // Now enable the endpoint.
    emberAfEndpointEnableDisable(id, true);

    return EMBER_ZCL_STATUS_SUCCESS;
}

EndpointId emberAfClearDynamicEndpoint(uint16_t index)
{
    EndpointId ep = 0;

    index = static_cast<uint8_t>(index + FIXED_ENDPOINT_COUNT);

    if ((index < MAX_ENDPOINT_COUNT) && (emAfEndpoints[index].endpoint != kInvalidEndpointId) &&
        (emberAfEndpointIndexIsEnabled(index)))
    {
        ep = emAfEndpoints[index].endpoint;
        emberAfEndpointEnableDisable(ep, false);
        emAfEndpoints[index].endpoint = kInvalidEndpointId;
    }

    return ep;
}

uint16_t emberAfFixedEndpointCount()
{
    return FIXED_ENDPOINT_COUNT;
}

uint16_t emberAfEndpointCount()
{
    return emberEndpointCount;
}

bool emberAfEndpointIndexIsEnabled(uint16_t index)
{
    return (emAfEndpoints[index].bitmask & EMBER_AF_ENDPOINT_ENABLED);
}

// some data types (like strings) are sent OTA in human readable order
// (how they are read) instead of little endian as the data types are.
bool emberAfIsThisDataTypeAStringType(EmberAfAttributeType dataType)
{
    return (dataType == ZCL_OCTET_STRING_ATTRIBUTE_TYPE || dataType == ZCL_CHAR_STRING_ATTRIBUTE_TYPE ||
            dataType == ZCL_LONG_OCTET_STRING_ATTRIBUTE_TYPE || dataType == ZCL_LONG_CHAR_STRING_ATTRIBUTE_TYPE);
}

bool emberAfIsStringAttributeType(EmberAfAttributeType attributeType)
{
    return (attributeType == ZCL_OCTET_STRING_ATTRIBUTE_TYPE || attributeType == ZCL_CHAR_STRING_ATTRIBUTE_TYPE);
}

bool emberAfIsLongStringAttributeType(EmberAfAttributeType attributeType)
{
    return (attributeType == ZCL_LONG_OCTET_STRING_ATTRIBUTE_TYPE || attributeType == ZCL_LONG_CHAR_STRING_ATTRIBUTE_TYPE);
}

bool emberAfIsThisDataTypeAListType(EmberAfAttributeType dataType)
{
    return dataType == ZCL_ARRAY_ATTRIBUTE_TYPE;
}

// This function is used to call the per-cluster attribute changed callback
void emAfClusterAttributeChangedCallback(const app::ConcreteAttributePath & attributePath)
{
    const EmberAfCluster * cluster = emberAfFindServerCluster(attributePath.mEndpointId, attributePath.mClusterId);
    if (cluster != nullptr)
    {
        EmberAfGenericClusterFunction f = emberAfFindClusterFunction(cluster, CLUSTER_MASK_ATTRIBUTE_CHANGED_FUNCTION);
        if (f != nullptr)
        {
            ((EmberAfClusterAttributeChangedCallback) f)(attributePath);
        }
    }
}

// This function is used to call the per-cluster pre-attribute changed callback
EmberAfStatus emAfClusterPreAttributeChangedCallback(const app::ConcreteAttributePath & attributePath,
                                                     EmberAfAttributeType attributeType, uint16_t size, uint8_t * value)
{
    const EmberAfCluster * cluster = emberAfFindServerCluster(attributePath.mEndpointId, attributePath.mClusterId);
    if (cluster == nullptr)
    {
        return EMBER_ZCL_STATUS_UNSUPPORTED_ATTRIBUTE;
    }

    EmberAfStatus status = EMBER_ZCL_STATUS_SUCCESS;
    // Casting and calling a function pointer on the same line results in ignoring the return
    // of the call on gcc-arm-none-eabi-9-2019-q4-major
    EmberAfClusterPreAttributeChangedCallback f = (EmberAfClusterPreAttributeChangedCallback)(
        emberAfFindClusterFunction(cluster, CLUSTER_MASK_PRE_ATTRIBUTE_CHANGED_FUNCTION));
    if (f != nullptr)
    {
        status = f(attributePath, attributeType, size, value);
    }
    return status;
}

static void initializeEndpoint(EmberAfDefinedEndpoint * definedEndpoint)
{
    uint8_t clusterIndex;
    const EmberAfEndpointType * epType = definedEndpoint->endpointType;
    for (clusterIndex = 0; clusterIndex < epType->clusterCount; clusterIndex++)
    {
        const EmberAfCluster * cluster = &(epType->cluster[clusterIndex]);
        EmberAfGenericClusterFunction f;
        emberAfClusterInitCallback(definedEndpoint->endpoint, cluster->clusterId);
        f = emberAfFindClusterFunction(cluster, CLUSTER_MASK_INIT_FUNCTION);
        if (f != nullptr)
        {
            ((EmberAfInitFunction) f)(definedEndpoint->endpoint);
        }
    }
}

// Calls the init functions.
void emAfCallInits()
{
    uint16_t index;
    for (index = 0; index < emberAfEndpointCount(); index++)
    {
        if (emberAfEndpointIndexIsEnabled(index))
        {
            initializeEndpoint(&(emAfEndpoints[index]));
        }
    }
}

// Returns the pointer to metadata, or null if it is not found
const EmberAfAttributeMetadata * emberAfLocateAttributeMetadata(EndpointId endpoint, ClusterId clusterId, AttributeId attributeId)
{
    const EmberAfAttributeMetadata * metadata = nullptr;
    EmberAfAttributeSearchRecord record;
    record.endpoint    = endpoint;
    record.clusterId   = clusterId;
    record.attributeId = attributeId;
    emAfReadOrWriteAttribute(&record, &metadata,
                             nullptr, // buffer
                             0,       // buffer size
                             false);  // write?
    return metadata;
}

static uint8_t * singletonAttributeLocation(const EmberAfAttributeMetadata * am)
{
    const EmberAfAttributeMetadata * m = &(generatedAttributes[0]);
    uint16_t index                     = 0;
    while (m < am)
    {
        if (m->IsSingleton() && !m->IsExternal())
        {
            index = static_cast<uint16_t>(index + m->size);
        }
        m++;
    }
    return (uint8_t *) (singletonAttributeData + index);
}

// This function does mem copy, but smartly, which means that if the type is a
// string, it will copy as much as it can.
// If src == NULL, then this method will set memory to zeroes
// See documentation for emAfReadOrWriteAttribute for the semantics of
// readLength when reading and writing.
static EmberAfStatus typeSensitiveMemCopy(ClusterId clusterId, uint8_t * dest, uint8_t * src, const EmberAfAttributeMetadata * am,
                                          bool write, uint16_t readLength)
{
    EmberAfAttributeType attributeType = am->attributeType;
    // readLength == 0 for a read indicates that we should just trust that the
    // caller has enough space for an attribute...
    bool ignoreReadLength = write || (readLength == 0);
    uint16_t bufferSize   = ignoreReadLength ? am->size : readLength;

    if (emberAfIsStringAttributeType(attributeType))
    {
        if (bufferSize < 1)
        {
            return EMBER_ZCL_STATUS_INSUFFICIENT_SPACE;
        }
        emberAfCopyString(dest, src, bufferSize - 1);
    }
    else if (emberAfIsLongStringAttributeType(attributeType))
    {
        if (bufferSize < 2)
        {
            return EMBER_ZCL_STATUS_INSUFFICIENT_SPACE;
        }
        emberAfCopyLongString(dest, src, bufferSize - 2);
    }
    else if (emberAfIsThisDataTypeAListType(attributeType))
    {
        if (bufferSize < 2)
        {
            return EMBER_ZCL_STATUS_INSUFFICIENT_SPACE;
        }

        // Just copy the length.
        memmove(dest, src, 2);
    }
    else
    {
        if (!ignoreReadLength && readLength < am->size)
        {
            return EMBER_ZCL_STATUS_INSUFFICIENT_SPACE;
        }
        if (src == nullptr)
        {
            memset(dest, 0, am->size);
        }
        else
        {
            memmove(dest, src, am->size);
        }
    }
    return EMBER_ZCL_STATUS_SUCCESS;
}

/**
 * @brief Matches a cluster based on cluster id and direction.
 *
 *   This function assumes that the passed cluster's endpoint already
 *   matches the endpoint of the EmberAfAttributeSearchRecord.
 *
 * Clusters match if:
 *   1. Cluster ids match AND
 *   2. Cluster is a server cluster (because there are no client attributes).
 */
bool emAfMatchCluster(const EmberAfCluster * cluster, EmberAfAttributeSearchRecord * attRecord)
{
    return (cluster->clusterId == attRecord->clusterId && (cluster->mask & CLUSTER_MASK_SERVER));
}

/**
 * @brief Matches an attribute based on attribute id.
 *   This function assumes that the passed cluster already matches the
 *   clusterId and direction of the passed EmberAfAttributeSearchRecord.
 *
 * Attributes match if attr ids match.
 */
bool emAfMatchAttribute(const EmberAfCluster * cluster, const EmberAfAttributeMetadata * am,
                        EmberAfAttributeSearchRecord * attRecord)
{
    return (am->attributeId == attRecord->attributeId);
}

// When reading non-string attributes, this function returns an error when destination
// buffer isn't large enough to accommodate the attribute type.  For strings, the
// function will copy at most readLength bytes.  This means the resulting string
// may be truncated.  The length byte(s) in the resulting string will reflect
// any truncation.  If readLength is zero, we are working with backwards-
// compatibility wrapper functions and we just cross our fingers and hope for
// the best.
//
// When writing attributes, readLength is ignored.  For non-string attributes,
// this function assumes the source buffer is the same size as the attribute
// type.  For strings, the function will copy as many bytes as will fit in the
// attribute.  This means the resulting string may be truncated.  The length
// byte(s) in the resulting string will reflect any truncated.
EmberAfStatus emAfReadOrWriteAttribute(EmberAfAttributeSearchRecord * attRecord, const EmberAfAttributeMetadata ** metadata,
                                       uint8_t * buffer, uint16_t readLength, bool write)
{
    assertChipStackLockedByCurrentThread();

    uint16_t attributeOffsetIndex = 0;

    for (uint16_t ep = 0; ep < emberAfEndpointCount(); ep++)
    {
        // Is this a dynamic endpoint?
        bool isDynamicEndpoint = (ep >= emberAfFixedEndpointCount());

        if (emAfEndpoints[ep].endpoint == attRecord->endpoint)
        {
            const EmberAfEndpointType * endpointType = emAfEndpoints[ep].endpointType;
            uint8_t clusterIndex;
            if (!emberAfEndpointIndexIsEnabled(ep))
            {
                continue;
            }
            for (clusterIndex = 0; clusterIndex < endpointType->clusterCount; clusterIndex++)
            {
                const EmberAfCluster * cluster = &(endpointType->cluster[clusterIndex]);
                if (emAfMatchCluster(cluster, attRecord))
                { // Got the cluster
                    uint16_t attrIndex;
                    for (attrIndex = 0; attrIndex < cluster->attributeCount; attrIndex++)
                    {
                        const EmberAfAttributeMetadata * am = &(cluster->attributes[attrIndex]);
                        if (emAfMatchAttribute(cluster, am, attRecord))
                        { // Got the attribute
                            // If passed metadata location is not null, populate
                            if (metadata != nullptr)
                            {
                                *metadata = am;
                            }

                            {
                                uint8_t * attributeLocation =
                                    (am->mask & ATTRIBUTE_MASK_SINGLETON ? singletonAttributeLocation(am)
                                                                         : attributeData + attributeOffsetIndex);
                                uint8_t *src, *dst;
                                if (write)
                                {
                                    src = buffer;
                                    dst = attributeLocation;
                                    if (!emberAfAttributeWriteAccessCallback(attRecord->endpoint, attRecord->clusterId,
                                                                             am->attributeId))
                                    {
                                        return EMBER_ZCL_STATUS_NOT_AUTHORIZED;
                                    }
                                }
                                else
                                {
                                    if (buffer == nullptr)
                                    {
                                        return EMBER_ZCL_STATUS_SUCCESS;
                                    }

                                    src = attributeLocation;
                                    dst = buffer;
                                    if (!emberAfAttributeReadAccessCallback(attRecord->endpoint, attRecord->clusterId,
                                                                            am->attributeId))
                                    {
                                        return EMBER_ZCL_STATUS_NOT_AUTHORIZED;
                                    }
                                }

                                // Is the attribute externally stored?
                                if (am->mask & ATTRIBUTE_MASK_EXTERNAL_STORAGE)
                                {
                                    return (write ? emberAfExternalAttributeWriteCallback(attRecord->endpoint, attRecord->clusterId,
                                                                                          am, buffer)
                                                  : emberAfExternalAttributeReadCallback(attRecord->endpoint, attRecord->clusterId,
                                                                                         am, buffer, emberAfAttributeSize(am)));
                                }

                                // Internal storage is only supported for fixed endpoints
                                if (!isDynamicEndpoint)
                                {
                                    return typeSensitiveMemCopy(attRecord->clusterId, dst, src, am, write, readLength);
                                }

                                return EMBER_ZCL_STATUS_FAILURE;
                            }
                        }
                        else
                        { // Not the attribute we are looking for
                            // Increase the index if attribute is not externally stored
                            if (!(am->mask & ATTRIBUTE_MASK_EXTERNAL_STORAGE) && !(am->mask & ATTRIBUTE_MASK_SINGLETON))
                            {
                                attributeOffsetIndex = static_cast<uint16_t>(attributeOffsetIndex + emberAfAttributeSize(am));
                            }
                        }
                    }
                }
                else
                { // Not the cluster we are looking for
                    attributeOffsetIndex = static_cast<uint16_t>(attributeOffsetIndex + cluster->clusterSize);
                }
            }
        }
        else
        { // Not the endpoint we are looking for
            // Dynamic endpoints are external and don't factor into storage size
            if (!isDynamicEndpoint)
            {
                attributeOffsetIndex = static_cast<uint16_t>(attributeOffsetIndex + emAfEndpoints[ep].endpointType->endpointSize);
            }
        }
    }
    return EMBER_ZCL_STATUS_UNSUPPORTED_ATTRIBUTE; // Sorry, attribute was not found.
}

const EmberAfEndpointType * emberAfFindEndpointType(chip::EndpointId endpointId)
{
    uint16_t ep = emberAfIndexFromEndpoint(endpointId);
    if (ep == kEmberInvalidEndpointIndex)
    {
        return nullptr;
    }
    return emAfEndpoints[ep].endpointType;
}

const EmberAfCluster * emberAfFindClusterInType(const EmberAfEndpointType * endpointType, ClusterId clusterId,
                                                EmberAfClusterMask mask, uint8_t * index)
{
    uint8_t i;
    uint8_t scopedIndex = 0;

    for (i = 0; i < endpointType->clusterCount; i++)
    {
        const EmberAfCluster * cluster = &(endpointType->cluster[i]);

        if ((mask == 0 || (mask == CLUSTER_MASK_CLIENT && emberAfClusterIsClient(cluster)) ||
             (mask == CLUSTER_MASK_SERVER && emberAfClusterIsServer(cluster))))
        {
            if (cluster->clusterId == clusterId)
            {
                if (index)
                {
                    *index = scopedIndex;
                }

                return cluster;
            }

            scopedIndex++;
        }
    }

    return nullptr;
}

uint8_t emberAfClusterIndex(EndpointId endpoint, ClusterId clusterId, EmberAfClusterMask mask)
{
    for (uint16_t ep = 0; ep < emberAfEndpointCount(); ep++)
    {
        // Check the endpoint id first, because that way we avoid examining the
        // endpoint type for endpoints that are not actually defined.
        if (emAfEndpoints[ep].endpoint == endpoint)
        {
            const EmberAfEndpointType * endpointType = emAfEndpoints[ep].endpointType;
            uint8_t index                            = 0xFF;
            if (emberAfFindClusterInType(endpointType, clusterId, mask, &index) != nullptr)
            {
                return index;
            }
        }
    }
    return 0xFF;
}

// Returns whether the given endpoint has the server of the given cluster on it.
bool emberAfContainsServer(EndpointId endpoint, ClusterId clusterId)
{
    return (emberAfFindServerCluster(endpoint, clusterId) != nullptr);
}

// This will find the first server that has the clusterId given from the index of endpoint.
bool emberAfContainsServerFromIndex(uint16_t index, ClusterId clusterId)
{
    if (index == kEmberInvalidEndpointIndex)
    {
        return false;
    }

    return emberAfFindClusterInType(emAfEndpoints[index].endpointType, clusterId, CLUSTER_MASK_SERVER);
}

namespace chip {
namespace app {

EnabledEndpointsWithServerCluster::EnabledEndpointsWithServerCluster(ClusterId clusterId) : mClusterId(clusterId)
{
    EnsureMatchingEndpoint();
}
EnabledEndpointsWithServerCluster & EnabledEndpointsWithServerCluster::operator++()
{
    ++mEndpointIndex;
    EnsureMatchingEndpoint();
    return *this;
}

void EnabledEndpointsWithServerCluster::EnsureMatchingEndpoint()
{
    for (; mEndpointIndex < mEndpointCount; ++mEndpointIndex)
    {
        if (!emberAfEndpointIndexIsEnabled(mEndpointIndex))
        {
            continue;
        }

        if (emberAfContainsServerFromIndex(mEndpointIndex, mClusterId))
        {
            break;
        }
    }
}

} // namespace app
} // namespace chip

// Finds the cluster that matches endpoint, clusterId, direction.
const EmberAfCluster * emberAfFindServerCluster(EndpointId endpoint, ClusterId clusterId)
{
    uint16_t ep = emberAfIndexFromEndpoint(endpoint);
    if (ep == kEmberInvalidEndpointIndex)
    {
        return nullptr;
    }

    return emberAfFindClusterInType(emAfEndpoints[ep].endpointType, clusterId, CLUSTER_MASK_SERVER);
}

// Returns cluster within the endpoint; Does not ignore disabled endpoints
const EmberAfCluster * emberAfFindClusterIncludingDisabledEndpoints(EndpointId endpoint, ClusterId clusterId,
                                                                    EmberAfClusterMask mask)
{
    uint16_t ep = emberAfIndexFromEndpointIncludingDisabledEndpoints(endpoint);
    if (ep < MAX_ENDPOINT_COUNT)
    {
        return emberAfFindClusterInType(emAfEndpoints[ep].endpointType, clusterId, mask);
    }
    return nullptr;
}

// Server wrapper for findClusterEndpointIndex
uint16_t emberAfFindClusterServerEndpointIndex(EndpointId endpoint, ClusterId clusterId)
{
    return findClusterEndpointIndex(endpoint, clusterId, CLUSTER_MASK_SERVER);
}

// Returns the endpoint index within a given cluster
static uint16_t findClusterEndpointIndex(EndpointId endpoint, ClusterId clusterId, uint8_t mask)
{
    uint16_t i, epi = 0;

    if (emberAfFindServerCluster(endpoint, clusterId) == nullptr)
    {
        return kEmberInvalidEndpointIndex;
    }

    for (i = 0; i < emberAfEndpointCount(); i++)
    {
        if (emAfEndpoints[i].endpoint == endpoint)
        {
            break;
        }
        if (emAfEndpoints[i].endpoint == kInvalidEndpointId)
        {
            // Not actually a configured endpoint.
            continue;
        }
        epi = static_cast<uint16_t>(
            epi + ((emberAfFindClusterIncludingDisabledEndpoints(emAfEndpoints[i].endpoint, clusterId, mask) != nullptr) ? 1 : 0));
    }

    return epi;
}

static uint16_t findIndexFromEndpoint(EndpointId endpoint, bool ignoreDisabledEndpoints)
{
    if (endpoint == kInvalidEndpointId)
    {
        return kEmberInvalidEndpointIndex;
    }

    uint16_t epi;
    for (epi = 0; epi < emberAfEndpointCount(); epi++)
    {
        if (emAfEndpoints[epi].endpoint == endpoint &&
            (!ignoreDisabledEndpoints || emAfEndpoints[epi].bitmask & EMBER_AF_ENDPOINT_ENABLED))
        {
            return epi;
        }
    }
    return kEmberInvalidEndpointIndex;
}

bool emberAfEndpointIsEnabled(EndpointId endpoint)
{
    uint16_t index = findIndexFromEndpoint(endpoint,
                                           false); // ignore disabled endpoints?

    EMBER_TEST_ASSERT(kEmberInvalidEndpointIndex != index);

    if (kEmberInvalidEndpointIndex == index)
    {
        return false;
    }

    return emberAfEndpointIndexIsEnabled(index);
}

bool emberAfEndpointEnableDisable(EndpointId endpoint, bool enable)
{
    uint16_t index = findIndexFromEndpoint(endpoint,
                                           false); // ignore disabled endpoints?
    bool currentlyEnabled;

    if (kEmberInvalidEndpointIndex == index)
    {
        return false;
    }

    currentlyEnabled = emAfEndpoints[index].bitmask & EMBER_AF_ENDPOINT_ENABLED;

    if (enable)
    {
        emAfEndpoints[index].bitmask |= EMBER_AF_ENDPOINT_ENABLED;
    }
    else
    {
        emAfEndpoints[index].bitmask &= EMBER_AF_ENDPOINT_DISABLED;
    }

#if defined(EZSP_HOST)
    ezspSetEndpointFlags(endpoint, (enable ? EZSP_ENDPOINT_ENABLED : EZSP_ENDPOINT_DISABLED));
#endif

    if (currentlyEnabled != enable)
    {
        if (enable)
        {
            initializeEndpoint(&(emAfEndpoints[index]));
            MatterReportingAttributeChangeCallback(endpoint);
        }
        else
        {
            uint8_t i;
            for (i = 0; i < emAfEndpoints[index].endpointType->clusterCount; i++)
            {
                const EmberAfCluster * cluster = &((emAfEndpoints[index].endpointType->cluster)[i]);
                //        emberAfCorePrintln("Disabling cluster tick for ep:%d, cluster:0x%2X, %p",
                //                           endpoint,
                //                           cluster->clusterId,
                //                           ((cluster->mask & CLUSTER_MASK_CLIENT)
                //                            ? "client"
                //                            : "server"));
                //        emberAfCoreFlush();
                emberAfDeactivateClusterTick(
                    endpoint, cluster->clusterId,
                    (cluster->mask & CLUSTER_MASK_CLIENT ? EMBER_AF_CLIENT_CLUSTER_TICK : EMBER_AF_SERVER_CLUSTER_TICK));
            }

            // Clear out any command handler overrides registered for this
            // endpoint.
            chip::app::InteractionModelEngine::GetInstance()->UnregisterCommandHandlers(endpoint);

            // Clear out any attribute access overrides registered for this
            // endpoint.
            app::AttributeAccessInterface * prev = nullptr;
            app::AttributeAccessInterface * cur  = gAttributeAccessOverrides;
            while (cur)
            {
                app::AttributeAccessInterface * next = cur->GetNext();
                if (cur->MatchesEndpoint(endpoint))
                {
                    // Remove it from the list
                    if (prev)
                    {
                        prev->SetNext(next);
                    }
                    else
                    {
                        gAttributeAccessOverrides = next;
                    }

                    cur->SetNext(nullptr);

                    // Do not change prev in this case.
                }
                else
                {
                    prev = cur;
                }
                cur = next;
            }
        }

        EndpointId parentEndpointId = emberAfParentEndpointFromIndex(index);
        while (parentEndpointId != kInvalidEndpointId)
        {
            MatterReportingAttributeChangeCallback(parentEndpointId, app::Clusters::Descriptor::Id,
                                                   app::Clusters::Descriptor::Attributes::PartsList::Id);
            uint16_t parentIndex = emberAfIndexFromEndpoint(parentEndpointId);
            if (parentIndex == kEmberInvalidEndpointIndex)
            {
                // Something has gone wrong.
                break;
            }
            parentEndpointId = emberAfParentEndpointFromIndex(parentIndex);
        }

        MatterReportingAttributeChangeCallback(/* endpoint = */ 0, app::Clusters::Descriptor::Id,
                                               app::Clusters::Descriptor::Attributes::PartsList::Id);
    }

    return true;
}

// Returns the index of a given endpoint.  Does not consider disabled endpoints.
uint16_t emberAfIndexFromEndpoint(EndpointId endpoint)
{
    return findIndexFromEndpoint(endpoint,
                                 true); // ignore disabled endpoints?
}

// Returns the index of a given endpoint.  Considers disabled endpoints.
uint16_t emberAfIndexFromEndpointIncludingDisabledEndpoints(EndpointId endpoint)
{
    return findIndexFromEndpoint(endpoint,
                                 false); // ignore disabled endpoints?
}

EndpointId emberAfEndpointFromIndex(uint16_t index)
{
    return emAfEndpoints[index].endpoint;
}

EndpointId emberAfParentEndpointFromIndex(uint16_t index)
{
    return emAfEndpoints[index].parentEndpointId;
}

// If server == true, returns the number of server clusters,
// otherwise number of client clusters on this endpoint
uint8_t emberAfClusterCount(EndpointId endpoint, bool server)
{
    uint16_t index = emberAfIndexFromEndpoint(endpoint);
    if (index == kEmberInvalidEndpointIndex)
    {
        return 0;
    }

    return emberAfClusterCountByIndex(index, server);
}

uint8_t emberAfClusterCountByIndex(uint16_t endpointIndex, bool server)
{
    const EmberAfDefinedEndpoint * de = &(emAfEndpoints[endpointIndex]);
    if (de->endpointType == nullptr)
    {
        return 0;
    }

    return emberAfClusterCountForEndpointType(de->endpointType, server);
}

uint8_t emberAfClusterCountForEndpointType(const EmberAfEndpointType * type, bool server)
{
    uint8_t c = 0;
    for (uint8_t i = 0; i < type->clusterCount; i++)
    {
        auto * cluster = &(type->cluster[i]);
        if (server && emberAfClusterIsServer(cluster))
        {
            c++;
        }
        if ((!server) && emberAfClusterIsClient(cluster))
        {
            c++;
        }
    }
    return c;
}

uint8_t emberAfGetClusterCountForEndpoint(EndpointId endpoint)
{
    uint16_t index = emberAfIndexFromEndpoint(endpoint);
    if (index == kEmberInvalidEndpointIndex)
    {
        return 0;
    }
    return emAfEndpoints[index].endpointType->clusterCount;
}

// Note the difference in implementation from emberAfGetNthCluster().
// emberAfGetClusterByIndex() retrieves the cluster by index regardless of server/client
// and those indexes may be DIFFERENT than the indexes returned from
// emberAfGetNthCluster().  In other words:
//
//  - Use emberAfGetClustersFromEndpoint()  with emberAfGetNthCluster()
//  - Use emberAfGetClusterCountForEndpoint() with emberAfGetClusterByIndex()
//
// Don't mix them.
const EmberAfCluster * emberAfGetClusterByIndex(EndpointId endpoint, uint8_t clusterIndex)
{
    uint16_t endpointIndex = emberAfIndexFromEndpoint(endpoint);
    EmberAfDefinedEndpoint * definedEndpoint;

    if (endpointIndex == kEmberInvalidEndpointIndex)
    {
        return nullptr;
    }
    definedEndpoint = &(emAfEndpoints[endpointIndex]);

    if (clusterIndex >= definedEndpoint->endpointType->clusterCount)
    {
        return nullptr;
    }
    return &(definedEndpoint->endpointType->cluster[clusterIndex]);
}

chip::Span<const EmberAfDeviceType> emberAfDeviceTypeListFromEndpoint(chip::EndpointId endpoint, CHIP_ERROR & err)
{
    uint16_t endpointIndex = emberAfIndexFromEndpoint(endpoint);
    chip::Span<const EmberAfDeviceType> ret;

    if (endpointIndex == 0xFFFF)
    {
        err = CHIP_ERROR_INVALID_ARGUMENT;
        return ret;
    }

    err = CHIP_NO_ERROR;
    return emAfEndpoints[endpointIndex].deviceTypeList;
}

CHIP_ERROR emberAfSetDeviceTypeList(EndpointId endpoint, Span<const EmberAfDeviceType> deviceTypeList)
{
    uint16_t endpointIndex = emberAfIndexFromEndpoint(endpoint);
    if (endpointIndex == 0xFFFF)
    {
        return CHIP_ERROR_INVALID_ARGUMENT;
    }

    emAfEndpoints[endpointIndex].deviceTypeList = deviceTypeList;
    return CHIP_NO_ERROR;
}

// Returns the cluster of Nth server or client cluster,
// depending on server toggle.
const EmberAfCluster * emberAfGetNthCluster(EndpointId endpoint, uint8_t n, bool server)
{
    uint16_t index = emberAfIndexFromEndpoint(endpoint);
    EmberAfDefinedEndpoint * de;
    uint8_t i, c = 0;
    const EmberAfCluster * cluster;

    if (index == kEmberInvalidEndpointIndex)
    {
        return nullptr;
    }
    de = &(emAfEndpoints[index]);

    for (i = 0; i < de->endpointType->clusterCount; i++)
    {
        cluster = &(de->endpointType->cluster[i]);

        if ((server && emberAfClusterIsServer(cluster)) || ((!server) && emberAfClusterIsClient(cluster)))
        {
            if (c == n)
            {
                return cluster;
            }
            c++;
        }
    }
    return nullptr;
}

// Returns the cluster id of Nth server or client cluster,
// depending on server toggle.
// Returns Optional<ClusterId>::Missing() if cluster does not exist.
Optional<ClusterId> emberAfGetNthClusterId(EndpointId endpoint, uint8_t n, bool server)
{
    const EmberAfCluster * cluster = emberAfGetNthCluster(endpoint, n, server);
    if (cluster == nullptr)
    {
        return Optional<ClusterId>::Missing();
    }
    return Optional<ClusterId>(cluster->clusterId);
}

// Returns number of clusters put into the passed cluster list
// for the given endpoint and client/server polarity
uint8_t emberAfGetClustersFromEndpoint(EndpointId endpoint, ClusterId * clusterList, uint8_t listLen, bool server)
{
    uint8_t clusterCount = emberAfClusterCount(endpoint, server);
    uint8_t i;
    const EmberAfCluster * cluster;
    if (clusterCount > listLen)
    {
        clusterCount = listLen;
    }
    for (i = 0; i < clusterCount; i++)
    {
        cluster        = emberAfGetNthCluster(endpoint, i, server);
        clusterList[i] = (cluster == nullptr ? kEmberInvalidEndpointIndex : cluster->clusterId);
    }
    return clusterCount;
}

void emberAfInitializeAttributes(EndpointId endpoint)
{
    emAfLoadAttributeDefaults(endpoint, false);
}

void emberAfResetAttributes(EndpointId endpoint)
{
    emAfLoadAttributeDefaults(endpoint, true);
}

void emAfLoadAttributeDefaults(EndpointId endpoint, bool ignoreStorage, Optional<ClusterId> clusterId)
{
    uint16_t ep;
    uint8_t clusterI;
    uint16_t attr;
    uint8_t * ptr;
    uint16_t epCount = emberAfEndpointCount();
    uint8_t attrData[ATTRIBUTE_LARGEST];
    auto * attrStorage = ignoreStorage ? nullptr : app::GetAttributePersistenceProvider();
    // Don't check whether we actually have an attrStorage here, because it's OK
    // to have one if none of our attributes have NVM storage.

    for (ep = 0; ep < epCount; ep++)
    {
        EmberAfDefinedEndpoint * de;
        if (endpoint != EMBER_BROADCAST_ENDPOINT)
        {
            ep = emberAfIndexFromEndpoint(endpoint);
            if (ep == kEmberInvalidEndpointIndex)
            {
                return;
            }
        }
        de = &(emAfEndpoints[ep]);

        for (clusterI = 0; clusterI < de->endpointType->clusterCount; clusterI++)
        {
            const EmberAfCluster * cluster = &(de->endpointType->cluster[clusterI]);
            if (clusterId.HasValue())
            {
                if (clusterId.Value() != cluster->clusterId)
                {
                    continue;
                }
            }

            // when the attributeCount is high, the loop takes too long to run and a
            // watchdog kicks in causing a reset. As a workaround, we'll
            // conditionally manually reset the watchdog. 300 sounds like a good
            // magic number for now.
            if (cluster->attributeCount > 300)
            {
                // halResetWatchdog();
            }
            for (attr = 0; attr < cluster->attributeCount; attr++)
            {
                const EmberAfAttributeMetadata * am = &(cluster->attributes[attr]);
                ptr                                 = nullptr; // Will get set to the value to write, as needed.

                // First check for a persisted value.
                if (!ignoreStorage && am->IsAutomaticallyPersisted())
                {
                    VerifyOrDie(attrStorage && "Attribute persistence needs a persistence provider");
                    MutableByteSpan bytes(attrData);
                    CHIP_ERROR err = attrStorage->ReadValue(
                        app::ConcreteAttributePath(de->endpoint, cluster->clusterId, am->attributeId), am, bytes);
                    if (err == CHIP_NO_ERROR)
                    {
                        ptr = attrData;
                    }
                    else
                    {
                        ChipLogDetail(
                            DataManagement,
                            "Failed to read stored attribute (%u, " ChipLogFormatMEI ", " ChipLogFormatMEI ": %" CHIP_ERROR_FORMAT,
                            de->endpoint, ChipLogValueMEI(cluster->clusterId), ChipLogValueMEI(am->attributeId), err.Format());
                        // Just fall back to default value.
                    }
                }

                if (!am->IsExternal())
                {
                    EmberAfAttributeSearchRecord record;
                    record.endpoint    = de->endpoint;
                    record.clusterId   = cluster->clusterId;
                    record.attributeId = am->attributeId;

                    if (ptr == nullptr)
                    {
                        size_t defaultValueSizeForBigEndianNudger = 0;
                        // Bypasses compiler warning about unused variable for little endian platforms.
                        (void) defaultValueSizeForBigEndianNudger;
                        if ((am->mask & ATTRIBUTE_MASK_MIN_MAX) != 0U)
                        {
                            // This is intentionally 2 and not 4 bytes since defaultValue in min/max
                            // attributes is still uint16_t.
                            if (emberAfAttributeSize(am) <= 2)
                            {
                                static_assert(sizeof(am->defaultValue.ptrToMinMaxValue->defaultValue.defaultValue) == 2,
                                              "if statement relies on size of max/min defaultValue being 2");
                                ptr = (uint8_t *) &(am->defaultValue.ptrToMinMaxValue->defaultValue.defaultValue);
                                defaultValueSizeForBigEndianNudger =
                                    sizeof(am->defaultValue.ptrToMinMaxValue->defaultValue.defaultValue);
                            }
                            else
                            {
                                ptr = (uint8_t *) am->defaultValue.ptrToMinMaxValue->defaultValue.ptrToDefaultValue;
                            }
                        }
                        else
                        {
                            if ((emberAfAttributeSize(am) <= 4) && !emberAfIsStringAttributeType(am->attributeType))
                            {
                                ptr                                = (uint8_t *) &(am->defaultValue.defaultValue);
                                defaultValueSizeForBigEndianNudger = sizeof(am->defaultValue.defaultValue);
                            }
                            else
                            {
                                ptr = (uint8_t *) am->defaultValue.ptrToDefaultValue;
                            }
                        }
                        // At this point, ptr either points to a default value, or is NULL, in which case
                        // it should be treated as if it is pointing to an array of all zeroes.

#if (BIGENDIAN_CPU)
                        // The default values for attributes that are less than or equal to
                        // defaultValueSizeForBigEndianNudger in bytes are stored in an
                        // uint32_t.  On big-endian platforms, a pointer to the default value
                        // of size less than defaultValueSizeForBigEndianNudger will point to the wrong
                        // byte.  So, for those cases, nudge the pointer forward so it points
                        // to the correct byte.
                        if (emberAfAttributeSize(am) < defaultValueSizeForBigEndianNudger && ptr != NULL)
                        {
                            ptr += (defaultValueSizeForBigEndianNudger - emberAfAttributeSize(am));
                        }
#endif // BIGENDIAN
                    }

                    emAfReadOrWriteAttribute(&record,
                                             nullptr, // metadata - unused
                                             ptr,
                                             0,     // buffer size - unused
                                             true); // write?
                    if (ignoreStorage)
                    {
                        emAfSaveAttributeToStorageIfNeeded(ptr, de->endpoint, record.clusterId, am);
                    }
                }
            }
        }
        if (endpoint != EMBER_BROADCAST_ENDPOINT)
        {
            break;
        }
    }
}

// 'data' argument may be null, since we changed the ptrToDefaultValue
// to be null instead of pointing to all zeroes.
// This function has to be able to deal with that.
void emAfSaveAttributeToStorageIfNeeded(uint8_t * data, EndpointId endpoint, ClusterId clusterId,
                                        const EmberAfAttributeMetadata * metadata)
{
    // Get out of here if this attribute isn't marked non-volatile.
    if (!metadata->IsAutomaticallyPersisted())
    {
        return;
    }

    // TODO: Maybe we should have a separate constant for the size of the
    // largest non-volatile attribute?
    uint8_t allZeroData[ATTRIBUTE_LARGEST] = { 0 };
    if (data == nullptr)
    {
        data = allZeroData;
    }

    size_t dataSize;
    EmberAfAttributeType type = metadata->attributeType;
    if (emberAfIsStringAttributeType(type))
    {
        dataSize = emberAfStringLength(data) + 1;
    }
    else if (emberAfIsLongStringAttributeType(type))
    {
        dataSize = emberAfLongStringLength(data) + 2;
    }
    else
    {
        dataSize = metadata->size;
    }

    auto * attrStorage = app::GetAttributePersistenceProvider();
    if (attrStorage)
    {
        attrStorage->WriteValue(app::ConcreteAttributePath(endpoint, clusterId, metadata->attributeId), ByteSpan(data, dataSize));
    }
    else
    {
        ChipLogProgress(DataManagement, "Can't store attribute value: no persistence provider");
    }
}

// This function returns the actual function point from the array,
// iterating over the function bits.
EmberAfGenericClusterFunction emberAfFindClusterFunction(const EmberAfCluster * cluster, EmberAfClusterMask functionMask)
{
    EmberAfClusterMask mask = 0x01;
    uint8_t functionIndex   = 0;

    if ((cluster->mask & functionMask) == 0)
    {
        return nullptr;
    }

    while (mask < functionMask)
    {
        if ((cluster->mask & mask) != 0)
        {
            functionIndex++;
        }
        mask = static_cast<EmberAfClusterMask>(mask << 1);
    }
    return cluster->functions[functionIndex];
}

bool registerAttributeAccessOverride(app::AttributeAccessInterface * attrOverride)
{
    for (auto * cur = gAttributeAccessOverrides; cur; cur = cur->GetNext())
    {
        if (cur->Matches(*attrOverride))
        {
            ChipLogError(Zcl, "Duplicate attribute override registration failed");
            return false;
        }
    }
    attrOverride->SetNext(gAttributeAccessOverrides);
    gAttributeAccessOverrides = attrOverride;
    return true;
}

namespace chip {
namespace app {
app::AttributeAccessInterface * GetAttributeAccessOverride(EndpointId endpointId, ClusterId clusterId)
{
    for (app::AttributeAccessInterface * cur = gAttributeAccessOverrides; cur; cur = cur->GetNext())
    {
        if (cur->Matches(endpointId, clusterId))
        {
            return cur;
        }
    }

    return nullptr;
}
} // namespace app
} // namespace chip

uint16_t emberAfGetServerAttributeCount(chip::EndpointId endpoint, chip::ClusterId cluster)
{
    const EmberAfCluster * clusterObj = emberAfFindServerCluster(endpoint, cluster);
    VerifyOrReturnError(clusterObj != nullptr, 0);
    return clusterObj->attributeCount;
}

uint16_t emberAfGetServerAttributeIndexByAttributeId(chip::EndpointId endpoint, chip::ClusterId cluster,
                                                     chip::AttributeId attributeId)
{
    const EmberAfCluster * clusterObj = emberAfFindServerCluster(endpoint, cluster);
    VerifyOrReturnError(clusterObj != nullptr, UINT16_MAX);

    for (uint16_t i = 0; i < clusterObj->attributeCount; i++)
    {
        if (clusterObj->attributes[i].attributeId == attributeId)
        {
            return i;
        }
    }
    return UINT16_MAX;
}

Optional<AttributeId> emberAfGetServerAttributeIdByIndex(EndpointId endpoint, ClusterId cluster, uint16_t attributeIndex)
{
    const EmberAfCluster * clusterObj = emberAfFindServerCluster(endpoint, cluster);
    if (clusterObj == nullptr || clusterObj->attributeCount <= attributeIndex)
    {
        return Optional<AttributeId>::Missing();
    }
    return Optional<AttributeId>(clusterObj->attributes[attributeIndex].attributeId);
}

DataVersion * emberAfDataVersionStorage(const chip::app::ConcreteClusterPath & aConcreteClusterPath)
{
    uint16_t index = emberAfIndexFromEndpoint(aConcreteClusterPath.mEndpointId);
    if (index == kEmberInvalidEndpointIndex)
    {
        // Unknown endpoint.
        return nullptr;
    }
    const EmberAfDefinedEndpoint & ep = emAfEndpoints[index];
    if (!ep.dataVersions)
    {
        // No storage provided.
        return nullptr;
    }

    // This does a second walk over endpoints to find the right one, but
    // probably worth it to avoid duplicating code.
    auto clusterIndex = emberAfClusterIndex(aConcreteClusterPath.mEndpointId, aConcreteClusterPath.mClusterId, CLUSTER_MASK_SERVER);
    if (clusterIndex == 0xFF)
    {
        // No such cluster on this endpoint.
        return nullptr;
    }

    return ep.dataVersions + clusterIndex;
}
