/*
 *
 *    Copyright (c) 2021 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.
 */

/**
 *    @file
 *          Contains the functions for compatibility with ember ZCL inner state
 *          when calling ember callbacks.
 */

#include <app/ClusterInfo.h>
#include <app/Command.h>
#include <app/ConcreteAttributePath.h>
#include <app/InteractionModelEngine.h>
#include <app/reporting/Engine.h>
#include <app/reporting/reporting.h>
#include <app/util/af.h>
#include <app/util/attribute-storage.h>
#include <app/util/attribute-table.h>
#include <app/util/ember-compatibility-functions.h>
#include <app/util/error-mapping.h>
#include <app/util/util.h>
#include <lib/core/CHIPCore.h>
#include <lib/core/CHIPTLV.h>
#include <lib/support/CodeUtils.h>
#include <lib/support/SafeInt.h>
#include <lib/support/TypeTraits.h>
#include <protocols/interaction_model/Constants.h>

#include <app-common/zap-generated/att-storage.h>
#include <app-common/zap-generated/attribute-type.h>

#include <zap-generated/endpoint_config.h>

using namespace chip;
using namespace chip::app;
using namespace chip::app::Compatibility;

namespace chip {
namespace app {
namespace Compatibility {
namespace {
constexpr uint32_t kTemporaryDataVersion = 0;
// On some apps, ATTRIBUTE_LARGEST can as small as 3, making compiler unhappy since data[kAttributeReadBufferSize] cannot hold
// uint64_t. Make kAttributeReadBufferSize at least 8 so it can fit all basic types.
constexpr size_t kAttributeReadBufferSize = (ATTRIBUTE_LARGEST >= 8 ? ATTRIBUTE_LARGEST : 8);
EmberAfClusterCommand imCompatibilityEmberAfCluster;
EmberApsFrame imCompatibilityEmberApsFrame;
EmberAfInterpanHeader imCompatibilityInterpanHeader;
Command * currentCommandObject;

// BasicType maps the type to basic int(8|16|32|64)(s|u) types.
EmberAfAttributeType BaseType(EmberAfAttributeType type)
{
    switch (type)
    {
    case ZCL_ACTION_ID_ATTRIBUTE_TYPE:  // Action Id
    case ZCL_FABRIC_IDX_ATTRIBUTE_TYPE: // Fabric Index
    case ZCL_BITMAP8_ATTRIBUTE_TYPE:    // 8-bit bitmap
    case ZCL_ENUM8_ATTRIBUTE_TYPE:      // 8-bit enumeration
        return ZCL_INT8U_ATTRIBUTE_TYPE;

    case ZCL_ENDPOINT_NO_ATTRIBUTE_TYPE: // Endpoint Number
    case ZCL_GROUP_ID_ATTRIBUTE_TYPE:    // Group Id
    case ZCL_VENDOR_ID_ATTRIBUTE_TYPE:   // Vendor Id
    case ZCL_ENUM16_ATTRIBUTE_TYPE:      // 16-bit enumeration
    case ZCL_BITMAP16_ATTRIBUTE_TYPE:    // 16-bit bitmap
    case ZCL_STATUS_ATTRIBUTE_TYPE:      // Status Code
        static_assert(std::is_same<chip::EndpointId, uint16_t>::value,
                      "chip::EndpointId is expected to be uint8_t, change this when necessary");
        static_assert(std::is_same<chip::GroupId, uint16_t>::value,
                      "chip::GroupId is expected to be uint16_t, change this when necessary");
        return ZCL_INT16U_ATTRIBUTE_TYPE;

    case ZCL_CLUSTER_ID_ATTRIBUTE_TYPE: // Cluster Id
    case ZCL_ATTRIB_ID_ATTRIBUTE_TYPE:  // Attribute Id
    case ZCL_FIELD_ID_ATTRIBUTE_TYPE:   // Field Id
    case ZCL_EVENT_ID_ATTRIBUTE_TYPE:   // Event Id
    case ZCL_COMMAND_ID_ATTRIBUTE_TYPE: // Command Id
    case ZCL_TRANS_ID_ATTRIBUTE_TYPE:   // Transaction Id
    case ZCL_DEVTYPE_ID_ATTRIBUTE_TYPE: // Device Type Id
    case ZCL_DATA_VER_ATTRIBUTE_TYPE:   // Data Version
    case ZCL_BITMAP32_ATTRIBUTE_TYPE:   // 32-bit bitmap
    case ZCL_EPOCH_S_ATTRIBUTE_TYPE:    // Epoch Seconds
        static_assert(std::is_same<chip::ClusterId, uint32_t>::value,
                      "chip::Cluster is expected to be uint32_t, change this when necessary");
        static_assert(std::is_same<chip::AttributeId, uint32_t>::value,
                      "chip::AttributeId is expected to be uint32_t, change this when necessary");
        static_assert(std::is_same<chip::AttributeId, uint32_t>::value,
                      "chip::AttributeId is expected to be uint32_t, change this when necessary");
        static_assert(std::is_same<chip::EventId, uint32_t>::value,
                      "chip::EventId is expected to be uint32_t, change this when necessary");
        static_assert(std::is_same<chip::CommandId, uint32_t>::value,
                      "chip::CommandId is expected to be uint32_t, change this when necessary");
        static_assert(std::is_same<chip::TransactionId, uint32_t>::value,
                      "chip::TransactionId is expected to be uint32_t, change this when necessary");
        static_assert(std::is_same<chip::DeviceTypeId, uint32_t>::value,
                      "chip::DeviceTypeId is expected to be uint32_t, change this when necessary");
        static_assert(std::is_same<chip::DataVersion, uint32_t>::value,
                      "chip::DataVersion is expected to be uint32_t, change this when necessary");
        return ZCL_INT32U_ATTRIBUTE_TYPE;

    case ZCL_EVENT_NO_ATTRIBUTE_TYPE:  // Event Number
    case ZCL_FABRIC_ID_ATTRIBUTE_TYPE: // Fabric Id
    case ZCL_NODE_ID_ATTRIBUTE_TYPE:   // Node Id
    case ZCL_BITMAP64_ATTRIBUTE_TYPE:  // 64-bit bitmap
    case ZCL_EPOCH_US_ATTRIBUTE_TYPE:  // Epoch Microseconds
        static_assert(std::is_same<chip::EventNumber, uint64_t>::value,
                      "chip::EventNumber is expected to be uint64_t, change this when necessary");
        static_assert(std::is_same<chip::FabricId, uint64_t>::value,
                      "chip::FabricId is expected to be uint64_t, change this when necessary");
        static_assert(std::is_same<chip::NodeId, uint64_t>::value,
                      "chip::NodeId is expected to be uint64_t, change this when necessary");
        return ZCL_INT64U_ATTRIBUTE_TYPE;

    default:
        return type;
    }
}

} // namespace

void SetupEmberAfObjects(Command * command, const ConcreteCommandPath & commandPath)
{
    Messaging::ExchangeContext * commandExchangeCtx = command->GetExchangeContext();

    imCompatibilityEmberApsFrame.clusterId           = commandPath.mClusterId;
    imCompatibilityEmberApsFrame.destinationEndpoint = commandPath.mEndpointId;
    imCompatibilityEmberApsFrame.sourceEndpoint      = 1; // source endpoint is fixed to 1 for now.
    imCompatibilityEmberApsFrame.sequence =
        (commandExchangeCtx != nullptr ? static_cast<uint8_t>(commandExchangeCtx->GetExchangeId() & 0xFF) : 0);

    imCompatibilityEmberAfCluster.commandId      = commandPath.mCommandId;
    imCompatibilityEmberAfCluster.apsFrame       = &imCompatibilityEmberApsFrame;
    imCompatibilityEmberAfCluster.interPanHeader = &imCompatibilityInterpanHeader;
    imCompatibilityEmberAfCluster.source         = commandExchangeCtx;

    emAfCurrentCommand   = &imCompatibilityEmberAfCluster;
    currentCommandObject = command;
}

bool IMEmberAfSendDefaultResponseWithCallback(EmberAfStatus status)
{
    if (currentCommandObject == nullptr)
    {
        // If this command is not handled by IM, then let ember send response.
        return false;
    }

    chip::app::ConcreteCommandPath commandPath(imCompatibilityEmberApsFrame.destinationEndpoint,
                                               imCompatibilityEmberApsFrame.clusterId, imCompatibilityEmberAfCluster.commandId);

    CHIP_ERROR err = currentCommandObject->AddStatus(commandPath, ToInteractionModelStatus(status));
    return CHIP_NO_ERROR == err;
}

void ResetEmberAfObjects()
{
    emAfCurrentCommand   = nullptr;
    currentCommandObject = nullptr;
}

} // namespace Compatibility

namespace {
// Common buffer for ReadSingleClusterData & WriteSingleClusterData
uint8_t attributeData[kAttributeReadBufferSize];
} // namespace

bool ServerClusterCommandExists(const ConcreteCommandPath & aCommandPath)
{
    // TODO: Currently, we are using cluster catalog from the ember library, this should be modified or replaced after several
    // updates to Commands.
    return emberAfContainsServer(aCommandPath.mEndpointId, aCommandPath.mClusterId);
}

CHIP_ERROR ReadSingleClusterData(FabricIndex aAccessingFabricIndex, const ConcreteAttributePath & aPath, TLV::TLVWriter * apWriter,
                                 bool * apDataExists)
{
    ChipLogDetail(DataManagement,
                  "Reading attribute: Cluster=" ChipLogFormatMEI " Endpoint=%" PRIx16 " AttributeId=" ChipLogFormatMEI,
                  ChipLogValueMEI(aPath.mClusterId), aPath.mEndpointId, ChipLogValueMEI(aPath.mAttributeId));

    AttributeAccessInterface * attrOverride = findAttributeAccessOverride(aPath.mEndpointId, aPath.mClusterId);
    if (attrOverride != nullptr)
    {
        // TODO: We should probably clone the writer and convert failures here
        // into status responses, unless our caller already does that.
        AttributeValueEncoder valueEncoder(apWriter, aAccessingFabricIndex);
        ReturnErrorOnFailure(attrOverride->Read(aPath, valueEncoder));

        if (valueEncoder.TriedEncode())
        {
            if (apDataExists != nullptr)
            {
                *apDataExists = true;
            }
            if (apWriter != nullptr)
            {
                // TODO: Add DataVersion support
                ReturnErrorOnFailure(
                    apWriter->Put(chip::TLV::ContextTag(AttributeDataElement::kCsTag_DataVersion), kTemporaryDataVersion));
            }
            return CHIP_NO_ERROR;
        }
    }

    EmberAfAttributeType attributeType;
    EmberAfStatus status;
    status = emberAfReadAttribute(aPath.mEndpointId, aPath.mClusterId, aPath.mAttributeId, CLUSTER_MASK_SERVER, attributeData,
                                  sizeof(attributeData), &attributeType);

    if (apDataExists != nullptr)
    {
        *apDataExists = (EMBER_ZCL_STATUS_SUCCESS == status);
    }

    VerifyOrReturnError(apWriter != nullptr, CHIP_NO_ERROR);
    if (status != EMBER_ZCL_STATUS_SUCCESS)
    {
        return apWriter->Put(chip::TLV::ContextTag(AttributeDataElement::kCsTag_Status), ToInteractionModelStatus(status));
    }

    // TODO: ZCL_STRUCT_ATTRIBUTE_TYPE is not included in this switch case currently, should add support for structures.
    switch (BaseType(attributeType))
    {
    case ZCL_NO_DATA_ATTRIBUTE_TYPE: // No data
        ReturnErrorOnFailure(apWriter->PutNull(TLV::ContextTag(AttributeDataElement::kCsTag_Data)));
        break;
    case ZCL_BOOLEAN_ATTRIBUTE_TYPE: // Boolean
        ReturnErrorOnFailure(apWriter->PutBoolean(TLV::ContextTag(AttributeDataElement::kCsTag_Data), !!attributeData[0]));
        break;
    case ZCL_INT8U_ATTRIBUTE_TYPE: // Unsigned 8-bit integer
        ReturnErrorOnFailure(apWriter->Put(TLV::ContextTag(AttributeDataElement::kCsTag_Data), attributeData[0]));
        break;
    case ZCL_INT16U_ATTRIBUTE_TYPE: // Unsigned 16-bit integer
    {
        uint16_t uint16_data;
        memcpy(&uint16_data, attributeData, sizeof(uint16_data));
        ReturnErrorOnFailure(apWriter->Put(TLV::ContextTag(AttributeDataElement::kCsTag_Data), uint16_data));
        break;
    }
    case ZCL_INT32U_ATTRIBUTE_TYPE: // Unsigned 32-bit integer
    {
        uint32_t uint32_data;
        memcpy(&uint32_data, attributeData, sizeof(uint32_data));
        ReturnErrorOnFailure(apWriter->Put(TLV::ContextTag(AttributeDataElement::kCsTag_Data), uint32_data));
        break;
    }
    case ZCL_INT64U_ATTRIBUTE_TYPE: // Unsigned 64-bit integer
    {
        uint64_t uint64_data;
        memcpy(&uint64_data, attributeData, sizeof(uint64_data));
        ReturnErrorOnFailure(apWriter->Put(TLV::ContextTag(AttributeDataElement::kCsTag_Data), uint64_data));
        break;
    }
    case ZCL_INT8S_ATTRIBUTE_TYPE: // Signed 8-bit integer
    {
        int8_t int8_data;
        memcpy(&int8_data, attributeData, sizeof(int8_data));
        ReturnErrorOnFailure(apWriter->Put(TLV::ContextTag(AttributeDataElement::kCsTag_Data), int8_data));
        break;
    }
    case ZCL_INT16S_ATTRIBUTE_TYPE: // Signed 16-bit integer
    {
        int16_t int16_data;
        memcpy(&int16_data, attributeData, sizeof(int16_data));
        ReturnErrorOnFailure(apWriter->Put(TLV::ContextTag(AttributeDataElement::kCsTag_Data), int16_data));
        break;
    }
    case ZCL_INT32S_ATTRIBUTE_TYPE: // Signed 32-bit integer
    {
        int32_t int32_data;
        memcpy(&int32_data, attributeData, sizeof(int32_data));
        ReturnErrorOnFailure(apWriter->Put(TLV::ContextTag(AttributeDataElement::kCsTag_Data), int32_data));
        break;
    }
    case ZCL_INT64S_ATTRIBUTE_TYPE: // Signed 64-bit integer
    {
        int64_t int64_data;
        memcpy(&int64_data, attributeData, sizeof(int64_data));
        ReturnErrorOnFailure(apWriter->Put(TLV::ContextTag(AttributeDataElement::kCsTag_Data), int64_data));
        break;
    }
    case ZCL_CHAR_STRING_ATTRIBUTE_TYPE: // Char string
    {
        char * actualData  = reinterpret_cast<char *>(attributeData + 1);
        uint8_t dataLength = attributeData[0];
        if (dataLength == 0xFF /* invalid data, put empty value instead */)
        {
            dataLength = 0;
        }
        ReturnErrorOnFailure(apWriter->PutString(TLV::ContextTag(AttributeDataElement::kCsTag_Data), actualData, dataLength));
        break;
    }
    case ZCL_LONG_CHAR_STRING_ATTRIBUTE_TYPE: {
        char * actualData = reinterpret_cast<char *>(attributeData + 2); // The pascal string contains 2 bytes length
        uint16_t dataLength;
        memcpy(&dataLength, attributeData, sizeof(dataLength));
        if (dataLength == 0xFFFF /* invalid data, put empty value instead */)
        {
            dataLength = 0;
        }
        ReturnErrorOnFailure(apWriter->PutString(TLV::ContextTag(AttributeDataElement::kCsTag_Data), actualData, dataLength));
        break;
    }
    case ZCL_OCTET_STRING_ATTRIBUTE_TYPE: // Octet string
    {
        uint8_t * actualData = attributeData + 1;
        uint8_t dataLength   = attributeData[0];
        if (dataLength == 0xFF /* invalid data, put empty value instead */)
        {
            dataLength = 0;
        }
        ReturnErrorOnFailure(
            apWriter->Put(TLV::ContextTag(AttributeDataElement::kCsTag_Data), chip::ByteSpan(actualData, dataLength)));
        break;
    }
    case ZCL_LONG_OCTET_STRING_ATTRIBUTE_TYPE: {
        uint8_t * actualData = attributeData + 2; // The pascal string contains 2 bytes length
        uint16_t dataLength;
        memcpy(&dataLength, attributeData, sizeof(dataLength));
        if (dataLength == 0xFFFF /* invalid data, put empty value instead */)
        {
            dataLength = 0;
        }
        ReturnErrorOnFailure(
            apWriter->Put(TLV::ContextTag(AttributeDataElement::kCsTag_Data), chip::ByteSpan(actualData, dataLength)));
        break;
    }
    case ZCL_ARRAY_ATTRIBUTE_TYPE: {
        // We only get here for attributes of list type that have no override
        // registered.  There should not be any nonempty lists like that.
        uint16_t size = emberAfAttributeValueSize(aPath.mClusterId, aPath.mAttributeId, attributeType, attributeData);
        if (size != 2)
        {
            // The value returned by emberAfAttributeValueSize for a list
            // includes the space needed to store the list length (2 bytes) plus
            // the space needed to store the actual list items.  We expect it to
            // return 2 here, indicating a zero-length list.  If it doesn't,
            // something has gone wrong.
            return CHIP_ERROR_INCORRECT_STATE;
        }

        // Just encode an empty array.
        TLV::TLVType containerType;
        ReturnErrorOnFailure(
            apWriter->StartContainer(TLV::ContextTag(AttributeDataElement::kCsTag_Data), TLV::kTLVType_Array, containerType));
        ReturnErrorOnFailure(apWriter->EndContainer(containerType));
        break;
    }
    default:
        ChipLogError(DataManagement, "Attribute type 0x%x not handled", static_cast<int>(attributeType));
        return apWriter->Put(chip::TLV::ContextTag(AttributeDataElement::kCsTag_Status),
                             Protocols::InteractionModel::Status::UnsupportedRead);
    }

    // TODO: Add DataVersion support
    ReturnErrorOnFailure(apWriter->Put(chip::TLV::ContextTag(AttributeDataElement::kCsTag_DataVersion), kTemporaryDataVersion));
    return CHIP_NO_ERROR;
}

namespace {
template <typename T>
CHIP_ERROR numericTlvDataToAttributeBuffer(TLV::TLVReader & aReader, uint16_t & dataLen)
{
    T value;
    static_assert(sizeof(value) <= sizeof(attributeData), "Value cannot fit into attribute data");
    ReturnErrorOnFailure(aReader.Get(value));
    dataLen = sizeof(value);
    memcpy(attributeData, &value, sizeof(value));
    return CHIP_NO_ERROR;
}
template <typename T>
CHIP_ERROR stringTlvDataToAttributeBuffer(TLV::TLVReader & aReader, uint16_t & dataLen)
{
    const uint8_t * data = nullptr;
    T len;
    VerifyOrReturnError(aReader.GetType() == TLV::TLVType::kTLVType_ByteString ||
                            aReader.GetType() == TLV::TLVType::kTLVType_UTF8String,
                        CHIP_ERROR_INVALID_ARGUMENT);
    VerifyOrReturnError(CanCastTo<T>(aReader.GetLength()), CHIP_ERROR_MESSAGE_TOO_LONG);
    ReturnErrorOnFailure(aReader.GetDataPtr(data));
    len = static_cast<T>(aReader.GetLength());
    VerifyOrReturnError(len + sizeof(len) /* length at the beginning of data */ <= sizeof(attributeData),
                        CHIP_ERROR_MESSAGE_TOO_LONG);
    memcpy(&attributeData[0], &len, sizeof(len));
    memcpy(&attributeData[sizeof(len)], data, len);
    dataLen = static_cast<uint16_t>(len + sizeof(len));
    return CHIP_NO_ERROR;
}

CHIP_ERROR prepareWriteData(EmberAfAttributeType expectedType, TLV::TLVReader & aReader, uint16_t & dataLen)
{
    switch (BaseType(expectedType))
    {
    case ZCL_BOOLEAN_ATTRIBUTE_TYPE: // Boolean
        return numericTlvDataToAttributeBuffer<bool>(aReader, dataLen);
    case ZCL_INT8U_ATTRIBUTE_TYPE: // Unsigned 8-bit integer
        return numericTlvDataToAttributeBuffer<uint8_t>(aReader, dataLen);
    case ZCL_INT16U_ATTRIBUTE_TYPE: // Unsigned 16-bit integer
        return numericTlvDataToAttributeBuffer<uint16_t>(aReader, dataLen);
    case ZCL_INT32U_ATTRIBUTE_TYPE: // Unsigned 32-bit integer
        return numericTlvDataToAttributeBuffer<uint32_t>(aReader, dataLen);
    case ZCL_INT64U_ATTRIBUTE_TYPE: // Unsigned 64-bit integer
        return numericTlvDataToAttributeBuffer<uint64_t>(aReader, dataLen);
    case ZCL_INT8S_ATTRIBUTE_TYPE: // Signed 8-bit integer
        return numericTlvDataToAttributeBuffer<int8_t>(aReader, dataLen);
    case ZCL_INT16S_ATTRIBUTE_TYPE: // Signed 16-bit integer
        return numericTlvDataToAttributeBuffer<int16_t>(aReader, dataLen);
    case ZCL_INT32S_ATTRIBUTE_TYPE: // Signed 32-bit integer
        return numericTlvDataToAttributeBuffer<int32_t>(aReader, dataLen);
    case ZCL_INT64S_ATTRIBUTE_TYPE: // Signed 64-bit integer
        return numericTlvDataToAttributeBuffer<int64_t>(aReader, dataLen);
    case ZCL_OCTET_STRING_ATTRIBUTE_TYPE: // Octet string
    case ZCL_CHAR_STRING_ATTRIBUTE_TYPE:  // Char string
        return stringTlvDataToAttributeBuffer<uint8_t>(aReader, dataLen);
    case ZCL_LONG_OCTET_STRING_ATTRIBUTE_TYPE: // Long octet string
    case ZCL_LONG_CHAR_STRING_ATTRIBUTE_TYPE:  // Long char string
        return stringTlvDataToAttributeBuffer<uint16_t>(aReader, dataLen);
    default:
        ChipLogError(DataManagement, "Attribute type %x not handled", static_cast<int>(expectedType));
        return CHIP_ERROR_INVALID_DATA_LIST;
    }
}
} // namespace

static Protocols::InteractionModel::Status WriteSingleClusterDataInternal(ClusterInfo & aClusterInfo, TLV::TLVReader & aReader,
                                                                          WriteHandler * apWriteHandler)
{
    // Passing nullptr as buf to emberAfReadAttribute means we only need attribute type here, and ember will not do data read &
    // copy in this case.
    const EmberAfAttributeMetadata * attributeMetadata = emberAfLocateAttributeMetadata(
        aClusterInfo.mEndpointId, aClusterInfo.mClusterId, aClusterInfo.mFieldId, CLUSTER_MASK_SERVER, 0);

    if (attributeMetadata == nullptr)
    {
        return Protocols::InteractionModel::Status::UnsupportedAttribute;
    }

    CHIP_ERROR preparationError = CHIP_NO_ERROR;
    uint16_t dataLen            = 0;
    if ((preparationError = prepareWriteData(attributeMetadata->attributeType, aReader, dataLen)) != CHIP_NO_ERROR)
    {
        ChipLogDetail(Zcl, "Failed to preapre data to write: %s", ErrorStr(preparationError));
        return Protocols::InteractionModel::Status::InvalidValue;
    }

    if (dataLen > attributeMetadata->size)
    {
        ChipLogDetail(Zcl, "Data to write exceedes the attribute size claimed.");
        return Protocols::InteractionModel::Status::InvalidValue;
    }

    return ToInteractionModelStatus(emberAfWriteAttributeExternal(aClusterInfo.mEndpointId, aClusterInfo.mClusterId,
                                                                  aClusterInfo.mFieldId, CLUSTER_MASK_SERVER, 0, attributeData,
                                                                  attributeMetadata->attributeType));
}

CHIP_ERROR WriteSingleClusterData(ClusterInfo & aClusterInfo, TLV::TLVReader & aReader, WriteHandler * apWriteHandler)
{
    AttributePathParams attributePathParams;
    attributePathParams.mNodeId     = aClusterInfo.mNodeId;
    attributePathParams.mEndpointId = aClusterInfo.mEndpointId;
    attributePathParams.mClusterId  = aClusterInfo.mClusterId;
    attributePathParams.mFieldId    = aClusterInfo.mFieldId;
    attributePathParams.mFlags.Set(AttributePathParams::Flags::kFieldIdValid);

    auto imCode = WriteSingleClusterDataInternal(aClusterInfo, aReader, apWriteHandler);
    return apWriteHandler->AddStatus(attributePathParams, imCode);
}
} // namespace app
} // namespace chip

void MatterReportingAttributeChangeCallback(EndpointId endpoint, ClusterId clusterId, AttributeId attributeId, uint8_t mask,
                                            uint16_t manufacturerCode, EmberAfAttributeType type, uint8_t * data)
{
    IgnoreUnusedVariable(manufacturerCode);
    IgnoreUnusedVariable(type);
    IgnoreUnusedVariable(data);
    IgnoreUnusedVariable(mask);

    MatterReportingAttributeChangeCallback(endpoint, clusterId, attributeId);
}

void MatterReportingAttributeChangeCallback(EndpointId endpoint, ClusterId clusterId, AttributeId attributeId)
{
    ClusterInfo info;
    info.mClusterId  = clusterId;
    info.mFieldId    = attributeId;
    info.mEndpointId = endpoint;
    info.mFlags.Set(ClusterInfo::Flags::kFieldIdValid);

    InteractionModelEngine::GetInstance()->GetReportingEngine().SetDirty(info);

    // Schedule work to run asynchronously on the CHIP thread. The scheduled work won't execute until the current execution context
    // has completed. This ensures that we can 'gather up' multiple attribute changes that have occurred in the same execution
    // context without requiring any explicit 'start' or 'end' change calls into the engine to book-end the change.
    InteractionModelEngine::GetInstance()->GetReportingEngine().ScheduleRun();
}
