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

#import "MTRAttributeTLVValueDecoder_Internal.h"
#import "MTRBaseDevice_Internal.h"
#import "MTRBaseSubscriptionCallback.h"
#import "MTRCallbackBridgeBase_internal.h"
#import "MTRCluster.h"
#import "MTRClusterStateCacheContainer_Internal.h"
#import "MTRCluster_internal.h"
#import "MTRError_Internal.h"
#import "MTREventTLVValueDecoder_Internal.h"
#import "MTRLogging_Internal.h"
#import "MTRSetupPayload_Internal.h"

#include "app/ConcreteAttributePath.h"
#include "app/ConcreteCommandPath.h"
#include "lib/core/CHIPError.h"
#include "lib/core/DataModelTypes.h"

#include <app/AttributePathParams.h>
#include <app/BufferedReadCallback.h>
#include <app/ClusterStateCache.h>
#include <app/InteractionModelEngine.h>
#include <app/ReadClient.h>
#include <app/util/error-mapping.h>
#include <controller/CommissioningWindowOpener.h>
#include <controller/ReadInteraction.h>
#include <controller/WriteInteraction.h>
#include <crypto/CHIPCryptoPAL.h>
#include <setup_payload/SetupPayload.h>
#include <system/SystemClock.h>

#include <memory>

using namespace chip;
using namespace chip::app;
using namespace chip::Protocols::InteractionModel;
using chip::Messaging::ExchangeManager;
using chip::Optional;
using chip::SessionHandle;

NSString * const MTRAttributePathKey = @"attributePath";
NSString * const MTRCommandPathKey = @"commandPath";
NSString * const MTREventPathKey = @"eventPath";
NSString * const MTRDataKey = @"data";
NSString * const MTRErrorKey = @"error";
NSString * const MTRTypeKey = @"type";
NSString * const MTRValueKey = @"value";
NSString * const MTRContextTagKey = @"contextTag";
NSString * const MTRSignedIntegerValueType = @"SignedInteger";
NSString * const MTRUnsignedIntegerValueType = @"UnsignedInteger";
NSString * const MTRBooleanValueType = @"Boolean";
NSString * const MTRUTF8StringValueType = @"UTF8String";
NSString * const MTROctetStringValueType = @"OctetString";
NSString * const MTRFloatValueType = @"Float";
NSString * const MTRDoubleValueType = @"Double";
NSString * const MTRNullValueType = @"Null";
NSString * const MTRStructureValueType = @"Structure";
NSString * const MTRArrayValueType = @"Array";

class MTRDataValueDictionaryCallbackBridge;

@interface MTRReadClientContainer : NSObject
@property (nonatomic, readwrite) app::ReadClient * readClientPtr;
@property (nonatomic, readwrite) app::AttributePathParams * pathParams;
@property (nonatomic, readwrite) uint64_t deviceID;
- (void)onDone;
@end

static NSMutableDictionary<NSNumber *, NSMutableArray<MTRReadClientContainer *> *> * readClientContainers;
static NSLock * readClientContainersLock;

static void InitializeReadClientContainers()
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        readClientContainers = [NSMutableDictionary dictionary];
        readClientContainersLock = [[NSLock alloc] init];
    });
}

static void AddReadClientContainer(uint64_t deviceId, MTRReadClientContainer * container)
{
    InitializeReadClientContainers();

    NSNumber * key = [NSNumber numberWithUnsignedLongLong:deviceId];
    [readClientContainersLock lock];
    if (!readClientContainers[key]) {
        readClientContainers[key] = [NSMutableArray array];
    }
    [readClientContainers[key] addObject:container];
    [readClientContainersLock unlock];
}

static void PurgeReadClientContainers(uint64_t deviceId, dispatch_queue_t queue, void (^_Nullable completion)(void))
{
    InitializeReadClientContainers();

    NSMutableArray<MTRReadClientContainer *> * listToDelete;
    NSNumber * key = [NSNumber numberWithUnsignedLongLong:deviceId];
    [readClientContainersLock lock];
    listToDelete = readClientContainers[key];
    [readClientContainers removeObjectForKey:key];
    [readClientContainersLock unlock];

    // Destroy read clients in the work queue
    dispatch_async(DeviceLayer::PlatformMgrImpl().GetWorkQueue(), ^{
        for (MTRReadClientContainer * container in listToDelete) {
            if (container.readClientPtr) {
                Platform::Delete(container.readClientPtr);
                container.readClientPtr = nullptr;
            }
            if (container.pathParams) {
                Platform::Delete(container.pathParams);
                container.pathParams = nullptr;
            }
        }
        [listToDelete removeAllObjects];
        if (completion) {
            dispatch_async(queue, completion);
        }
    });
}

static void PurgeCompletedReadClientContainers(uint64_t deviceId)
{
    InitializeReadClientContainers();

    NSNumber * key = [NSNumber numberWithUnsignedLongLong:deviceId];
    [readClientContainersLock lock];
    NSMutableArray<MTRReadClientContainer *> * array = readClientContainers[key];
    NSUInteger i = 0;
    while (i < [array count]) {
        if (array[i].readClientPtr == nullptr) {
            [array removeObjectAtIndex:i];
            continue;
        }
        i++;
    }
    [readClientContainersLock unlock];
}

#ifdef DEBUG
// This function is for unit testing only. This function closes all read clients.
static void CauseReadClientFailure(uint64_t deviceId, dispatch_queue_t queue, void (^_Nullable completion)(void))
{
    InitializeReadClientContainers();

    NSMutableArray<MTRReadClientContainer *> * listToFail;
    NSNumber * key = [NSNumber numberWithUnsignedLongLong:deviceId];
    [readClientContainersLock lock];
    listToFail = readClientContainers[key];
    [readClientContainers removeObjectForKey:key];
    [readClientContainersLock unlock];

    dispatch_async(DeviceLayer::PlatformMgrImpl().GetWorkQueue(), ^{
        for (MTRReadClientContainer * container in listToFail) {
            // Send auto resubscribe request again by read clients, which must fail.
            chip::app::ReadPrepareParams readParams;
            if (container.readClientPtr) {
                container.readClientPtr->SendAutoResubscribeRequest(std::move(readParams));
            }
        }
        if (completion) {
            dispatch_async(queue, completion);
        }
    });
}
#endif

@implementation MTRReadClientContainer
- (void)onDone
{
    if (_readClientPtr) {
        Platform::Delete(_readClientPtr);
        _readClientPtr = nullptr;
    }
    if (_pathParams) {
        Platform::Delete(_pathParams);
        _pathParams = nullptr;
    }
    PurgeCompletedReadClientContainers(_deviceID);
}

- (void)dealloc
{
    if (_readClientPtr) {
        Platform::Delete(_readClientPtr);
        _readClientPtr = nullptr;
    }
    if (_pathParams) {
        Platform::Delete(_pathParams);
        _pathParams = nullptr;
    }
}
@end

@implementation MTRBaseDevice

- (instancetype)initWithPASEDevice:(chip::DeviceProxy *)device controller:(MTRDeviceController *)controller
{
    if (self = [super init]) {
        _isPASEDevice = YES;
        _nodeID = device->GetDeviceId();
        _deviceController = controller;
    }
    return self;
}

- (instancetype)initWithNodeID:(NSNumber *)nodeID controller:(MTRDeviceController *)controller
{
    if (self = [super init]) {
        _isPASEDevice = NO;
        _nodeID = nodeID.unsignedLongLongValue;
        _deviceController = controller;
    }
    return self;
}

+ (instancetype)deviceWithNodeID:(NSNumber *)nodeID controller:(MTRDeviceController *)controller
{
    // Indirect through the controller to give it a chance to create an
    // MTRBaseDeviceOverXPC instead of just an MTRBaseDevice.
    return [controller baseDeviceForNodeID:nodeID];
}

- (void)invalidateCASESession
{
    if (self.isPASEDevice) {
        return;
    }

    [self.deviceController invalidateCASESessionForNode:self.nodeID];
}

namespace {

class SubscriptionCallback final : public MTRBaseSubscriptionCallback {
public:
    SubscriptionCallback(DataReportCallback attributeReportCallback, DataReportCallback eventReportCallback,
        ErrorCallback errorCallback, MTRDeviceResubscriptionScheduledHandler _Nullable resubscriptionScheduledHandler,
        MTRSubscriptionEstablishedHandler _Nullable subscriptionEstablishedHandler, OnDoneHandler _Nullable onDoneHandler)
        : MTRBaseSubscriptionCallback(attributeReportCallback, eventReportCallback, errorCallback, resubscriptionScheduledHandler,
            subscriptionEstablishedHandler, onDoneHandler)
    {
    }

    void OnEventData(const EventHeader & aEventHeader, TLV::TLVReader * apData, const StatusIB * apStatus) override;

    void OnAttributeData(const ConcreteDataAttributePath & aPath, TLV::TLVReader * apData, const StatusIB & aStatus) override;
};

} // anonymous namespace

- (void)subscribeWithQueue:(dispatch_queue_t)queue
                        params:(MTRSubscribeParams *)params
    clusterStateCacheContainer:(MTRClusterStateCacheContainer * _Nullable)clusterStateCacheContainer
        attributeReportHandler:(MTRDeviceReportHandler _Nullable)attributeReportHandler
            eventReportHandler:(MTRDeviceReportHandler _Nullable)eventReportHandler
                  errorHandler:(void (^)(NSError * error))errorHandler
       subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptionEstablished
       resubscriptionScheduled:(MTRDeviceResubscriptionScheduledHandler _Nullable)resubscriptionScheduled
{
    if (self.isPASEDevice) {
        // We don't support subscriptions over PASE.
        dispatch_async(queue, ^{
            errorHandler([MTRError errorForCHIPErrorCode:CHIP_ERROR_INCORRECT_STATE]);
        });
        return;
    }

    // Copy params before going async.
    params = [params copy];

    [self.deviceController getSessionForNode:self.nodeID
                                  completion:^(ExchangeManager * _Nullable exchangeManager, const Optional<SessionHandle> & session,
                                      NSError * _Nullable error) {
                                      if (error != nil) {
                                          dispatch_async(queue, ^{
                                              errorHandler(error);
                                          });
                                          return;
                                      }

                                      // Wildcard endpoint, cluster, attribute, event.
                                      auto attributePath = std::make_unique<AttributePathParams>();
                                      auto eventPath = std::make_unique<EventPathParams>();
                                      // We want to get event reports at the minInterval, not the maxInterval.
                                      eventPath->mIsUrgentEvent = true;
                                      ReadPrepareParams readParams(session.Value());
                                      [params toReadPrepareParams:readParams];
                                      readParams.mpAttributePathParamsList = attributePath.get();
                                      readParams.mAttributePathParamsListSize = 1;
                                      readParams.mpEventPathParamsList = eventPath.get();
                                      readParams.mEventPathParamsListSize = 1;

                                      std::unique_ptr<ClusterStateCache> clusterStateCache;
                                      ReadClient::Callback * callbackForReadClient = nullptr;
                                      OnDoneHandler onDoneHandler = nil;

                                      if (clusterStateCacheContainer) {
                                          __weak MTRClusterStateCacheContainer * weakPtr = clusterStateCacheContainer;
                                          onDoneHandler = ^{
                                              // This, like all manipulation of cppClusterStateCache, needs to run on the Matter
                                              // queue.
                                              MTRClusterStateCacheContainer * container = weakPtr;
                                              if (container) {
                                                  container.cppClusterStateCache = nullptr;
                                              }
                                          };
                                      }

                                      auto callback = std::make_unique<SubscriptionCallback>(
                                          ^(NSArray * value) {
                                              dispatch_async(queue, ^{
                                                  if (attributeReportHandler != nil) {
                                                      attributeReportHandler(value);
                                                  }
                                              });
                                          },
                                          ^(NSArray * value) {
                                              dispatch_async(queue, ^{
                                                  if (eventReportHandler != nil) {
                                                      eventReportHandler(value);
                                                  }
                                              });
                                          },
                                          ^(NSError * error) {
                                              dispatch_async(queue, ^{
                                                  errorHandler(error);
                                              });
                                          },
                                          ^(NSError * error, NSNumber * resubscriptionDelay) {
                                              dispatch_async(queue, ^{
                                                  if (resubscriptionScheduled != nil) {
                                                      resubscriptionScheduled(error, resubscriptionDelay);
                                                  }
                                              });
                                          },
                                          ^(void) {
                                              dispatch_async(queue, ^{
                                                  if (subscriptionEstablished != nil) {
                                                      subscriptionEstablished();
                                                  }
                                              });
                                          },
                                          onDoneHandler);

                                      if (clusterStateCacheContainer) {
                                          clusterStateCache = std::make_unique<ClusterStateCache>(*callback.get());
                                          callbackForReadClient = &clusterStateCache->GetBufferedCallback();
                                      } else {
                                          callbackForReadClient = &callback->GetBufferedCallback();
                                      }

                                      auto readClient = std::make_unique<ReadClient>(InteractionModelEngine::GetInstance(),
                                          exchangeManager, *callbackForReadClient, ReadClient::InteractionType::Subscribe);

                                      CHIP_ERROR err;
                                      if (!params.resubscribeIfLost) {
                                          err = readClient->SendRequest(readParams);
                                      } else {
                                          // SendAutoResubscribeRequest cleans up the params, even on failure.
                                          attributePath.release();
                                          eventPath.release();
                                          err = readClient->SendAutoResubscribeRequest(std::move(readParams));
                                      }

                                      if (err != CHIP_NO_ERROR) {
                                          dispatch_async(queue, ^{
                                              errorHandler([MTRError errorForCHIPErrorCode:err]);
                                          });

                                          return;
                                      }

                                      if (clusterStateCacheContainer) {
                                          clusterStateCacheContainer.cppClusterStateCache = clusterStateCache.get();
                                          // ClusterStateCache will be deleted when OnDone is called.
                                          callback->AdoptClusterStateCache(std::move(clusterStateCache));
                                      }
                                      // Callback and ReadClient will be deleted when OnDone is called.
                                      callback->AdoptReadClient(std::move(readClient));
                                      callback.release();
                                  }];
}

// Convert TLV data into data-value dictionary as described in MTRDeviceResponseHandler
id _Nullable MTRDecodeDataValueDictionaryFromCHIPTLV(chip::TLV::TLVReader * data)
{
    chip::TLV::TLVType dataTLVType = data->GetType();
    switch (dataTLVType) {
    case chip::TLV::kTLVType_SignedInteger: {
        int64_t val;
        CHIP_ERROR err = data->Get(val);
        if (err != CHIP_NO_ERROR) {
            MTR_LOG_ERROR("Error(%s): TLV signed integer decoding failed", chip::ErrorStr(err));
            return nil;
        }
        return [NSDictionary dictionaryWithObjectsAndKeys:MTRSignedIntegerValueType, MTRTypeKey, [NSNumber numberWithLongLong:val],
                             MTRValueKey, nil];
    }
    case chip::TLV::kTLVType_UnsignedInteger: {
        uint64_t val;
        CHIP_ERROR err = data->Get(val);
        if (err != CHIP_NO_ERROR) {
            MTR_LOG_ERROR("Error(%s): TLV unsigned integer decoding failed", chip::ErrorStr(err));
            return nil;
        }
        return [NSDictionary dictionaryWithObjectsAndKeys:MTRUnsignedIntegerValueType, MTRTypeKey,
                             [NSNumber numberWithUnsignedLongLong:val], MTRValueKey, nil];
    }
    case chip::TLV::kTLVType_Boolean: {
        bool val;
        CHIP_ERROR err = data->Get(val);
        if (err != CHIP_NO_ERROR) {
            MTR_LOG_ERROR("Error(%s): TLV boolean decoding failed", chip::ErrorStr(err));
            return nil;
        }
        return [NSDictionary
            dictionaryWithObjectsAndKeys:MTRBooleanValueType, MTRTypeKey, [NSNumber numberWithBool:val], MTRValueKey, nil];
    }
    case chip::TLV::kTLVType_FloatingPointNumber: {
        // Try float first
        float floatValue;
        CHIP_ERROR err = data->Get(floatValue);
        if (err == CHIP_NO_ERROR) {
            return @ { MTRTypeKey : MTRFloatValueType, MTRValueKey : [NSNumber numberWithFloat:floatValue] };
        }
        double val;
        err = data->Get(val);
        if (err != CHIP_NO_ERROR) {
            MTR_LOG_ERROR("Error(%s): TLV floating point decoding failed", chip::ErrorStr(err));
            return nil;
        }
        return [NSDictionary
            dictionaryWithObjectsAndKeys:MTRDoubleValueType, MTRTypeKey, [NSNumber numberWithDouble:val], MTRValueKey, nil];
    }
    case chip::TLV::kTLVType_UTF8String: {
        uint32_t len = data->GetLength();
        const uint8_t * ptr;
        CHIP_ERROR err = data->GetDataPtr(ptr);
        if (err != CHIP_NO_ERROR) {
            MTR_LOG_ERROR("Error(%s): TLV UTF8String decoding failed", chip::ErrorStr(err));
            return nil;
        }
        return [NSDictionary dictionaryWithObjectsAndKeys:MTRUTF8StringValueType, MTRTypeKey,
                             [[NSString alloc] initWithBytes:ptr length:len encoding:NSUTF8StringEncoding], MTRValueKey, nil];
    }
    case chip::TLV::kTLVType_ByteString: {
        uint32_t len = data->GetLength();
        const uint8_t * ptr;
        CHIP_ERROR err = data->GetDataPtr(ptr);
        if (err != CHIP_NO_ERROR) {
            MTR_LOG_ERROR("Error(%s): TLV ByteString decoding failed", chip::ErrorStr(err));
            return nil;
        }
        return [NSDictionary dictionaryWithObjectsAndKeys:MTROctetStringValueType, MTRTypeKey,
                             [NSData dataWithBytes:ptr length:len], MTRValueKey, nil];
    }
    case chip::TLV::kTLVType_Null: {
        return [NSDictionary dictionaryWithObjectsAndKeys:MTRNullValueType, MTRTypeKey, nil];
    }
    case chip::TLV::kTLVType_Structure:
    case chip::TLV::kTLVType_Array: {
        NSString * typeName;
        switch (dataTLVType) {
        case chip::TLV::kTLVType_Structure:
            typeName = MTRStructureValueType;
            break;
        case chip::TLV::kTLVType_Array:
            typeName = MTRArrayValueType;
            break;
        default:
            typeName = @"Unsupported";
            break;
        }
        chip::TLV::TLVType tlvType;
        CHIP_ERROR err = data->EnterContainer(tlvType);
        if (err != CHIP_NO_ERROR) {
            MTR_LOG_ERROR("Error(%s): TLV container entering failed", chip::ErrorStr(err));
            return nil;
        }
        NSMutableArray * array = [[NSMutableArray alloc] init];
        while ((err = data->Next()) == CHIP_NO_ERROR) {
            chip::TLV::Tag tag = data->GetTag();
            id value = MTRDecodeDataValueDictionaryFromCHIPTLV(data);
            if (value == nullptr) {
                MTR_LOG_ERROR("Error when decoding TLV container");
                return nil;
            }
            NSMutableDictionary * arrayElement = [NSMutableDictionary dictionary];
            [arrayElement setObject:value forKey:MTRDataKey];
            if (dataTLVType == chip::TLV::kTLVType_Structure) {
                [arrayElement setObject:[NSNumber numberWithUnsignedLong:TagNumFromTag(tag)] forKey:MTRContextTagKey];
            }
            [array addObject:arrayElement];
        }
        if (err != CHIP_END_OF_TLV) {
            MTR_LOG_ERROR("Error(%s): TLV container decoding failed", chip::ErrorStr(err));
            return nil;
        }
        err = data->ExitContainer(tlvType);
        if (err != CHIP_NO_ERROR) {
            MTR_LOG_ERROR("Error(%s): TLV container exiting failed", chip::ErrorStr(err));
            return nil;
        }
        return [NSDictionary dictionaryWithObjectsAndKeys:typeName, MTRTypeKey, array, MTRValueKey, nil];
    }
    default:
        MTR_LOG_ERROR("Error: Unsupported TLV type for conversion: %u", (unsigned) data->GetType());
        return nil;
    }
}

static CHIP_ERROR MTREncodeTLVFromDataValueDictionary(id object, chip::TLV::TLVWriter & writer, chip::TLV::Tag tag)
{
    if (![object isKindOfClass:[NSDictionary class]]) {
        MTR_LOG_ERROR("Error: Unsupported object to encode: %@", [object class]);
        return CHIP_ERROR_INVALID_ARGUMENT;
    }
    NSString * typeName = ((NSDictionary *) object)[MTRTypeKey];
    id value = ((NSDictionary *) object)[MTRValueKey];
    if (!typeName) {
        MTR_LOG_ERROR("Error: Object to encode is corrupt");
        return CHIP_ERROR_INVALID_ARGUMENT;
    }
    if ([typeName isEqualToString:MTRSignedIntegerValueType]) {
        if (![value isKindOfClass:[NSNumber class]]) {
            MTR_LOG_ERROR("Error: Object to encode has corrupt signed integer type: %@", [value class]);
            return CHIP_ERROR_INVALID_ARGUMENT;
        }
        return writer.Put(tag, [value longLongValue]);
    }
    if ([typeName isEqualToString:MTRUnsignedIntegerValueType]) {
        if (![value isKindOfClass:[NSNumber class]]) {
            MTR_LOG_ERROR("Error: Object to encode has corrupt unsigned integer type: %@", [value class]);
            return CHIP_ERROR_INVALID_ARGUMENT;
        }
        return writer.Put(tag, [value unsignedLongLongValue]);
    }
    if ([typeName isEqualToString:MTRBooleanValueType]) {
        if (![value isKindOfClass:[NSNumber class]]) {
            MTR_LOG_ERROR("Error: Object to encode has corrupt boolean type: %@", [value class]);
            return CHIP_ERROR_INVALID_ARGUMENT;
        }
        return writer.Put(tag, static_cast<bool>([value boolValue]));
    }
    if ([typeName isEqualToString:MTRFloatValueType]) {
        if (![value isKindOfClass:[NSNumber class]]) {
            MTR_LOG_ERROR("Error: Object to encode has corrupt float type: %@", [value class]);
            return CHIP_ERROR_INVALID_ARGUMENT;
        }
        return writer.Put(tag, [value floatValue]);
    }
    if ([typeName isEqualToString:MTRDoubleValueType]) {
        if (![value isKindOfClass:[NSNumber class]]) {
            MTR_LOG_ERROR("Error: Object to encode has corrupt double type: %@", [value class]);
            return CHIP_ERROR_INVALID_ARGUMENT;
        }
        return writer.Put(tag, [value doubleValue]);
    }
    if ([typeName isEqualToString:MTRNullValueType]) {
        return writer.PutNull(tag);
    }
    if ([typeName isEqualToString:MTRUTF8StringValueType]) {
        if (![value isKindOfClass:[NSString class]]) {
            MTR_LOG_ERROR("Error: Object to encode has corrupt UTF8 string type: %@", [value class]);
            return CHIP_ERROR_INVALID_ARGUMENT;
        }
        return writer.PutString(tag, [value cStringUsingEncoding:NSUTF8StringEncoding]);
    }
    if ([typeName isEqualToString:MTROctetStringValueType]) {
        if (![value isKindOfClass:[NSData class]]) {
            MTR_LOG_ERROR("Error: Object to encode has corrupt octet string type: %@", [value class]);
            return CHIP_ERROR_INVALID_ARGUMENT;
        }
        return writer.Put(tag, chip::ByteSpan(static_cast<const uint8_t *>([value bytes]), [value length]));
    }
    if ([typeName isEqualToString:MTRStructureValueType]) {
        if (![value isKindOfClass:[NSArray class]]) {
            MTR_LOG_ERROR("Error: Object to encode has corrupt structure type: %@", [value class]);
            return CHIP_ERROR_INVALID_ARGUMENT;
        }
        TLV::TLVType outer;
        ReturnErrorOnFailure(writer.StartContainer(tag, chip::TLV::kTLVType_Structure, outer));
        for (id element in value) {
            if (![element isKindOfClass:[NSDictionary class]]) {
                MTR_LOG_ERROR("Error: Structure element to encode has corrupt type: %@", [element class]);
                return CHIP_ERROR_INVALID_ARGUMENT;
            }
            NSNumber * elementTag = element[MTRContextTagKey];
            id elementValue = element[MTRDataKey];
            if (!elementTag || !elementValue) {
                MTR_LOG_ERROR("Error: Structure element to encode has corrupt value: %@", element);
                return CHIP_ERROR_INVALID_ARGUMENT;
            }
            ReturnErrorOnFailure(
                MTREncodeTLVFromDataValueDictionary(elementValue, writer, chip::TLV::ContextTag([elementTag unsignedCharValue])));
        }
        ReturnErrorOnFailure(writer.EndContainer(outer));
        return CHIP_NO_ERROR;
    }
    if ([typeName isEqualToString:MTRArrayValueType]) {
        if (![value isKindOfClass:[NSArray class]]) {
            MTR_LOG_ERROR("Error: Object to encode has corrupt array type: %@", [value class]);
            return CHIP_ERROR_INVALID_ARGUMENT;
        }
        TLV::TLVType outer;
        ReturnErrorOnFailure(writer.StartContainer(tag, chip::TLV::kTLVType_Array, outer));
        for (id element in value) {
            if (![element isKindOfClass:[NSDictionary class]]) {
                MTR_LOG_ERROR("Error: Array element to encode has corrupt type: %@", [element class]);
                return CHIP_ERROR_INVALID_ARGUMENT;
            }
            id elementValue = element[MTRDataKey];
            if (!elementValue) {
                MTR_LOG_ERROR("Error: Array element to encode has corrupt value: %@", element);
                return CHIP_ERROR_INVALID_ARGUMENT;
            }
            ReturnErrorOnFailure(MTREncodeTLVFromDataValueDictionary(elementValue, writer, chip::TLV::AnonymousTag()));
        }
        ReturnErrorOnFailure(writer.EndContainer(outer));
        return CHIP_NO_ERROR;
    }
    MTR_LOG_ERROR("Error: Unsupported type to encode: %@", typeName);
    return CHIP_ERROR_INVALID_ARGUMENT;
}

// Callback type to pass data value as an NSObject
typedef void (*MTRDataValueDictionaryCallback)(void * context, id value);

// Rename to be generic for decode and encode
class MTRDataValueDictionaryDecodableType {
public:
    MTRDataValueDictionaryDecodableType()
        : decodedObj(nil)
    {
    }
    MTRDataValueDictionaryDecodableType(id obj)
        : decodedObj(obj)
    {
    }

    CHIP_ERROR Decode(chip::TLV::TLVReader & data)
    {
        decodedObj = MTRDecodeDataValueDictionaryFromCHIPTLV(&data);
        if (decodedObj == nil) {
            MTR_LOG_ERROR("Error: Failed to get value from TLV data for attribute reading response");
        }
        return (decodedObj) ? CHIP_NO_ERROR : CHIP_ERROR_DECODE_FAILED;
    }

    CHIP_ERROR Encode(chip::TLV::TLVWriter & writer, chip::TLV::Tag tag) const
    {
        return MTREncodeTLVFromDataValueDictionary(decodedObj, writer, tag);
    }

    static constexpr bool kIsFabricScoped = false;

    static bool MustUseTimedInvoke() { return false; }

    id _Nullable GetDecodedObject() const { return decodedObj; }

private:
    id _Nullable decodedObj;
};

// Callback bridge for MTRDataValueDictionaryCallback
class MTRDataValueDictionaryCallbackBridge : public MTRCallbackBridge<MTRDataValueDictionaryCallback> {
public:
    MTRDataValueDictionaryCallbackBridge(dispatch_queue_t queue, MTRDeviceResponseHandler handler, MTRActionBlock action)
        : MTRCallbackBridge<MTRDataValueDictionaryCallback>(queue, handler, action, OnSuccessFn) {};

    static void OnSuccessFn(void * context, id value) { DispatchSuccess(context, value); }
};

template <typename DecodableAttributeType> class BufferedReadAttributeCallback final : public app::ReadClient::Callback {
public:
    using OnSuccessCallbackType
        = std::function<void(const app::ConcreteDataAttributePath & aPath, const DecodableAttributeType & aData)>;
    using OnErrorCallbackType = std::function<void(const app::ConcreteDataAttributePath * aPath, CHIP_ERROR aError)>;
    using OnDoneCallbackType = std::function<void(BufferedReadAttributeCallback * callback)>;
    using OnSubscriptionEstablishedCallbackType = std::function<void()>;

    BufferedReadAttributeCallback(ClusterId aClusterId, AttributeId aAttributeId, OnSuccessCallbackType aOnSuccess,
        OnErrorCallbackType aOnError, OnDoneCallbackType aOnDone,
        OnSubscriptionEstablishedCallbackType aOnSubscriptionEstablished = nullptr)
        : mClusterId(aClusterId)
        , mAttributeId(aAttributeId)
        , mOnSuccess(aOnSuccess)
        , mOnError(aOnError)
        , mOnDone(aOnDone)
        , mOnSubscriptionEstablished(aOnSubscriptionEstablished)
        , mBufferedReadAdapter(*this)
    {
    }

    ~BufferedReadAttributeCallback()
    {
        // Ensure we release the ReadClient before we tear down anything else,
        // so it can call our OnDeallocatePaths properly.
        mReadClient = nullptr;
    }

    app::BufferedReadCallback & GetBufferedCallback() { return mBufferedReadAdapter; }

    void AdoptReadClient(Platform::UniquePtr<app::ReadClient> aReadClient) { mReadClient = std::move(aReadClient); }

private:
    void OnAttributeData(
        const app::ConcreteDataAttributePath & aPath, TLV::TLVReader * apData, const app::StatusIB & aStatus) override
    {
        CHIP_ERROR err = CHIP_NO_ERROR;
        DecodableAttributeType value;

        //
        // We shouldn't be getting list item operations in the provided path since that should be handled by the buffered read
        // callback. If we do, that's a bug.
        //
        VerifyOrDie(!aPath.IsListItemOperation());

        VerifyOrExit(aStatus.IsSuccess(), err = aStatus.ToChipError());
        VerifyOrExit((aPath.mClusterId == mClusterId || mClusterId == kInvalidClusterId)
                && (aPath.mAttributeId == mAttributeId || mAttributeId == kInvalidAttributeId),
            err = CHIP_ERROR_SCHEMA_MISMATCH);
        VerifyOrExit(apData != nullptr, err = CHIP_ERROR_INVALID_ARGUMENT);

        SuccessOrExit(err = app::DataModel::Decode(*apData, value));

        mOnSuccess(aPath, value);

    exit:
        if (err != CHIP_NO_ERROR) {
            mOnError(&aPath, err);
        }
    }

    void OnError(CHIP_ERROR aError) override { mOnError(nullptr, aError); }

    void OnDone(ReadClient *) override { mOnDone(this); }

    void OnSubscriptionEstablished(SubscriptionId aSubscriptionId) override
    {
        if (mOnSubscriptionEstablished) {
            mOnSubscriptionEstablished();
        }
    }

    void OnDeallocatePaths(chip::app::ReadPrepareParams && aReadPrepareParams) override {}

    ClusterId mClusterId;
    AttributeId mAttributeId;
    OnSuccessCallbackType mOnSuccess;
    OnErrorCallbackType mOnError;
    OnDoneCallbackType mOnDone;
    OnSubscriptionEstablishedCallbackType mOnSubscriptionEstablished;
    app::BufferedReadCallback mBufferedReadAdapter;
    Platform::UniquePtr<app::ReadClient> mReadClient;
};

- (void)readAttributesWithEndpointID:(NSNumber * _Nullable)endpointID
                           clusterID:(NSNumber * _Nullable)clusterID
                         attributeID:(NSNumber * _Nullable)attributeID
                              params:(MTRReadParams * _Nullable)params
                               queue:(dispatch_queue_t)queue
                          completion:(MTRDeviceResponseHandler)completion
{
    endpointID = (endpointID == nil) ? nil : [endpointID copy];
    clusterID = (clusterID == nil) ? nil : [clusterID copy];
    attributeID = (attributeID == nil) ? nil : [attributeID copy];
    params = (params == nil) ? nil : [params copy];
    auto * bridge = new MTRDataValueDictionaryCallbackBridge(queue, completion,
        ^(ExchangeManager & exchangeManager, const SessionHandle & session, MTRDataValueDictionaryCallback successCb,
            MTRErrorCallback failureCb, MTRCallbackBridgeBase * bridge) {
            auto resultArray = [[NSMutableArray alloc] init];
            auto resultSuccess = [[NSMutableArray alloc] init];
            auto resultFailure = [[NSMutableArray alloc] init];
            auto onSuccessCb = [resultArray, resultSuccess](const app::ConcreteAttributePath & attribPath,
                                   const MTRDataValueDictionaryDecodableType & aData) {
                [resultArray addObject:@ {
                    MTRAttributePathKey : [[MTRAttributePath alloc] initWithPath:attribPath],
                    MTRDataKey : aData.GetDecodedObject()
                }];
                if ([resultSuccess count] == 0) {
                    [resultSuccess addObject:[NSNumber numberWithBool:YES]];
                }
            };

            auto onFailureCb = [resultArray, resultFailure](const app::ConcreteAttributePath * attribPath, CHIP_ERROR aError) {
                if (attribPath) {
                    [resultArray addObject:@ {
                        MTRAttributePathKey : [[MTRAttributePath alloc] initWithPath:*attribPath],
                        MTRErrorKey : [MTRError errorForCHIPErrorCode:aError]
                    }];
                } else if ([resultFailure count] == 0) {
                    [resultFailure addObject:[MTRError errorForCHIPErrorCode:aError]];
                }
            };

            app::AttributePathParams attributePath;
            if (endpointID) {
                attributePath.mEndpointId = static_cast<chip::EndpointId>([endpointID unsignedShortValue]);
            }
            if (clusterID) {
                attributePath.mClusterId = static_cast<chip::ClusterId>([clusterID unsignedLongValue]);
            }
            if (attributeID) {
                attributePath.mAttributeId = static_cast<chip::AttributeId>([attributeID unsignedLongValue]);
            }
            app::InteractionModelEngine * engine = app::InteractionModelEngine::GetInstance();
            CHIP_ERROR err = CHIP_NO_ERROR;

            chip::app::ReadPrepareParams readParams(session);
            [params toReadPrepareParams:readParams];
            readParams.mpAttributePathParamsList = &attributePath;
            readParams.mAttributePathParamsListSize = 1;

            auto onDone = [resultArray, resultSuccess, resultFailure, bridge, successCb, failureCb](
                              BufferedReadAttributeCallback<MTRDataValueDictionaryDecodableType> * callback) {
                if ([resultFailure count] > 0 || [resultSuccess count] == 0) {
                    // Failure
                    if (failureCb) {
                        if ([resultFailure count] > 0) {
                            failureCb(bridge, [MTRError errorToCHIPErrorCode:resultFailure[0]]);
                        } else if ([resultArray count] > 0) {
                            failureCb(bridge, [MTRError errorToCHIPErrorCode:resultArray[0][MTRErrorKey]]);
                        } else {
                            failureCb(bridge, CHIP_ERROR_READ_FAILED);
                        }
                    }
                } else {
                    // Success
                    if (successCb) {
                        successCb(bridge, resultArray);
                    }
                }
                chip::Platform::Delete(callback);
            };

            auto callback = chip::Platform::MakeUnique<BufferedReadAttributeCallback<MTRDataValueDictionaryDecodableType>>(
                attributePath.mClusterId, attributePath.mAttributeId, onSuccessCb, onFailureCb, onDone, nullptr);
            VerifyOrReturnError(callback != nullptr, CHIP_ERROR_NO_MEMORY);

            auto readClient = chip::Platform::MakeUnique<app::ReadClient>(
                engine, &exchangeManager, callback->GetBufferedCallback(), chip::app::ReadClient::InteractionType::Read);
            VerifyOrReturnError(readClient != nullptr, CHIP_ERROR_NO_MEMORY);

            err = readClient->SendRequest(readParams);

            if (err != CHIP_NO_ERROR) {
                return err;
            }

            //
            // At this point, we'll get a callback through the OnDone callback above regardless of success or failure
            // of the read operation to permit us to free up the callback object. So, release ownership of the callback
            // object now to prevent it from being reclaimed at the end of this scoped block.
            //
            callback->AdoptReadClient(std::move(readClient));
            callback.release();
            return err;
        });
    std::move(*bridge).DispatchAction(self);
}

- (void)writeAttributeWithEndpointID:(NSNumber *)endpointID
                           clusterID:(NSNumber *)clusterID
                         attributeID:(NSNumber *)attributeID
                               value:(id)value
                   timedWriteTimeout:(NSNumber * _Nullable)timeoutMs
                               queue:(dispatch_queue_t)queue
                          completion:(MTRDeviceResponseHandler)completion
{
    auto * bridge = new MTRDataValueDictionaryCallbackBridge(queue, completion,
        ^(ExchangeManager & exchangeManager, const SessionHandle & session, MTRDataValueDictionaryCallback successCb,
            MTRErrorCallback failureCb, MTRCallbackBridgeBase * bridge) {
            auto resultArray = [[NSMutableArray alloc] init];
            auto resultSuccess = [[NSMutableArray alloc] init];
            auto resultFailure = [[NSMutableArray alloc] init];
            auto onSuccessCb = [resultArray, resultSuccess](const app::ConcreteAttributePath & attribPath) {
                [resultArray addObject:@ { MTRAttributePathKey : [[MTRAttributePath alloc] initWithPath:attribPath] }];
                if ([resultSuccess count] == 0) {
                    [resultSuccess addObject:[NSNumber numberWithBool:YES]];
                }
            };

            auto onFailureCb = [resultArray, resultFailure](const app::ConcreteAttributePath * attribPath, CHIP_ERROR aError) {
                if (attribPath) {
                    [resultArray addObject:@ {
                        MTRAttributePathKey : [[MTRAttributePath alloc] initWithPath:*attribPath],
                        MTRErrorKey : [MTRError errorForCHIPErrorCode:aError],
                    }];
                } else {
                    if ([resultFailure count] == 0) {
                        [resultFailure addObject:[MTRError errorForCHIPErrorCode:aError]];
                    }
                }
            };

            auto onDoneCb
                = [bridge, successCb, failureCb, resultArray, resultSuccess, resultFailure](app::WriteClient * pWriteClient) {
                      if ([resultFailure count] > 0 || [resultSuccess count] == 0) {
                          // Failure
                          if (failureCb) {
                              if ([resultFailure count] > 0) {
                                  failureCb(bridge, [MTRError errorToCHIPErrorCode:resultFailure[0]]);
                              } else if ([resultArray count] > 0) {
                                  failureCb(bridge, [MTRError errorToCHIPErrorCode:resultArray[0][MTRErrorKey]]);
                              } else {
                                  failureCb(bridge, CHIP_ERROR_WRITE_FAILED);
                              }
                          }
                      } else {
                          // Success
                          if (successCb) {
                              successCb(bridge, resultArray);
                          }
                      }
                  };

            return chip::Controller::WriteAttribute<MTRDataValueDictionaryDecodableType>(session,
                static_cast<chip::EndpointId>([endpointID unsignedShortValue]),
                static_cast<chip::ClusterId>([clusterID unsignedLongValue]),
                static_cast<chip::AttributeId>([attributeID unsignedLongValue]), MTRDataValueDictionaryDecodableType(value),
                onSuccessCb, onFailureCb, (timeoutMs == nil) ? NullOptional : Optional<uint16_t>([timeoutMs unsignedShortValue]),
                onDoneCb, NullOptional);
        });
    std::move(*bridge).DispatchAction(self);
}

class NSObjectCommandCallback final : public app::CommandSender::Callback {
public:
    using OnSuccessCallbackType
        = std::function<void(const app::ConcreteCommandPath &, const app::StatusIB &, const MTRDataValueDictionaryDecodableType &)>;
    using OnErrorCallbackType = std::function<void(CHIP_ERROR aError)>;
    using OnDoneCallbackType = std::function<void(app::CommandSender * commandSender)>;

    /*
     * Constructor that takes in success, failure and onDone callbacks.
     *
     * The latter can be provided later through the SetOnDoneCallback below in cases where the
     * TypedCommandCallback object needs to be created first before it can be passed in as a closure
     * into a hypothetical OnDoneCallback function.
     */
    NSObjectCommandCallback(chip::ClusterId clusterId, chip::CommandId commandId, OnSuccessCallbackType aOnSuccess,
        OnErrorCallbackType aOnError, OnDoneCallbackType aOnDone = {})
        : mOnSuccess(aOnSuccess)
        , mOnError(aOnError)
        , mOnDone(aOnDone)
        , mClusterId(clusterId)
        , mCommandId(commandId)
    {
    }

    void SetOnDoneCallback(OnDoneCallbackType callback) { mOnDone = callback; }

private:
    void OnResponse(app::CommandSender * apCommandSender, const app::ConcreteCommandPath & aCommandPath,
        const app::StatusIB & aStatus, TLV::TLVReader * aReader) override;

    void OnError(const app::CommandSender * apCommandSender, CHIP_ERROR aError) override { mOnError(aError); }

    void OnDone(app::CommandSender * apCommandSender) override { mOnDone(apCommandSender); }

    OnSuccessCallbackType mOnSuccess;
    OnErrorCallbackType mOnError;
    OnDoneCallbackType mOnDone;
    chip::ClusterId mClusterId;
    // Id of the command we send.
    chip::CommandId mCommandId;
};

void NSObjectCommandCallback::OnResponse(app::CommandSender * apCommandSender, const app::ConcreteCommandPath & aCommandPath,
    const app::StatusIB & aStatus, TLV::TLVReader * aReader)
{
    MTRDataValueDictionaryDecodableType response;
    CHIP_ERROR err = CHIP_NO_ERROR;

    //
    // Validate that the data response we received matches what we expect in terms of its cluster and command IDs.
    //
    VerifyOrExit(aCommandPath.mClusterId == mClusterId, err = CHIP_ERROR_SCHEMA_MISMATCH);

    // If aReader is null, we got a status response and the command id in the
    // path should match our command id.  If aReader is not null, we got a data
    // response, which will have its own command id, which we don't know.
    VerifyOrExit(aCommandPath.mCommandId == mCommandId || aReader != nullptr, err = CHIP_ERROR_SCHEMA_MISMATCH);

    if (aReader != nullptr) {
        err = app::DataModel::Decode(*aReader, response);
        SuccessOrExit(err);
    }

    mOnSuccess(aCommandPath, aStatus, response);

exit:
    if (err != CHIP_NO_ERROR) {
        mOnError(err);
    }
}

- (void)invokeCommandWithEndpointID:(NSNumber *)endpointID
                          clusterID:(NSNumber *)clusterID
                          commandID:(NSNumber *)commandID
                      commandFields:(id)commandFields
                 timedInvokeTimeout:(NSNumber * _Nullable)timeoutMs
                              queue:(dispatch_queue_t)queue
                         completion:(MTRDeviceResponseHandler)completion
{
    endpointID = (endpointID == nil) ? nil : [endpointID copy];
    clusterID = (clusterID == nil) ? nil : [clusterID copy];
    commandID = (commandID == nil) ? nil : [commandID copy];
    // TODO: This is not going to deep-copy the NSArray instances in
    // commandFields.  We need to do something smarter here.
    commandFields = (commandFields == nil) ? nil : [commandFields copy];
    timeoutMs = (timeoutMs == nil) ? nil : [timeoutMs copy];

    auto * bridge = new MTRDataValueDictionaryCallbackBridge(queue, completion,
        ^(ExchangeManager & exchangeManager, const SessionHandle & session, MTRDataValueDictionaryCallback successCb,
            MTRErrorCallback failureCb, MTRCallbackBridgeBase * bridge) {
            auto resultArray = [[NSMutableArray alloc] init];
            auto resultSuccess = [[NSMutableArray alloc] init];
            auto resultFailure = [[NSMutableArray alloc] init];
            auto onSuccessCb = [resultArray, resultSuccess](const app::ConcreteCommandPath & commandPath,
                                   const app::StatusIB & status, const MTRDataValueDictionaryDecodableType & responseData) {
                if (responseData.GetDecodedObject()) {
                    [resultArray addObject:@ {
                        MTRCommandPathKey : [[MTRCommandPath alloc] initWithPath:commandPath],
                        MTRDataKey : responseData.GetDecodedObject()
                    }];
                } else {
                    [resultArray addObject:@ { MTRCommandPathKey : [[MTRCommandPath alloc] initWithPath:commandPath] }];
                }
                if ([resultSuccess count] == 0) {
                    [resultSuccess addObject:[NSNumber numberWithBool:YES]];
                }
            };

            auto onFailureCb = [resultFailure](CHIP_ERROR aError) {
                if ([resultFailure count] == 0) {
                    [resultFailure addObject:[MTRError errorForCHIPErrorCode:aError]];
                }
            };

            app::CommandPathParams commandPath = { static_cast<chip::EndpointId>([endpointID unsignedShortValue]), 0,
                static_cast<chip::ClusterId>([clusterID unsignedLongValue]),
                static_cast<chip::CommandId>([commandID unsignedLongValue]), (app::CommandPathFlags::kEndpointIdValid) };

            auto decoder = chip::Platform::MakeUnique<NSObjectCommandCallback>(
                commandPath.mClusterId, commandPath.mCommandId, onSuccessCb, onFailureCb);
            VerifyOrReturnError(decoder != nullptr, CHIP_ERROR_NO_MEMORY);

            auto rawDecoderPtr = decoder.get();
            auto onDoneCb = [rawDecoderPtr, bridge, successCb, failureCb, resultArray, resultSuccess, resultFailure](
                                app::CommandSender * commandSender) {
                if ([resultFailure count] > 0 || [resultSuccess count] == 0) {
                    // Failure
                    if (failureCb) {
                        if ([resultFailure count] > 0) {
                            failureCb(bridge, [MTRError errorToCHIPErrorCode:resultFailure[0]]);
                        } else {
                            failureCb(bridge, CHIP_ERROR_WRITE_FAILED);
                        }
                    }
                } else {
                    // Success
                    if (successCb) {
                        successCb(bridge, resultArray);
                    }
                }
                chip::Platform::Delete(commandSender);
                chip::Platform::Delete(rawDecoderPtr);
            };

            decoder->SetOnDoneCallback(onDoneCb);

            bool isTimedRequest = (timeoutMs != nil);
            auto commandSender = chip::Platform::MakeUnique<app::CommandSender>(decoder.get(), &exchangeManager, isTimedRequest);
            VerifyOrReturnError(commandSender != nullptr, CHIP_ERROR_NO_MEMORY);

            ReturnErrorOnFailure(commandSender->AddRequestData(commandPath, MTRDataValueDictionaryDecodableType(commandFields),
                (timeoutMs == nil) ? NullOptional : Optional<uint16_t>([timeoutMs unsignedShortValue])));
            ReturnErrorOnFailure(commandSender->SendCommandRequest(session));

            decoder.release();
            commandSender.release();
            return CHIP_NO_ERROR;
        });
    std::move(*bridge).DispatchAction(self);
}

- (void)subscribeToAttributesWithEndpointID:(NSNumber * _Nullable)endpointID
                                  clusterID:(NSNumber * _Nullable)clusterID
                                attributeID:(NSNumber * _Nullable)attributeID
                                     params:(MTRSubscribeParams * _Nullable)params
                                      queue:(dispatch_queue_t)queue
                              reportHandler:(MTRDeviceResponseHandler)reportHandler
                    subscriptionEstablished:(MTRSubscriptionEstablishedHandler)subscriptionEstablished
{
    if (self.isPASEDevice) {
        // We don't support subscriptions over PASE.
        dispatch_async(queue, ^{
            reportHandler(nil, [MTRError errorForCHIPErrorCode:CHIP_ERROR_INCORRECT_STATE]);
        });
        return;
    }

    // Copy params before going async.
    endpointID = (endpointID == nil) ? nil : [endpointID copy];
    clusterID = (clusterID == nil) ? nil : [clusterID copy];
    attributeID = (attributeID == nil) ? nil : [attributeID copy];
    params = (params == nil) ? nil : [params copy];

    [self.deviceController
        getSessionForNode:self.nodeID
               completion:^(ExchangeManager * _Nullable exchangeManager, const Optional<SessionHandle> & session,
                   NSError * _Nullable error) {
                   if (error != nil) {
                       if (reportHandler) {
                           dispatch_async(queue, ^{
                               reportHandler(nil, error);
                           });
                       }
                       return;
                   }

                   auto onReportCb = [queue, reportHandler](const app::ConcreteAttributePath & attribPath,
                                         const MTRDataValueDictionaryDecodableType & data) {
                       id valueObject = data.GetDecodedObject();
                       app::ConcreteAttributePath pathCopy = attribPath;
                       dispatch_async(queue, ^{
                           reportHandler(@[ @ {
                               MTRAttributePathKey : [[MTRAttributePath alloc] initWithPath:pathCopy],
                               MTRDataKey : valueObject
                           } ],
                               nil);
                       });
                   };

                   auto establishedOrFailed = chip::Platform::MakeShared<BOOL>(NO);
                   auto onFailureCb = [establishedOrFailed, queue, subscriptionEstablished, reportHandler](
                                          const app::ConcreteAttributePath * attribPath, CHIP_ERROR error) {
                       if (!(*establishedOrFailed)) {
                           *establishedOrFailed = YES;
                           if (subscriptionEstablished) {
                               dispatch_async(queue, subscriptionEstablished);
                           }
                       }
                       if (reportHandler) {
                           dispatch_async(queue, ^{
                               reportHandler(nil, [MTRError errorForCHIPErrorCode:error]);
                           });
                       }
                   };

                   auto onEstablishedCb = [establishedOrFailed, queue, subscriptionEstablished]() {
                       if (*establishedOrFailed) {
                           return;
                       }
                       *establishedOrFailed = YES;
                       if (subscriptionEstablished) {
                           dispatch_async(queue, subscriptionEstablished);
                       }
                   };

                   MTRReadClientContainer * container = [[MTRReadClientContainer alloc] init];
                   container.deviceID = self.nodeID;
                   container.pathParams = Platform::New<app::AttributePathParams>();
                   if (endpointID) {
                       container.pathParams->mEndpointId = static_cast<chip::EndpointId>([endpointID unsignedShortValue]);
                   }
                   if (clusterID) {
                       container.pathParams->mClusterId = static_cast<chip::ClusterId>([clusterID unsignedLongValue]);
                   }
                   if (attributeID) {
                       container.pathParams->mAttributeId = static_cast<chip::AttributeId>([attributeID unsignedLongValue]);
                   }

                   app::InteractionModelEngine * engine = app::InteractionModelEngine::GetInstance();
                   CHIP_ERROR err = CHIP_NO_ERROR;

                   chip::app::ReadPrepareParams readParams(session.Value());
                   [params toReadPrepareParams:readParams];
                   readParams.mpAttributePathParamsList = container.pathParams;
                   readParams.mAttributePathParamsListSize = 1;

                   auto onDone = [container](BufferedReadAttributeCallback<MTRDataValueDictionaryDecodableType> * callback) {
                       [container onDone];
                       // Make sure we delete callback last, because doing that actually destroys our
                       // lambda, so we can't access captured values after that.
                       chip::Platform::Delete(callback);
                   };

                   auto callback = chip::Platform::MakeUnique<BufferedReadAttributeCallback<MTRDataValueDictionaryDecodableType>>(
                       container.pathParams->mClusterId, container.pathParams->mAttributeId, onReportCb, onFailureCb, onDone,
                       onEstablishedCb);

                   auto readClient = Platform::New<app::ReadClient>(
                       engine, exchangeManager, callback->GetBufferedCallback(), chip::app::ReadClient::InteractionType::Subscribe);

                   if (!params.resubscribeIfLost) {
                       err = readClient->SendRequest(readParams);
                   } else {
                       err = readClient->SendAutoResubscribeRequest(std::move(readParams));
                   }

                   if (err != CHIP_NO_ERROR) {
                       if (reportHandler) {
                           dispatch_async(queue, ^{
                               reportHandler(nil, [MTRError errorForCHIPErrorCode:err]);
                           });
                       }
                       Platform::Delete(readClient);
                       Platform::Delete(container.pathParams);
                       container.pathParams = nullptr;
                       return;
                   }

                   // Read clients will be purged when deregistered.
                   container.readClientPtr = readClient;
                   AddReadClientContainer(container.deviceID, container);
                   callback.release();
               }];
}

- (void)deregisterReportHandlersWithQueue:(dispatch_queue_t)queue completion:(dispatch_block_t)completion
{
    // This method must only be used for MTRDeviceOverXPC. However, for unit testing purpose, the method purges all read clients.
    MTR_LOG_DEBUG("Unexpected call to deregister report handlers");
    PurgeReadClientContainers(self.nodeID, queue, completion);
}

namespace {
class OpenCommissioningWindowHelper {
    typedef void (^ResultCallback)(CHIP_ERROR status, const SetupPayload &);

public:
    static CHIP_ERROR OpenCommissioningWindow(Controller::DeviceController * controller, NodeId nodeID,
        System::Clock::Seconds16 timeout, uint16_t discriminator, uint32_t setupPIN, ResultCallback callback);

private:
    OpenCommissioningWindowHelper(Controller::DeviceController * controller, ResultCallback callback);

    static void OnOpenCommissioningWindowResponse(void * context, NodeId deviceId, CHIP_ERROR status, chip::SetupPayload payload);

    Controller::CommissioningWindowOpener mOpener;
    Callback::Callback<Controller::OnOpenCommissioningWindow> mOnOpenCommissioningWindowCallback;
    ResultCallback mResultCallback;
};

OpenCommissioningWindowHelper::OpenCommissioningWindowHelper(Controller::DeviceController * controller, ResultCallback callback)
    : mOpener(controller)
    , mOnOpenCommissioningWindowCallback(OnOpenCommissioningWindowResponse, this)
    , mResultCallback(callback)
{
}

CHIP_ERROR OpenCommissioningWindowHelper::OpenCommissioningWindow(Controller::DeviceController * controller, NodeId nodeID,
    System::Clock::Seconds16 timeout, uint16_t discriminator, uint32_t setupPIN, ResultCallback callback)
{
    auto * self = new (std::nothrow) OpenCommissioningWindowHelper(controller, callback);
    if (self == nullptr) {
        return CHIP_ERROR_NO_MEMORY;
    }

    SetupPayload unused;
    CHIP_ERROR err = self->mOpener.OpenCommissioningWindow(nodeID, timeout, Crypto::kSpake2p_Min_PBKDF_Iterations, discriminator,
        MakeOptional(setupPIN), NullOptional, &self->mOnOpenCommissioningWindowCallback, unused);
    if (err != CHIP_NO_ERROR) {
        delete self;
    }
    // Else will clean up when the callback is called.
    return err;
}

void OpenCommissioningWindowHelper::OnOpenCommissioningWindowResponse(
    void * context, NodeId deviceId, CHIP_ERROR status, chip::SetupPayload payload)
{
    auto * self = static_cast<OpenCommissioningWindowHelper *>(context);
    self->mResultCallback(status, payload);
    delete self;
}

} // anonymous namespace

- (void)openCommissioningWindowWithSetupPasscode:(NSNumber *)setupPasscode
                                   discriminator:(NSNumber *)discriminator
                                        duration:(NSNumber *)duration
                                           queue:(dispatch_queue_t)queue
                                      completion:(MTRDeviceOpenCommissioningWindowHandler)completion
{
    if (self.isPASEDevice) {
        MTR_LOG_ERROR("Can't open a commissioning window over PASE");
        dispatch_async(queue, ^{
            completion(nil, [MTRError errorForCHIPErrorCode:CHIP_ERROR_INCORRECT_STATE]);
        });
        return;
    }

    unsigned long long durationVal = [duration unsignedLongLongValue];
    if (!CanCastTo<uint16_t>(durationVal)) {
        MTR_LOG_ERROR("Error: Duration %llu is too large.", durationVal);
        dispatch_async(queue, ^{
            completion(nil, [MTRError errorForCHIPErrorCode:CHIP_ERROR_INVALID_INTEGER_VALUE]);
        });
        return;
    }

    unsigned long long discriminatorVal = [discriminator unsignedLongLongValue];

    if (discriminatorVal > 0xFFF) {
        MTR_LOG_ERROR("Error: Discriminator %llu is too large. Max value %d", discriminatorVal, 0xFFF);
        dispatch_async(queue, ^{
            completion(nil, [MTRError errorForCHIPErrorCode:CHIP_ERROR_INVALID_INTEGER_VALUE]);
        });
        return;
    }

    unsigned long long passcodeVal = [setupPasscode unsignedLongLongValue];
    if (!CanCastTo<uint32_t>(passcodeVal) || !SetupPayload::IsValidSetupPIN(static_cast<uint32_t>(passcodeVal))) {
        MTR_LOG_ERROR("Error: Setup passcode %llu is not valid", passcodeVal);
        dispatch_async(queue, ^{
            completion(nil, [MTRError errorForCHIPErrorCode:CHIP_ERROR_INVALID_INTEGER_VALUE]);
        });
        return;
    }

    [self.deviceController
        asyncDispatchToMatterQueue:^(Controller::DeviceCommissioner * commissioner) {
            auto resultCallback = ^(CHIP_ERROR status, const SetupPayload & payload) {
                if (status != CHIP_NO_ERROR) {
                    dispatch_async(queue, ^{
                        completion(nil, [MTRError errorForCHIPErrorCode:status]);
                    });
                    return;
                }
                auto * payloadObj = [[MTRSetupPayload alloc] initWithSetupPayload:payload];
                if (payloadObj == nil) {
                    dispatch_async(queue, ^{
                        completion(nil, [MTRError errorForCHIPErrorCode:CHIP_ERROR_NO_MEMORY]);
                    });
                    return;
                }

                dispatch_async(queue, ^{
                    completion(payloadObj, nil);
                });
            };

            SetupPayload setupPayload;
            auto errorCode = OpenCommissioningWindowHelper::OpenCommissioningWindow(commissioner, self.nodeID,
                chip::System::Clock::Seconds16(static_cast<uint16_t>(durationVal)), static_cast<uint16_t>(discriminatorVal),
                static_cast<uint32_t>(passcodeVal), resultCallback);

            if (errorCode != CHIP_NO_ERROR) {
                dispatch_async(queue, ^{
                    completion(nil, [MTRError errorForCHIPErrorCode:errorCode]);
                });
                return;
            }

            // resultCallback will handle things now.
        }
        errorHandler:^(NSError * error) {
            dispatch_async(queue, ^{
                completion(nil, error);
            });
        }];
}

#ifdef DEBUG
// This method is for unit testing only
- (void)failSubscribers:(dispatch_queue_t)queue completion:(void (^)(void))completion
{
    MTR_LOG_DEBUG("Causing failure in subscribers on purpose");
    CauseReadClientFailure(self.nodeID, queue, completion);
}
#endif

// The following method is for unit testing purpose only
+ (id)CHIPEncodeAndDecodeNSObject:(id)object
{
    MTRDataValueDictionaryDecodableType originalData(object);
    chip::TLV::TLVWriter writer;
    uint8_t buffer[1024];
    writer.Init(buffer, sizeof(buffer));

    CHIP_ERROR error = originalData.Encode(writer, chip::TLV::Tag(1));
    if (error != CHIP_NO_ERROR) {
        MTR_LOG_ERROR("Error: Data encoding failed: %s", error.AsString());
        return nil;
    }

    error = writer.Finalize();
    if (error != CHIP_NO_ERROR) {
        MTR_LOG_ERROR("Error: TLV writer finalizing failed: %s", error.AsString());
        return nil;
    }
    chip::TLV::TLVReader reader;
    reader.Init(buffer, writer.GetLengthWritten());
    error = reader.Next();
    if (error != CHIP_NO_ERROR) {
        MTR_LOG_ERROR("Error: TLV reader failed to fetch next element: %s", error.AsString());
        return nil;
    }
    __auto_type tag = reader.GetTag();
    if (tag != chip::TLV::Tag(1)) {
        MTR_LOG_ERROR("Error: TLV reader did not read the tag correctly: %llu", tag.mVal);
        return nil;
    }
    MTRDataValueDictionaryDecodableType decodedData;
    error = decodedData.Decode(reader);
    if (error != CHIP_NO_ERROR) {
        MTR_LOG_ERROR("Error: Data decoding failed: %s", error.AsString());
        return nil;
    }
    return decodedData.GetDecodedObject();
}

@end

@implementation MTRBaseDevice (Deprecated)

- (void)subscribeWithQueue:(dispatch_queue_t)queue
                minInterval:(uint16_t)minInterval
                maxInterval:(uint16_t)maxInterval
                     params:(MTRSubscribeParams * _Nullable)params
             cacheContainer:(MTRAttributeCacheContainer * _Nullable)attributeCacheContainer
     attributeReportHandler:(MTRDeviceReportHandler _Nullable)attributeReportHandler
         eventReportHandler:(MTRDeviceReportHandler _Nullable)eventReportHandler
               errorHandler:(MTRDeviceErrorHandler)errorHandler
    subscriptionEstablished:(dispatch_block_t _Nullable)subscriptionEstablishedHandler
    resubscriptionScheduled:(MTRDeviceResubscriptionScheduledHandler _Nullable)resubscriptionScheduledHandler
{
    MTRSubscribeParams * _Nullable subscribeParams = [params copy];
    if (subscribeParams == nil) {
        subscribeParams = [[MTRSubscribeParams alloc] initWithMinInterval:@(minInterval) maxInterval:@(maxInterval)];
    } else {
        subscribeParams.minInterval = @(minInterval);
        subscribeParams.maxInterval = @(maxInterval);
    }
    [self subscribeWithQueue:queue
                            params:subscribeParams
        clusterStateCacheContainer:attributeCacheContainer.realContainer
            attributeReportHandler:attributeReportHandler
                eventReportHandler:eventReportHandler
                      errorHandler:errorHandler
           subscriptionEstablished:subscriptionEstablishedHandler
           resubscriptionScheduled:resubscriptionScheduledHandler];
}

- (void)readAttributeWithEndpointId:(NSNumber * _Nullable)endpointId
                          clusterId:(NSNumber * _Nullable)clusterId
                        attributeId:(NSNumber * _Nullable)attributeId
                             params:(MTRReadParams * _Nullable)params
                        clientQueue:(dispatch_queue_t)clientQueue
                         completion:(MTRDeviceResponseHandler)completion
{
    [self readAttributesWithEndpointID:endpointId
                             clusterID:clusterId
                           attributeID:attributeId
                                params:params
                                 queue:clientQueue
                            completion:completion];
}

- (void)writeAttributeWithEndpointId:(NSNumber *)endpointId
                           clusterId:(NSNumber *)clusterId
                         attributeId:(NSNumber *)attributeId
                               value:(id)value
                   timedWriteTimeout:(NSNumber * _Nullable)timeoutMs
                         clientQueue:(dispatch_queue_t)clientQueue
                          completion:(MTRDeviceResponseHandler)completion
{
    [self writeAttributeWithEndpointID:endpointId
                             clusterID:clusterId
                           attributeID:attributeId
                                 value:value
                     timedWriteTimeout:timeoutMs
                                 queue:clientQueue
                            completion:completion];
}

- (void)invokeCommandWithEndpointId:(NSNumber *)endpointId
                          clusterId:(NSNumber *)clusterId
                          commandId:(NSNumber *)commandId
                      commandFields:(id)commandFields
                 timedInvokeTimeout:(NSNumber * _Nullable)timeoutMs
                        clientQueue:(dispatch_queue_t)clientQueue
                         completion:(MTRDeviceResponseHandler)completion
{
    [self invokeCommandWithEndpointID:endpointId
                            clusterID:clusterId
                            commandID:commandId
                        commandFields:commandFields
                   timedInvokeTimeout:timeoutMs
                                queue:clientQueue
                           completion:completion];
}

- (void)subscribeAttributeWithEndpointId:(NSNumber * _Nullable)endpointId
                               clusterId:(NSNumber * _Nullable)clusterId
                             attributeId:(NSNumber * _Nullable)attributeId
                             minInterval:(NSNumber *)minInterval
                             maxInterval:(NSNumber *)maxInterval
                                  params:(MTRSubscribeParams * _Nullable)params
                             clientQueue:(dispatch_queue_t)clientQueue
                           reportHandler:(MTRDeviceResponseHandler)reportHandler
                 subscriptionEstablished:(dispatch_block_t _Nullable)subscriptionEstablishedHandler
{
    MTRSubscribeParams * _Nullable subscribeParams = [params copy];
    if (subscribeParams == nil) {
        subscribeParams = [[MTRSubscribeParams alloc] initWithMinInterval:minInterval maxInterval:maxInterval];
    } else {
        subscribeParams.minInterval = minInterval;
        subscribeParams.maxInterval = maxInterval;
    }
    [self subscribeToAttributesWithEndpointID:endpointId
                                    clusterID:clusterId
                                  attributeID:attributeId
                                       params:subscribeParams
                                        queue:clientQueue
                                reportHandler:reportHandler
                      subscriptionEstablished:subscriptionEstablishedHandler];
}

- (void)deregisterReportHandlersWithClientQueue:(dispatch_queue_t)queue completion:(dispatch_block_t)completion
{
    [self deregisterReportHandlersWithQueue:queue completion:completion];
}

@end

@implementation MTRClusterPath
- (instancetype)initWithPath:(const ConcreteClusterPath &)path
{
    if (self = [super init]) {
        _endpoint = @(path.mEndpointId);
        _cluster = @(path.mClusterId);
    }
    return self;
}

- (NSString *)description
{
    return [NSString stringWithFormat:@"<MTRClusterPath> endpoint %u cluster %u", (uint16_t) _endpoint.unsignedShortValue,
                     (uint32_t) _cluster.unsignedLongValue];
}

+ (instancetype)clusterPathWithEndpointID:(NSNumber *)endpointID clusterID:(NSNumber *)clusterID
{
    ConcreteClusterPath path(static_cast<chip::EndpointId>([endpointID unsignedShortValue]),
        static_cast<chip::ClusterId>([clusterID unsignedLongValue]));

    return [[MTRClusterPath alloc] initWithPath:path];
}

- (BOOL)isEqualToClusterPath:(MTRClusterPath *)clusterPath
{
    return [_endpoint isEqualToNumber:clusterPath.endpoint] && [_cluster isEqualToNumber:clusterPath.cluster];
}

- (BOOL)isEqual:(id)object
{
    if (![object isKindOfClass:[self class]]) {
        return NO;
    }
    return [self isEqualToClusterPath:object];
}

- (NSUInteger)hash
{
    return _endpoint.unsignedShortValue ^ _cluster.unsignedLongValue;
}

- (id)copyWithZone:(NSZone *)zone
{
    return [MTRClusterPath clusterPathWithEndpointID:_endpoint clusterID:_cluster];
}

@end

@implementation MTRAttributePath
- (instancetype)initWithPath:(const ConcreteDataAttributePath &)path
{
    if (self = [super initWithPath:path]) {
        _attribute = @(path.mAttributeId);
    }
    return self;
}

- (NSString *)description
{
    return [NSString stringWithFormat:@"<MTRAttributePath> endpoint %u cluster %u attribute %u",
                     (uint16_t) self.endpoint.unsignedShortValue, (uint32_t) self.cluster.unsignedLongValue,
                     (uint32_t) _attribute.unsignedLongValue];
}

+ (instancetype)attributePathWithEndpointID:(NSNumber *)endpointID
                                  clusterID:(NSNumber *)clusterID
                                attributeID:(NSNumber *)attributeID
{
    ConcreteDataAttributePath path(static_cast<chip::EndpointId>([endpointID unsignedShortValue]),
        static_cast<chip::ClusterId>([clusterID unsignedLongValue]),
        static_cast<chip::AttributeId>([attributeID unsignedLongValue]));

    return [[MTRAttributePath alloc] initWithPath:path];
}

- (BOOL)isEqualToAttributePath:(MTRAttributePath *)attributePath
{
    return [self isEqualToClusterPath:attributePath] && [_attribute isEqualToNumber:attributePath.attribute];
}

- (BOOL)isEqual:(id)object
{
    if (![object isKindOfClass:[self class]]) {
        return NO;
    }
    return [self isEqualToAttributePath:object];
}

- (NSUInteger)hash
{
    return self.endpoint.unsignedShortValue ^ self.cluster.unsignedLongValue ^ _attribute.unsignedLongValue;
}

- (id)copyWithZone:(NSZone *)zone
{
    return [MTRAttributePath attributePathWithEndpointID:self.endpoint clusterID:self.cluster attributeID:_attribute];
}
@end

@implementation MTRAttributePath (Deprecated)
+ (instancetype)attributePathWithEndpointId:(NSNumber *)endpointId
                                  clusterId:(NSNumber *)clusterId
                                attributeId:(NSNumber *)attributeId
{
    return [self attributePathWithEndpointID:endpointId clusterID:clusterId attributeID:attributeId];
}
@end

@implementation MTREventPath
- (instancetype)initWithPath:(const ConcreteEventPath &)path
{
    if (self = [super initWithPath:path]) {
        _event = @(path.mEventId);
    }
    return self;
}

+ (instancetype)eventPathWithEndpointID:(NSNumber *)endpointID clusterID:(NSNumber *)clusterID eventID:(NSNumber *)eventID
{
    ConcreteEventPath path(static_cast<chip::EndpointId>([endpointID unsignedShortValue]),
        static_cast<chip::ClusterId>([clusterID unsignedLongValue]), static_cast<chip::EventId>([eventID unsignedLongValue]));

    return [[MTREventPath alloc] initWithPath:path];
}

- (id)copyWithZone:(NSZone *)zone
{
    return [MTREventPath eventPathWithEndpointID:self.endpoint clusterID:self.cluster eventID:_event];
}
@end

@implementation MTREventPath (Deprecated)
+ (instancetype)eventPathWithEndpointId:(NSNumber *)endpointId clusterId:(NSNumber *)clusterId eventId:(NSNumber *)eventId
{
    return [self eventPathWithEndpointID:endpointId clusterID:clusterId eventID:eventId];
}
@end

@implementation MTRCommandPath
- (instancetype)initWithPath:(const ConcreteCommandPath &)path
{
    if (self = [super initWithPath:path]) {
        _command = @(path.mCommandId);
    }
    return self;
}

+ (instancetype)commandPathWithEndpointID:(NSNumber *)endpointID clusterID:(NSNumber *)clusterID commandID:(NSNumber *)commandID
{
    ConcreteCommandPath path(static_cast<chip::EndpointId>([endpointID unsignedShortValue]),
        static_cast<chip::ClusterId>([clusterID unsignedLongValue]), static_cast<chip::CommandId>([commandID unsignedLongValue]));

    return [[MTRCommandPath alloc] initWithPath:path];
}

- (id)copyWithZone:(NSZone *)zone
{
    return [MTRCommandPath commandPathWithEndpointID:self.endpoint clusterID:self.cluster commandID:_command];
}
@end

@implementation MTRCommandPath (Deprecated)
+ (instancetype)commandPathWithEndpointId:(NSNumber *)endpointId clusterId:(NSNumber *)clusterId commandId:(NSNumber *)commandId
{
    return [self commandPathWithEndpointID:endpointId clusterID:clusterId commandID:commandId];
}
@end

@implementation MTRAttributeReport
- (instancetype)initWithPath:(const ConcreteDataAttributePath &)path value:(id _Nullable)value error:(NSError * _Nullable)error
{
    if (self = [super init]) {
        _path = [[MTRAttributePath alloc] initWithPath:path];
        _value = value;
        _error = error;
    }
    return self;
}
@end

@implementation MTREventReport
- (instancetype)initWithPath:(const ConcreteEventPath &)path
                 eventNumber:(NSNumber *)eventNumber
                    priority:(NSNumber *)priority
                   timestamp:(NSNumber *)timestamp
                       value:(id _Nullable)value
                       error:(NSError * _Nullable)error
{
    if (self = [super init]) {
        _path = [[MTREventPath alloc] initWithPath:path];
        _eventNumber = eventNumber;
        _priority = priority;
        _timestamp = timestamp;
        _value = value;
        _error = error;
    }
    return self;
}
@end

namespace {
void SubscriptionCallback::OnEventData(const EventHeader & aEventHeader, TLV::TLVReader * apData, const StatusIB * apStatus)
{
    id _Nullable value = nil;
    NSError * _Nullable error = nil;
    if (apStatus != nullptr) {
        error = [MTRError errorForIMStatus:*apStatus];
    } else if (apData == nullptr) {
        error = [MTRError errorForCHIPErrorCode:CHIP_ERROR_INVALID_ARGUMENT];
    } else {
        CHIP_ERROR err;
        value = MTRDecodeEventPayload(aEventHeader.mPath, *apData, &err);
        if (err == CHIP_ERROR_IM_MALFORMED_EVENT_PATH_IB) {
            // We don't know this event; just skip it.
            return;
        }

        if (err != CHIP_NO_ERROR) {
            value = nil;
            error = [MTRError errorForCHIPErrorCode:err];
        }
    }

    if (mEventReports == nil) {
        // Never got a OnReportBegin?  Not much to do other than tear things down.
        ReportError(CHIP_ERROR_INCORRECT_STATE);
        return;
    }

    [mEventReports addObject:[[MTREventReport alloc] initWithPath:aEventHeader.mPath
                                                      eventNumber:@(aEventHeader.mEventNumber)
                                                         priority:@((uint8_t) aEventHeader.mPriorityLevel)
                                                        timestamp:@(aEventHeader.mTimestamp.mValue)
                                                            value:value
                                                            error:error]];
}

void SubscriptionCallback::OnAttributeData(
    const ConcreteDataAttributePath & aPath, TLV::TLVReader * apData, const StatusIB & aStatus)
{
    if (aPath.IsListItemOperation()) {
        ReportError(CHIP_ERROR_INCORRECT_STATE);
        return;
    }

    id _Nullable value = nil;
    NSError * _Nullable error = nil;
    if (aStatus.mStatus != Status::Success) {
        error = [MTRError errorForIMStatus:aStatus];
    } else if (apData == nullptr) {
        error = [MTRError errorForCHIPErrorCode:CHIP_ERROR_INVALID_ARGUMENT];
    } else {
        CHIP_ERROR err;
        value = MTRDecodeAttributeValue(aPath, *apData, &err);
        if (err == CHIP_ERROR_IM_MALFORMED_ATTRIBUTE_PATH_IB) {
            // We don't know this attribute; just skip it.
            return;
        }

        if (err != CHIP_NO_ERROR) {
            value = nil;
            error = [MTRError errorForCHIPErrorCode:err];
        }
    }

    if (mAttributeReports == nil) {
        // Never got a OnReportBegin?  Not much to do other than tear things down.
        ReportError(CHIP_ERROR_INCORRECT_STATE);
        return;
    }

    [mAttributeReports addObject:[[MTRAttributeReport alloc] initWithPath:aPath value:value error:error]];
}

} // anonymous namespace
