/**
 *
 *    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(void)
{
    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);
    emberAfSetDeviceEnabled(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;
        emberAfSetDeviceEnabled(ep, false);
        emberAfEndpointEnableDisable(ep, false);
        emAfEndpoints[index].endpoint = kInvalidEndpointId;
    }

    return ep;
}

uint16_t emberAfFixedEndpointCount(void)
{
    return FIXED_ENDPOINT_COUNT;
}

uint16_t emberAfEndpointCount(void)
{
    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(void)
{
    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;
}
