/**
 *
 *    Copyright (c) 2020-2023 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.h"
#import "MTRCluster.h"
#import "MTRClusterStateCacheContainer_Internal.h"
#import "MTRCluster_Internal.h"
#import "MTRDevice_Internal.h"
#import "MTRError_Internal.h"
#import "MTREventTLVValueDecoder_Internal.h"
#import "MTRFramework.h"
#import "MTRLogging_Internal.h"
#import "MTRSetupPayload_Internal.h"

#include "app/ConcreteAttributePath.h"
#include "app/ConcreteCommandPath.h"
#include "app/ConcreteEventPath.h"
#include "app/StatusResponse.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";
NSString * const MTREventNumberKey = @"eventNumber";
NSString * const MTREventPriorityKey = @"eventPriority";
NSString * const MTREventTimeTypeKey = @"eventTimeType";
NSString * const MTREventSystemUpTimeKey = @"eventSystemUpTime";
NSString * const MTREventTimestampDateKey = @"eventTimestampDate";

class MTRDataValueDictionaryCallbackBridge;

@interface MTRReadClientContainer : NSObject
@property (nonatomic, readwrite) app::ReadClient * readClientPtr;
@property (nonatomic, readwrite) app::AttributePathParams * pathParams;
@property (nonatomic, readwrite) app::EventPathParams * eventPathParams;
@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 ReinstateReadClientList(NSMutableArray<MTRReadClientContainer *> * readClientList, NSNumber * key,
    dispatch_queue_t queue, dispatch_block_t _Nullable completion)
{
    [readClientContainersLock lock];
    auto existingList = readClientContainers[key];
    if (existingList) {
        [existingList addObjectsFromArray:readClientList];
    } else {
        readClientContainers[key] = readClientList;
    }
    [readClientContainersLock unlock];
    if (completion) {
        dispatch_async(queue, completion);
    }
}

static void PurgeReadClientContainers(
    MTRDeviceController * controller, 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
    [controller
        asyncDispatchToMatterQueue:^() {
            for (MTRReadClientContainer * container in listToDelete) {
                if (container.readClientPtr) {
                    Platform::Delete(container.readClientPtr);
                    container.readClientPtr = nullptr;
                }
                if (container.pathParams) {
                    static_assert(std::is_trivially_destructible<AttributePathParams>::value,
                        "AttributePathParams destructors won't get run");
                    Platform::MemoryFree(container.pathParams);
                    container.pathParams = nullptr;
                }
                if (container.eventPathParams) {
                    static_assert(
                        std::is_trivially_destructible<EventPathParams>::value, "EventPathParams destructors won't get run");
                    Platform::MemoryFree(container.eventPathParams);
                    container.eventPathParams = nullptr;
                }
            }
            [listToDelete removeAllObjects];
            if (completion) {
                dispatch_async(queue, completion);
            }
        }
        errorHandler:^(NSError * error) {
            // Can't delete things. Just put them back, and hope we
            // can delete them later.
            ReinstateReadClientList(listToDelete, key, 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(
    MTRDeviceController * controller, 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];

    [controller
        asyncDispatchToMatterQueue:^() {
            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);
            }
        }
        errorHandler:^(NSError * error) {
            // Can't fail things. Just put them back.
            ReinstateReadClientList(listToFail, key, queue, completion);
        }];
}
#endif

static bool CheckMemberOfType(NSDictionary<NSString *, id> * responseValue, NSString * memberName, Class expectedClass,
    NSString * errorMessage, NSError * __autoreleasing * error);
static void LogStringAndReturnError(NSString * errorStr, CHIP_ERROR errorCode, NSError * __autoreleasing * error);
static void LogStringAndReturnError(NSString * errorStr, MTRErrorCode errorCode, NSError * __autoreleasing * error);

@implementation MTRReadClientContainer
- (void)onDone
{
    if (_readClientPtr) {
        Platform::Delete(_readClientPtr);
        _readClientPtr = nullptr;
    }
    if (_pathParams) {
        static_assert(std::is_trivially_destructible<AttributePathParams>::value, "AttributePathParams destructors won't get run");
        Platform::MemoryFree(_pathParams);
        _pathParams = nullptr;
    }
    if (_eventPathParams) {
        static_assert(std::is_trivially_destructible<EventPathParams>::value, "EventPathParams destructors won't get run");
        Platform::MemoryFree(_eventPathParams);
        _eventPathParams = nullptr;
    }
    PurgeCompletedReadClientContainers(_deviceID);
}

- (void)dealloc
{
    if (_readClientPtr) {
        Platform::Delete(_readClientPtr);
        _readClientPtr = nullptr;
    }
    if (_pathParams) {
        static_assert(std::is_trivially_destructible<AttributePathParams>::value, "AttributePathParams destructors won't get run");
        Platform::MemoryFree(_pathParams);
        _pathParams = nullptr;
    }
    if (_eventPathParams) {
        static_assert(std::is_trivially_destructible<EventPathParams>::value, "EventPathParams destructors won't get run");
        Platform::MemoryFree(_eventPathParams);
        _eventPathParams = 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;
}

+ (MTRBaseDevice *)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];
}

- (MTRTransportType)sessionTransportType
{
    return [self.deviceController sessionTransportTypeForDevice:self];
}

- (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>();
                                      eventPath->mIsUrgentEvent = params.reportEventsUrgently;
                                      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;
                                                  container.baseDevice = nil;
                                              }
                                          };
                                      }

                                      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.resubscribeAutomatically) {
                                          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));
                                          clusterStateCacheContainer.baseDevice = self;
                                      }
                                      // 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 DecodableValueType> class BufferedReadClientCallback final : public app::ReadClient::Callback {
public:
    using OnSuccessAttributeCallbackType
        = std::function<void(const ConcreteAttributePath & aPath, const DecodableValueType & aData)>;
    using OnSuccessEventCallbackType = std::function<void(const EventHeader & aEventHeader, const DecodableValueType & aData)>;
    using OnErrorCallbackType = std::function<void(
        const app::ConcreteAttributePath * attributePath, const app::ConcreteEventPath * eventPath, CHIP_ERROR aError)>;
    using OnDoneCallbackType = std::function<void(BufferedReadClientCallback * callback)>;
    using OnSubscriptionEstablishedCallbackType = std::function<void()>;
    using OnDeviceResubscriptionScheduledCallbackType = std::function<void(NSError * error, NSNumber * resubscriptionDelay)>;

    BufferedReadClientCallback(app::AttributePathParams * aAttributePathParamsList, size_t aAttributePathParamsSize,
        app::EventPathParams * aEventPathParamsList, size_t aEventPathParamsSize,
        OnSuccessAttributeCallbackType aOnAttributeSuccess, OnSuccessEventCallbackType aOnEventSuccess,
        OnErrorCallbackType aOnError, OnDoneCallbackType aOnDone,
        OnSubscriptionEstablishedCallbackType aOnSubscriptionEstablished = nullptr,
        OnDeviceResubscriptionScheduledCallbackType aOnDeviceResubscriptionScheduled = nullptr)
        : mAttributePathParamsList(aAttributePathParamsList)
        , mAttributePathParamsSize(aAttributePathParamsSize)
        , mEventPathParamsList(aEventPathParamsList)
        , mEventPathParamsSize(aEventPathParamsSize)
        , mOnAttributeSuccess(aOnAttributeSuccess)
        , mOnEventSuccess(aOnEventSuccess)
        , mOnError(aOnError)
        , mOnDone(aOnDone)
        , mOnSubscriptionEstablished(aOnSubscriptionEstablished)
        , mOnDeviceResubscriptionScheduled(aOnDeviceResubscriptionScheduled)
        , mBufferedReadAdapter(*this)
    {
    }

    ~BufferedReadClientCallback()
    {
        // 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;
        DecodableValueType value;

        VerifyOrExit(mOnAttributeSuccess != nullptr, err = CHIP_ERROR_INVALID_ARGUMENT);

        VerifyOrExit(mAttributePathParamsList != nullptr, err = CHIP_ERROR_INVALID_ARGUMENT);

        //
        // 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(
            std::find_if(mAttributePathParamsList, mAttributePathParamsList + mAttributePathParamsSize,
                [aPath](app::AttributePathParams & pathParam) -> bool { return pathParam.IsAttributePathSupersetOf(aPath); })
                != mAttributePathParamsList + mAttributePathParamsSize,
            err = CHIP_ERROR_SCHEMA_MISMATCH);
        VerifyOrExit(apData != nullptr, err = CHIP_ERROR_INVALID_ARGUMENT);

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

        mOnAttributeSuccess(aPath, value);

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

    void OnEventData(const EventHeader & aEventHeader, TLV::TLVReader * apData, const StatusIB * apStatus) override
    {
        CHIP_ERROR err = CHIP_NO_ERROR;
        DecodableValueType value;

        VerifyOrExit(mOnEventSuccess != nullptr, err = CHIP_ERROR_INVALID_ARGUMENT);

        VerifyOrExit(mEventPathParamsList != nullptr, err = CHIP_ERROR_INVALID_ARGUMENT);

        VerifyOrExit(std::find_if(mEventPathParamsList, mEventPathParamsList + mEventPathParamsSize,
                         [aEventHeader](app::EventPathParams & pathParam) -> bool {
                             return pathParam.IsEventPathSupersetOf(aEventHeader.mPath);
                         })
                != mEventPathParamsList + mEventPathParamsSize,
            err = CHIP_ERROR_SCHEMA_MISMATCH);
        VerifyOrExit(apData != nullptr, err = CHIP_ERROR_INVALID_ARGUMENT);

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

        mOnEventSuccess(aEventHeader, value);

    exit:
        if (err != CHIP_NO_ERROR) {
            mOnError(nullptr, &aEventHeader.mPath, err);
        }
    }

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

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

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

    CHIP_ERROR OnResubscriptionNeeded(ReadClient * apReadClient, CHIP_ERROR aTerminationCause) override
    {
        CHIP_ERROR err = ReadClient::Callback::OnResubscriptionNeeded(apReadClient, aTerminationCause);
        ReturnErrorOnFailure(err);

        if (mOnDeviceResubscriptionScheduled != nullptr) {
            auto callback = mOnDeviceResubscriptionScheduled;
            auto error = [MTRError errorForCHIPErrorCode:aTerminationCause];
            auto delayMs = @(apReadClient->ComputeTimeTillNextSubscription());
            callback(error, delayMs);
        }
        return CHIP_NO_ERROR;
    }

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

    OnSuccessAttributeCallbackType mOnAttributeSuccess;
    OnSuccessEventCallbackType mOnEventSuccess;
    OnErrorCallbackType mOnError;
    OnDoneCallbackType mOnDone;
    OnSubscriptionEstablishedCallbackType mOnSubscriptionEstablished;
    OnDeviceResubscriptionScheduledCallbackType mOnDeviceResubscriptionScheduled;
    app::BufferedReadCallback mBufferedReadAdapter;
    Platform::UniquePtr<app::ReadClient> mReadClient;
    app::AttributePathParams * mAttributePathParamsList;
    app::EventPathParams * mEventPathParamsList;
    size_t mAttributePathParamsSize;
    size_t mEventPathParamsSize;
};

- (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
{
    NSArray<MTRAttributeRequestPath *> * attributePaths = [NSArray
        arrayWithObject:[MTRAttributeRequestPath requestPathWithEndpointID:endpointID clusterID:clusterID attributeID:attributeID]];
    [self readAttributePaths:attributePaths eventPaths:nil params:params queue:queue completion:completion];
}

- (void)readAttributePaths:(NSArray<MTRAttributeRequestPath *> * _Nullable)attributePaths
                eventPaths:(NSArray<MTREventRequestPath *> * _Nullable)eventPaths
                    params:(MTRReadParams * _Nullable)params
                     queue:(dispatch_queue_t)queue
                completion:(MTRDeviceResponseHandler)completion
{
    if ((attributePaths == nil || [attributePaths count] == 0) && (eventPaths == nil || [eventPaths count] == 0)) {
        // No paths, just return an empty array.
        dispatch_async(queue, ^{
            completion(@[], nil);
        });
        return;
    }

    NSArray<MTRAttributeRequestPath *> * attributes = nil;
    if (attributePaths != nil) {
        attributes = [[NSArray alloc] initWithArray:attributePaths copyItems:YES];
    }

    NSArray<MTREventRequestPath *> * events = nil;
    if (eventPaths != nil) {
        events = [[NSArray alloc] initWithArray:eventPaths copyItems:YES];
    }
    params = (params == nil) ? nil : [params copy];
    auto * bridge = new MTRDataValueDictionaryCallbackBridge(queue, completion,
        ^(ExchangeManager & exchangeManager, const SessionHandle & session, MTRDataValueDictionaryCallback successCb,
            MTRErrorCallback failureCb, MTRCallbackBridgeBase * bridge) {
            // interactionStatus tracks whether the whole read interaction has failed.
            //
            // Make sure interactionStatus survives even if this block scope is destroyed.
            auto interactionStatus = std::make_shared<CHIP_ERROR>(CHIP_NO_ERROR);

            auto resultArray = [[NSMutableArray alloc] init];
            auto onAttributeSuccessCb
                = [resultArray](const ConcreteAttributePath & aAttributePath, const MTRDataValueDictionaryDecodableType & aData) {
                      [resultArray addObject:@ {
                          MTRAttributePathKey : [[MTRAttributePath alloc] initWithPath:aAttributePath],
                          MTRDataKey : aData.GetDecodedObject()
                      }];
                  };

            auto onEventSuccessCb
                = [resultArray](const EventHeader & aEventHeader, const MTRDataValueDictionaryDecodableType & aData) {
                      [resultArray addObject:[MTRBaseDevice eventReportForHeader:aEventHeader andData:aData.GetDecodedObject()]];
                  };

            auto onFailureCb = [resultArray, interactionStatus](const app::ConcreteAttributePath * aAttributePath,
                                   const app::ConcreteEventPath * aEventPath, CHIP_ERROR aError) {
                if (aAttributePath != nullptr) {
                    [resultArray addObject:@ {
                        MTRAttributePathKey : [[MTRAttributePath alloc] initWithPath:*aAttributePath],
                        MTRErrorKey : [MTRError errorForCHIPErrorCode:aError]
                    }];
                } else if (aEventPath != nullptr) {
                    [resultArray addObject:@ {
                        MTREventPathKey : [[MTREventPath alloc] initWithPath:*aEventPath],
                        MTRErrorKey : [MTRError errorForCHIPErrorCode:aError]
                    }];
                } else {
                    // This will only happen once per read interaction, and
                    // after that there will be no more calls to onFailureCb or
                    // onSuccessCb.
                    *interactionStatus = aError;
                }
            };

            Platform::ScopedMemoryBuffer<AttributePathParams> attributePathParamsList;
            Platform::ScopedMemoryBuffer<EventPathParams> eventPathParamsList;

            if (attributes != nil) {
                size_t count = 0;
                VerifyOrReturnError(attributePathParamsList.Calloc([attributes count]), CHIP_ERROR_NO_MEMORY);
                for (MTRAttributeRequestPath * attribute in attributes) {
                    [attribute convertToAttributePathParams:attributePathParamsList[count++]];
                }
            }

            if (events != nil) {
                size_t count = 0;
                VerifyOrReturnError(eventPathParamsList.Calloc([events count]), CHIP_ERROR_NO_MEMORY);
                for (MTREventRequestPath * event in events) {
                    [event convertToEventPathParams:eventPathParamsList[count++]];
                }
            }

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

            chip::app::ReadPrepareParams readParams(session);
            [params toReadPrepareParams:readParams];
            readParams.mpAttributePathParamsList = attributePathParamsList.Get();
            readParams.mAttributePathParamsListSize = [attributes count];
            readParams.mpEventPathParamsList = eventPathParamsList.Get();
            readParams.mEventPathParamsListSize = [events count];

            AttributePathParams * attributePathParamsListToFree = attributePathParamsList.Get();
            EventPathParams * eventPathParamsListToFree = eventPathParamsList.Get();

            auto onDone
                = [resultArray, interactionStatus, bridge, successCb, failureCb, attributePathParamsListToFree,
                      eventPathParamsListToFree](BufferedReadClientCallback<MTRDataValueDictionaryDecodableType> * callback) {
                      if (*interactionStatus != CHIP_NO_ERROR) {
                          // Failure
                          failureCb(bridge, *interactionStatus);
                      } else {
                          // Success
                          successCb(bridge, resultArray);
                      }
                      if (attributePathParamsListToFree != nullptr) {
                          Platform::MemoryFree(attributePathParamsListToFree);
                      }
                      if (eventPathParamsListToFree != nullptr) {
                          Platform::MemoryFree(eventPathParamsListToFree);
                      }
                      chip::Platform::Delete(callback);
                  };

            auto callback = chip::Platform::MakeUnique<BufferedReadClientCallback<MTRDataValueDictionaryDecodableType>>(
                attributePathParamsList.Get(), readParams.mAttributePathParamsListSize, eventPathParamsList.Get(),
                readParams.mEventPathParamsListSize, onAttributeSuccessCb, onEventSuccessCb, 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();
            attributePathParamsList.Release();
            eventPathParamsList.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) {
            // Controller::WriteAttribute guarantees that there will be exactly one call to either the success callback or the
            // failure callback, for a non-group session.
            auto onSuccessCb = [successCb, bridge](const app::ConcreteAttributePath & attribPath) {
                auto resultArray = @[ @ { MTRAttributePathKey : [[MTRAttributePath alloc] initWithPath:attribPath] } ];
                successCb(bridge, resultArray);
            };

            auto onFailureCb = [failureCb, bridge](
                                   const app::ConcreteAttributePath * attribPath, CHIP_ERROR aError) { failureCb(bridge, aError); };

            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]));
        });
    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
    {
        if (mCalledCallback) {
            return;
        }
        mCalledCallback = true;

        mOnError(aError);
    }

    void OnDone(app::CommandSender * apCommandSender) override
    {
        if (!mCalledCallback) {
            // This can happen if the server sends a response with an empty
            // InvokeResponses list.  Since we are not sending wildcard command
            // paths, that's not a valid response and we should treat it as an
            // error.  Use the error we would have gotten if we in fact expected
            // a nonempty list.
            OnError(apCommandSender, CHIP_END_OF_TLV);
        }

        mOnDone(apCommandSender);
    }

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

void NSObjectCommandCallback::OnResponse(app::CommandSender * apCommandSender, const app::ConcreteCommandPath & aCommandPath,
    const app::StatusIB & aStatus, TLV::TLVReader * aReader)
{
    if (mCalledCallback) {
        return;
    }
    mCalledCallback = true;

    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) {
            // NSObjectCommandCallback guarantees that there will be exactly one call to either the success callback or the failure
            // callback.
            auto onSuccessCb = [successCb, bridge](const app::ConcreteCommandPath & commandPath, const app::StatusIB & status,
                                   const MTRDataValueDictionaryDecodableType & responseData) {
                auto resultArray = [[NSMutableArray alloc] init];
                if (responseData.GetDecodedObject()) {
                    [resultArray addObject:@ {
                        MTRCommandPathKey : [[MTRCommandPath alloc] initWithPath:commandPath],
                        MTRDataKey : responseData.GetDecodedObject()
                    }];
                } else {
                    [resultArray addObject:@ { MTRCommandPathKey : [[MTRCommandPath alloc] initWithPath:commandPath] }];
                }
                successCb(bridge, resultArray);
            };

            auto onFailureCb = [failureCb, bridge](CHIP_ERROR aError) { failureCb(bridge, 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](app::CommandSender * commandSender) {
                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])));

            // We don't have a way to communicate a non-default invoke timeout
            // here for now.
            // TODO: https://github.com/project-chip/connectedhomeip/issues/24563
            ReturnErrorOnFailure(commandSender->SendCommandRequest(session, NullOptional));

            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
{
    NSArray<MTRAttributeRequestPath *> * attributePaths = [NSArray
        arrayWithObject:[MTRAttributeRequestPath requestPathWithEndpointID:endpointID clusterID:clusterID attributeID:attributeID]];
    [self subscribeToAttributePaths:attributePaths
                         eventPaths:nil
                             params:params
                              queue:queue
                      reportHandler:reportHandler
            subscriptionEstablished:subscriptionEstablished
            resubscriptionScheduled:nil];
}

- (void)subscribeToAttributePaths:(NSArray<MTRAttributeRequestPath *> * _Nullable)attributePaths
                       eventPaths:(NSArray<MTREventRequestPath *> * _Nullable)eventPaths
                           params:(MTRSubscribeParams * _Nullable)params
                            queue:(dispatch_queue_t)queue
                    reportHandler:(MTRDeviceResponseHandler)reportHandler
          subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptionEstablished
          resubscriptionScheduled:(MTRDeviceResubscriptionScheduledHandler _Nullable)resubscriptionScheduled
{
    if ((attributePaths == nil || [attributePaths count] == 0) && (eventPaths == nil || [eventPaths count] == 0)) {
        // Per spec a server would respond InvalidAction to this, so just go
        // ahead and do that.
        dispatch_async(queue, ^{
            reportHandler(nil, [MTRError errorForIMStatus:StatusIB(Status::InvalidAction)]);
        });
        return;
    }

    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.
    NSArray<MTRAttributeRequestPath *> * attributes = nil;
    if (attributePaths != nil) {
        attributes = [[NSArray alloc] initWithArray:attributePaths copyItems:YES];
    }

    NSArray<MTREventRequestPath *> * events = nil;
    if (eventPaths != nil) {
        events = [[NSArray alloc] initWithArray:eventPaths copyItems:YES];
    }

    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) {
                       dispatch_async(queue, ^{
                           reportHandler(nil, error);
                       });
                       return;
                   }

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

                   auto onEventReportCb = [queue, reportHandler](
                                              const EventHeader & eventHeader, const MTRDataValueDictionaryDecodableType & data) {
                       NSDictionary * report = [MTRBaseDevice eventReportForHeader:eventHeader andData:data.GetDecodedObject()];
                       dispatch_async(queue, ^{
                           reportHandler(@[ report ], nil);
                       });
                   };

                   auto onFailureCb = [queue, reportHandler](const app::ConcreteAttributePath * attributePath,
                                          const app::ConcreteEventPath * eventPath, CHIP_ERROR error) {
                       if (attributePath != nullptr) {
                           ConcreteAttributePath pathCopy(*attributePath);
                           dispatch_async(queue, ^{
                               reportHandler(@[ @ {
                                   MTRAttributePathKey : [[MTRAttributePath alloc] initWithPath:pathCopy],
                                   MTRErrorKey : [MTRError errorForCHIPErrorCode:error]
                               } ],
                                   nil);
                           });
                       } else if (eventPath != nullptr) {
                           ConcreteEventPath pathCopy(*eventPath);
                           dispatch_async(queue, ^{
                               reportHandler(@[ @ {
                                   MTRAttributePathKey : [[MTREventPath alloc] initWithPath:pathCopy],
                                   MTRErrorKey : [MTRError errorForCHIPErrorCode:error]
                               } ],
                                   nil);
                           });
                       } else {
                           dispatch_async(queue, ^{
                               reportHandler(nil, [MTRError errorForCHIPErrorCode:error]);
                           });
                       }
                   };

                   auto onEstablishedCb = [queue, subscriptionEstablished]() {
                       if (subscriptionEstablished) {
                           dispatch_async(queue, subscriptionEstablished);
                       }
                   };

                   auto onResubscriptionScheduledCb
                       = [queue, resubscriptionScheduled](NSError * error, NSNumber * resubscriptionDelay) {
                             if (resubscriptionScheduled) {
                                 dispatch_async(queue, ^{
                                     resubscriptionScheduled(error, resubscriptionDelay);
                                 });
                             }
                         };

                   MTRReadClientContainer * container = [[MTRReadClientContainer alloc] init];
                   container.deviceID = self.nodeID;

                   size_t attributePathSize = 0;
                   if (attributes != nil) {
                       container.pathParams = static_cast<AttributePathParams *>(
                           Platform::MemoryCalloc([attributes count], sizeof(AttributePathParams)));
                       if (container.pathParams == nullptr) {
                           dispatch_async(queue, ^{
                               reportHandler(nil, [MTRError errorForCHIPErrorCode:CHIP_ERROR_NO_MEMORY]);
                           });
                           return;
                       }
                       for (MTRAttributeRequestPath * attribute in attributes) {
                           [attribute convertToAttributePathParams:container.pathParams[attributePathSize++]];
                       }
                   }
                   size_t eventPathSize = 0;
                   if (events != nil) {
                       container.eventPathParams
                           = static_cast<EventPathParams *>(Platform::MemoryCalloc([events count], sizeof(EventPathParams)));
                       if (container.eventPathParams == nullptr) {
                           dispatch_async(queue, ^{
                               reportHandler(nil, [MTRError errorForCHIPErrorCode:CHIP_ERROR_NO_MEMORY]);
                           });
                           return;
                       }
                       for (MTREventRequestPath * event in events) {
                           [event convertToEventPathParams:container.eventPathParams[eventPathSize++]];
                       }
                   }

                   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 = attributePathSize;
                   readParams.mpEventPathParamsList = container.eventPathParams;
                   readParams.mEventPathParamsListSize = eventPathSize;

                   auto onDone = [container](BufferedReadClientCallback<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<BufferedReadClientCallback<MTRDataValueDictionaryDecodableType>>(
                       container.pathParams, attributePathSize, container.eventPathParams, eventPathSize, onAttributeReportCb,
                       onEventReportCb, onFailureCb, onDone, onEstablishedCb, onResubscriptionScheduledCb);

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

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

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

                       if (container.eventPathParams != nullptr) {
                           Platform::MemoryFree(container.eventPathParams);
                       }
                       container.pathParams = nullptr;
                       container.eventPathParams = 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.deviceController, 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, const Optional<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, const Optional<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,
        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;
}

#pragma mark - Utility for time conversion
NSTimeInterval MTRTimeIntervalForEventTimestampValue(uint64_t timeValue)
{
    // Note: The event timestamp value as written in the spec is in microseconds, but the released 1.0 SDK implemented it in
    // milliseconds. The following issue was filed to address the inconsistency:
    //    https://github.com/CHIP-Specifications/connectedhomeip-spec/issues/6236
    // For consistency with the released behavior, calculations here will be done in milliseconds.

    // First convert the event timestamp value (in milliseconds) to NSTimeInterval - to minimize potential loss of precision
    // of uint64 => NSTimeInterval (double), convert whole seconds and remainder separately and then combine
    uint64_t eventTimestampValueSeconds = timeValue / chip::kMillisecondsPerSecond;
    uint64_t eventTimestampValueRemainderMilliseconds = timeValue % chip::kMillisecondsPerSecond;
    NSTimeInterval eventTimestampValueRemainder
        = NSTimeInterval(eventTimestampValueRemainderMilliseconds) / chip::kMillisecondsPerSecond;
    NSTimeInterval eventTimestampValue = eventTimestampValueSeconds + eventTimestampValueRemainder;

    return eventTimestampValue;
}

#pragma mark - Utility for event priority conversion
BOOL MTRPriorityLevelIsValid(chip::app::PriorityLevel priorityLevel)
{
    return (priorityLevel >= chip::app::PriorityLevel::Debug) && (priorityLevel <= chip::app::PriorityLevel::Critical);
}

MTREventPriority MTREventPriorityForValidPriorityLevel(chip::app::PriorityLevel priorityLevel)
{
    switch (priorityLevel) {
    case chip::app::PriorityLevel::Debug:
        return MTREventPriorityDebug;
    case chip::app::PriorityLevel::Info:
        return MTREventPriorityInfo;
    default:
        return MTREventPriorityCritical;
    }
}

} // anonymous namespace

- (void)_openCommissioningWindowWithSetupPasscode:(nullable 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;
    }

    Optional<uint32_t> passcode;
    if (setupPasscode != nil) {
        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;
        }
        passcode.Emplace(static_cast<uint32_t>(passcodeVal));
    }

    [self.deviceController
        asyncGetCommissionerOnMatterQueue:^(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),
                passcode, 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);
            });
        }];
}

- (void)openCommissioningWindowWithSetupPasscode:(NSNumber *)setupPasscode
                                   discriminator:(NSNumber *)discriminator
                                        duration:(NSNumber *)duration
                                           queue:(dispatch_queue_t)queue
                                      completion:(MTRDeviceOpenCommissioningWindowHandler)completion
{
    [self _openCommissioningWindowWithSetupPasscode:setupPasscode
                                      discriminator:discriminator
                                           duration:duration
                                              queue:queue
                                         completion:completion];
}

- (void)openCommissioningWindowWithDiscriminator:(NSNumber *)discriminator
                                        duration:(NSNumber *)duration
                                           queue:(dispatch_queue_t)queue
                                      completion:(MTRDeviceOpenCommissioningWindowHandler)completion
{
    [self _openCommissioningWindowWithSetupPasscode:nil
                                      discriminator:discriminator
                                           duration:duration
                                              queue:queue
                                         completion:completion];
}

#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.deviceController, 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::CommonTag(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::CommonTag(1)) {
        MTR_LOG_ERROR("Error: TLV reader did not read the tag correctly: %x.%u", chip::TLV::ProfileIdFromTag(tag),
            chip::TLV::TagNumFromTag(tag));
        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();
}

- (void)readEventsWithEndpointID:(NSNumber * _Nullable)endpointID
                       clusterID:(NSNumber * _Nullable)clusterID
                         eventID:(NSNumber * _Nullable)eventID
                          params:(MTRReadParams * _Nullable)params
                           queue:(dispatch_queue_t)queue
                      completion:(MTRDeviceResponseHandler)completion
{
    NSArray<MTREventRequestPath *> * eventPaths = [NSArray arrayWithObject:[MTREventRequestPath requestPathWithEndpointID:endpointID
                                                                                                                clusterID:clusterID
                                                                                                                  eventID:eventID]];
    [self readAttributePaths:nil eventPaths:eventPaths params:params queue:queue completion:completion];
}

- (void)subscribeToEventsWithEndpointID:(NSNumber * _Nullable)endpointID
                              clusterID:(NSNumber * _Nullable)clusterID
                                eventID:(NSNumber * _Nullable)eventID
                                 params:(MTRSubscribeParams * _Nullable)params
                                  queue:(dispatch_queue_t)queue
                          reportHandler:(MTRDeviceResponseHandler)reportHandler
                subscriptionEstablished:(MTRSubscriptionEstablishedHandler)subscriptionEstablished
{
    NSArray<MTREventRequestPath *> * eventPaths = [NSArray arrayWithObject:[MTREventRequestPath requestPathWithEndpointID:endpointID
                                                                                                                clusterID:clusterID
                                                                                                                  eventID:eventID]];
    [self subscribeToAttributePaths:nil
                         eventPaths:eventPaths
                             params:params
                              queue:queue
                      reportHandler:reportHandler
            subscriptionEstablished:subscriptionEstablished
            resubscriptionScheduled:nil];
}

+ (NSDictionary *)eventReportForHeader:(const chip::app::EventHeader &)header andData:(id _Nullable)data
{
    MTREventPath * eventPath = [[MTREventPath alloc] initWithPath:header.mPath];
    if (data == nil) {
        MTR_LOG_ERROR("%@ could not decode event data", eventPath);
        return @{ MTREventPathKey : eventPath, MTRErrorKey : [MTRError errorForCHIPErrorCode:CHIP_ERROR_INVALID_ARGUMENT] };
    }

    // Construct the right type, and key/value depending on the type
    NSNumber * eventTimeType;
    NSString * timestampKey;
    id timestampValue;
    if (header.mTimestamp.mType == Timestamp::Type::kSystem) {
        eventTimeType = @(MTREventTimeTypeSystemUpTime);
        timestampKey = MTREventSystemUpTimeKey;
        timestampValue = @(MTRTimeIntervalForEventTimestampValue(header.mTimestamp.mValue));
    } else if (header.mTimestamp.mType == Timestamp::Type::kEpoch) {
        eventTimeType = @(MTREventTimeTypeTimestampDate);
        timestampKey = MTREventTimestampDateKey;
        timestampValue = [NSDate dateWithTimeIntervalSince1970:MTRTimeIntervalForEventTimestampValue(header.mTimestamp.mValue)];
    } else {
        MTR_LOG_ERROR("%@ Unsupported event timestamp type %u - ignoring", eventPath, (unsigned int) header.mTimestamp.mType);
        return @{ MTREventPathKey : eventPath, MTRErrorKey : [MTRError errorForCHIPErrorCode:CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE] };
    }

    if (!MTRPriorityLevelIsValid(header.mPriorityLevel)) {
        MTR_LOG_ERROR("%@ Unsupported event priority %u - ignoring", eventPath, (unsigned int) header.mPriorityLevel);
        return @{ MTREventPathKey : eventPath, MTRErrorKey : [MTRError errorForCHIPErrorCode:CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE] };
    }

    return @{
        MTREventPathKey : eventPath,
        MTRDataKey : data,
        MTREventNumberKey : @(header.mEventNumber),
        MTREventPriorityKey : @(MTREventPriorityForValidPriorityLevel(header.mPriorityLevel)),
        MTREventTimeTypeKey : eventTimeType,
        timestampKey : timestampValue
    };
}

+ (System::PacketBufferHandle)_responseDataForCommand:(NSDictionary<NSString *, id> *)responseValue
                                            clusterID:(chip::ClusterId)clusterID
                                            commandID:(chip::CommandId)commandID
                                                error:(NSError * __autoreleasing *)error
{
    if (!CheckMemberOfType(responseValue, MTRCommandPathKey, [MTRCommandPath class],
            @"response-value command path is not an MTRCommandPath.", error)) {
        return System::PacketBufferHandle();
    }

    MTRCommandPath * path = responseValue[MTRCommandPathKey];

    if (![path.cluster isEqualToNumber:@(clusterID)]) {
        LogStringAndReturnError([NSString stringWithFormat:@"Expected cluster id %@ but got %@", path.cluster, @(clusterID)],
            MTRErrorCodeSchemaMismatch, error);
        return System::PacketBufferHandle();
    }

    if (![path.command isEqualToNumber:@(commandID)]) {
        LogStringAndReturnError([NSString stringWithFormat:@"Expected command id %@ but got %@", path.command, @(commandID)],
            MTRErrorCodeSchemaMismatch, error);
        return System::PacketBufferHandle();
    }

    if (!CheckMemberOfType(
            responseValue, MTRDataKey, [NSDictionary class], @"response-value data is not a data-value dictionary.", error)) {
        return System::PacketBufferHandle();
    }

    NSDictionary * data = responseValue[MTRDataKey];

    auto buffer = System::PacketBufferHandle::New(System::PacketBuffer::kMaxSizeWithoutReserve, 0);
    if (buffer.IsNull()) {
        LogStringAndReturnError(@"Unable to allocate encoding buffer", CHIP_ERROR_NO_MEMORY, error);
        return System::PacketBufferHandle();
    }

    System::PacketBufferTLVWriter writer;
    // Commands never need chained buffers, since they cannot be chunked.
    writer.Init(std::move(buffer), /* useChainedBuffers = */ false);

    CHIP_ERROR errorCode = MTREncodeTLVFromDataValueDictionary(data, writer, TLV::AnonymousTag());
    if (errorCode != CHIP_NO_ERROR) {
        LogStringAndReturnError(@"Unable to encode data-value to TLV", errorCode, error);
        return System::PacketBufferHandle();
    }

    errorCode = writer.Finalize(&buffer);
    if (errorCode != CHIP_NO_ERROR) {
        LogStringAndReturnError(@"Unable to encode data-value to TLV", errorCode, error);
        return System::PacketBufferHandle();
    }

    return buffer;
}
@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 MTRAttributeRequestPath
- (instancetype)initWithEndpointID:(NSNumber * _Nullable)endpointID
                         clusterID:(NSNumber * _Nullable)clusterID
                       attributeID:(NSNumber * _Nullable)attributeID
{
    _endpoint = [endpointID copy];
    _cluster = [clusterID copy];
    _attribute = [attributeID copy];
    return self;
}

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

+ (MTRAttributeRequestPath *)requestPathWithEndpointID:(NSNumber * _Nullable)endpointID
                                             clusterID:(NSNumber * _Nullable)clusterID
                                           attributeID:(NSNumber * _Nullable)attributeID
{

    return [[MTRAttributeRequestPath alloc] initWithEndpointID:endpointID clusterID:clusterID attributeID:attributeID];
}

- (BOOL)isEqualToAttributeRequestPath:(MTRAttributeRequestPath *)path
{
    return [_endpoint isEqualToNumber:path.endpoint] && [_cluster isEqualToNumber:path.cluster] &&
        [_attribute isEqualToNumber:path.attribute];
}

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

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

- (id)copyWithZone:(NSZone *)zone
{
    return [MTRAttributeRequestPath requestPathWithEndpointID:_endpoint clusterID:_cluster attributeID:_attribute];
}

- (void)convertToAttributePathParams:(chip::app::AttributePathParams &)params
{
    if (_endpoint != nil) {
        params.mEndpointId = static_cast<chip::EndpointId>(_endpoint.unsignedShortValue);
    } else {
        params.SetWildcardEndpointId();
    }

    if (_cluster != nil) {
        params.mClusterId = static_cast<chip::ClusterId>(_cluster.unsignedLongValue);
    } else {
        params.SetWildcardClusterId();
    }

    if (_attribute != nil) {
        params.mAttributeId = static_cast<chip::AttributeId>(_attribute.unsignedLongValue);
    } else {
        params.SetWildcardAttributeId();
    }
}
@end

@implementation MTREventRequestPath
- (instancetype)initWithEndpointID:(NSNumber * _Nullable)endpointID
                         clusterID:(NSNumber * _Nullable)clusterID
                           eventID:(NSNumber * _Nullable)eventID
{
    _endpoint = [endpointID copy];
    _cluster = [clusterID copy];
    _event = [eventID copy];
    return self;
}

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

+ (MTREventRequestPath *)requestPathWithEndpointID:(NSNumber * _Nullable)endpointID
                                         clusterID:(NSNumber * _Nullable)clusterID
                                           eventID:(NSNumber * _Nullable)eventID
{

    return [[MTREventRequestPath alloc] initWithEndpointID:endpointID clusterID:clusterID eventID:eventID];
}

- (BOOL)isEqualToEventRequestPath:(MTREventRequestPath *)path
{
    return
        [_endpoint isEqualToNumber:path.endpoint] && [_cluster isEqualToNumber:path.cluster] && [_event isEqualToNumber:path.event];
}

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

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

- (id)copyWithZone:(NSZone *)zone
{
    return [MTREventRequestPath requestPathWithEndpointID:_endpoint clusterID:_cluster eventID:_event];
}

- (void)convertToEventPathParams:(chip::app::EventPathParams &)params
{
    if (_endpoint != nil) {
        params.mEndpointId = static_cast<chip::EndpointId>(_endpoint.unsignedShortValue);
    } else {
        params.SetWildcardEndpointId();
    }

    if (_cluster != nil) {
        params.mClusterId = static_cast<chip::ClusterId>(_cluster.unsignedLongValue);
    } else {
        params.SetWildcardClusterId();
    }

    if (_event != nil) {
        params.mEventId = static_cast<chip::EventId>(_event.unsignedLongValue);
    } else {
        params.SetWildcardEventId();
    }
}
@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];
}

+ (MTRClusterPath *)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];
}

+ (MTRAttributePath *)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];
}

- (ConcreteAttributePath)_asConcretePath
{
    return ConcreteAttributePath([self.endpoint unsignedShortValue], static_cast<ClusterId>([self.cluster unsignedLongValue]),
        static_cast<AttributeId>([self.attribute unsignedLongValue]));
}
@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;
}

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

+ (MTREventPath *)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];
}

- (ConcreteEventPath)_asConcretePath
{
    return ConcreteEventPath([self.endpoint unsignedShortValue], static_cast<ClusterId>([self.cluster unsignedLongValue]),
        static_cast<EventId>([self.event unsignedLongValue]));
}
@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;
}

+ (MTRCommandPath *)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

static void LogStringAndReturnError(NSString * errorStr, MTRErrorCode errorCode, NSError * __autoreleasing * error)
{
    MTR_LOG_ERROR("%s", errorStr.UTF8String);
    if (!error) {
        return;
    }

    NSDictionary * userInfo = @ { NSLocalizedFailureReasonErrorKey : NSLocalizedString(errorStr, nil) };
    *error = [NSError errorWithDomain:MTRErrorDomain code:errorCode userInfo:userInfo];
}

static void LogStringAndReturnError(NSString * errorStr, CHIP_ERROR errorCode, NSError * __autoreleasing * error)
{
    MTR_LOG_ERROR("%s: %s", errorStr.UTF8String, errorCode.AsString());
    if (!error) {
        return;
    }

    *error = [MTRError errorForCHIPErrorCode:errorCode];
}

static bool CheckMemberOfType(NSDictionary<NSString *, id> * responseValue, NSString * memberName, Class expectedClass,
    NSString * errorMessage, NSError * __autoreleasing * error)
{
    id _Nullable value = responseValue[memberName];
    if (value == nil) {
        LogStringAndReturnError([NSString stringWithFormat:@"%s is null when not expected to be", memberName.UTF8String],
            MTRErrorCodeInvalidArgument, error);
        return false;
    }

    if (![value isKindOfClass:expectedClass]) {
        LogStringAndReturnError(errorMessage, MTRErrorCodeInvalidArgument, error);
        return false;
    }

    return true;
}

// Allocates a buffer, encodes the data-value as TLV, and points the TLV::Reader
// to the data.  Returns false if any of that fails, in which case error gets
// set.
//
// Data model decoding requires a contiguous buffer (because lists walk all the
// data multiple times and TLVPacketBufferBackingStore doesn't have a way to
// checkpoint and restore its state), but we can encode into chained packet
// buffers and then decide whether we need a contiguous realloc.
static bool EncodeDataValueToTLV(System::PacketBufferHandle & buffer, Platform::ScopedMemoryBuffer<uint8_t> & flatBuffer,
    NSDictionary * data, TLV::TLVReader & reader, NSError * __autoreleasing * error)
{
    buffer = System::PacketBufferHandle::New(System::PacketBuffer::kMaxSizeWithoutReserve, 0);
    if (buffer.IsNull()) {
        LogStringAndReturnError(@"Unable to allocate encoding buffer", CHIP_ERROR_NO_MEMORY, error);
        return false;
    }

    System::PacketBufferTLVWriter writer;
    writer.Init(std::move(buffer), /* useChainedBuffers = */ true);

    CHIP_ERROR errorCode = MTREncodeTLVFromDataValueDictionary(data, writer, TLV::AnonymousTag());
    if (errorCode != CHIP_NO_ERROR) {
        LogStringAndReturnError(@"Unable to encode data-value to TLV", errorCode, error);
        return false;
    }

    errorCode = writer.Finalize(&buffer);
    if (errorCode != CHIP_NO_ERROR) {
        LogStringAndReturnError(@"Unable to encode data-value to TLV", errorCode, error);
        return false;
    }

    if (buffer->HasChainedBuffer()) {
        // We need to reallocate into a single contiguous buffer.
        size_t remainingData = buffer->TotalLength();
        if (!flatBuffer.Calloc(remainingData)) {
            LogStringAndReturnError(@"Unable to allocate decoding buffer", CHIP_ERROR_NO_MEMORY, error);
            return false;
        }
        size_t copiedData = 0;
        while (!buffer.IsNull()) {
            if (buffer->DataLength() > remainingData) {
                // Should never happen, but let's be extra careful about buffer
                // overruns.
                LogStringAndReturnError(@"Encoding buffer size is bigger than it claimed", CHIP_ERROR_INCORRECT_STATE, error);
                return false;
            }

            memcpy(flatBuffer.Get() + copiedData, buffer->Start(), buffer->DataLength());
            copiedData += buffer->DataLength();
            remainingData -= buffer->DataLength();
            buffer.Advance();
        }
        if (remainingData != 0) {
            LogStringAndReturnError(
                @"Did not copy all data from Encoding buffer for some reason", CHIP_ERROR_INCORRECT_STATE, error);
            return false;
        }
        reader.Init(flatBuffer.Get(), copiedData);
    } else {
        reader.Init(buffer->Start(), buffer->DataLength());
    }

    errorCode = reader.Next(TLV::AnonymousTag());
    if (errorCode != CHIP_NO_ERROR) {
        LogStringAndReturnError(@"data-value TLV encoding did not create a TLV element", errorCode, error);
        return false;
    }

    return true;
}

@implementation MTRAttributeReport
+ (void)initialize
{
    // One of our init methods ends up doing Platform::MemoryAlloc.
    MTRFrameworkInit();
}

- (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;
}

- (nullable instancetype)initWithResponseValue:(NSDictionary<NSString *, id> *)responseValue
                                         error:(NSError * __autoreleasing *)error
{
    if (!(self = [super init])) {
        return nil;
    }

    // In theory, the types of all the things in the dictionary will be correct
    // if our consumer passes in an actual response-value dictionary, but
    // double-check just to be sure
    if (!CheckMemberOfType(responseValue, MTRAttributePathKey, [MTRAttributePath class],
            @"response-value attribute path is not an MTRAttributePath.", error)) {
        return nil;
    }
    MTRAttributePath * path = responseValue[MTRAttributePathKey];

    id _Nullable value = responseValue[MTRErrorKey];
    if (value != nil) {
        if (!CheckMemberOfType(responseValue, MTRErrorKey, [NSError class], @"response-value error is not an NSError.", error)) {
            return nil;
        }

        _path = path;
        _value = nil;
        _error = value;
        return self;
    }

    if (!CheckMemberOfType(
            responseValue, MTRDataKey, [NSDictionary class], @"response-value data is not a data-value dictionary.", error)) {
        return nil;
    }
    NSDictionary * data = responseValue[MTRDataKey];

    // Encode the data to TLV and then decode from that, to reuse existing code.
    System::PacketBufferHandle buffer;
    Platform::ScopedMemoryBuffer<uint8_t> flatBuffer;
    TLV::TLVReader reader;
    if (!EncodeDataValueToTLV(buffer, flatBuffer, data, reader, error)) {
        return nil;
    }

    auto attributePath = [path _asConcretePath];

    CHIP_ERROR errorCode = CHIP_ERROR_INTERNAL;
    id decodedValue = MTRDecodeAttributeValue(attributePath, reader, &errorCode);
    if (errorCode == CHIP_NO_ERROR) {
        _path = path;
        _value = decodedValue;
        _error = nil;
        return self;
    }

    if (errorCode == CHIP_ERROR_IM_MALFORMED_ATTRIBUTE_PATH_IB) {
        LogStringAndReturnError(@"No known schema for decoding attribute value.", MTRErrorCodeUnknownSchema, error);
        return nil;
    }

    // Treat all other errors as schema errors.
    LogStringAndReturnError(@"Attribute decoding failed schema check.", MTRErrorCodeSchemaMismatch, error);
    return nil;
}

- (id)copyWithZone:(NSZone *)zone
{
    return [[MTRAttributeReport alloc] initWithPath:[self.path _asConcretePath] value:self.value error:self.error];
}

@end

@interface MTREventReport () {
    NSNumber * _timestampValue;
}
@end

@implementation MTREventReport
+ (void)initialize
{
    // One of our init methods ends up doing Platform::MemoryAlloc.
    MTRFrameworkInit();
}

- (instancetype)initWithPath:(const chip::app::ConcreteEventPath &)path
                 eventNumber:(NSNumber *)eventNumber
                    priority:(PriorityLevel)priority
                   timestamp:(const Timestamp &)timestamp
                       value:(id)value
{
    if (self = [super init]) {
        _path = [[MTREventPath alloc] initWithPath:path];
        _eventNumber = eventNumber;
        if (!MTRPriorityLevelIsValid(priority)) {
            return nil;
        }
        _priority = @(MTREventPriorityForValidPriorityLevel(priority));
        _timestampValue = @(timestamp.mValue);
        if (timestamp.IsSystem()) {
            _eventTimeType = MTREventTimeTypeSystemUpTime;
            _systemUpTime = MTRTimeIntervalForEventTimestampValue(timestamp.mValue);
        } else if (timestamp.IsEpoch()) {
            _eventTimeType = MTREventTimeTypeTimestampDate;
            _timestampDate = [NSDate dateWithTimeIntervalSince1970:MTRTimeIntervalForEventTimestampValue(timestamp.mValue)];
        } else {
            return nil;
        }
        _value = value;
        _error = nil;
    }
    return self;
}

- (instancetype)initWithPath:(const chip::app::ConcreteEventPath &)path error:(NSError *)error
{
    if (self = [super init]) {
        _path = [[MTREventPath alloc] initWithPath:path];
        // Use some sort of initialized values for our members, even though
        // those values are meaningless in this case.
        _eventNumber = @(0);
        _priority = @(MTREventPriorityDebug);
        _eventTimeType = MTREventTimeTypeSystemUpTime;
        _systemUpTime = 0;
        _timestampDate = nil;
        _value = nil;
        _error = error;
    }
    return self;
}

- (nullable instancetype)initWithResponseValue:(NSDictionary<NSString *, id> *)responseValue
                                         error:(NSError * __autoreleasing *)error
{
    if (!(self = [super init])) {
        return nil;
    }

    // In theory, the types of all the things in the dictionary will be correct
    // if our consumer passes in an actual response-value dictionary, but
    // double-check just to be sure
    if (!CheckMemberOfType(
            responseValue, MTREventPathKey, [MTREventPath class], @"response-value event path is not an MTREventPath.", error)) {
        return nil;
    }
    MTREventPath * path = responseValue[MTREventPathKey];

    id _Nullable value = responseValue[MTRErrorKey];
    if (value != nil) {
        if (!CheckMemberOfType(responseValue, MTRErrorKey, [NSError class], @"response-value error is not an NSError.", error)) {
            return nil;
        }

        return [self initWithPath:[path _asConcretePath] error:value];
    }

    if (!CheckMemberOfType(
            responseValue, MTRDataKey, [NSDictionary class], @"response-value data is not a data-value dictionary.", error)) {
        return nil;
    }
    NSDictionary * data = responseValue[MTRDataKey];

    // Encode the data to TLV and then decode from that, to reuse existing code.
    System::PacketBufferHandle buffer;
    Platform::ScopedMemoryBuffer<uint8_t> flatBuffer;
    TLV::TLVReader reader;
    if (!EncodeDataValueToTLV(buffer, flatBuffer, data, reader, error)) {
        return nil;
    }
    auto eventPath = [path _asConcretePath];

    CHIP_ERROR errorCode = CHIP_ERROR_INTERNAL;
    id decodedValue = MTRDecodeEventPayload(eventPath, reader, &errorCode);
    if (errorCode == CHIP_NO_ERROR) {
        // Validate our other members.
        if (!CheckMemberOfType(
                responseValue, MTREventNumberKey, [NSNumber class], @"response-value event number is not an NSNumber", error)) {
            return nil;
        }
        _eventNumber = responseValue[MTREventNumberKey];

        if (!CheckMemberOfType(
                responseValue, MTREventPriorityKey, [NSNumber class], @"response-value event priority is not an NSNumber", error)) {
            return nil;
        }
        _priority = responseValue[MTREventPriorityKey];

        if (!CheckMemberOfType(responseValue, MTREventTimeTypeKey, [NSNumber class],
                @"response-value event time type is not an NSNumber", error)) {
            return nil;
        }
        NSNumber * wrappedTimeType = responseValue[MTREventTimeTypeKey];
        if (wrappedTimeType.unsignedIntegerValue == MTREventTimeTypeSystemUpTime) {
            if (!CheckMemberOfType(responseValue, MTREventSystemUpTimeKey, [NSNumber class],
                    @"response-value event system uptime time is not an NSNumber", error)) {
                return nil;
            }
            NSNumber * wrappedSystemTime = responseValue[MTREventSystemUpTimeKey];
            _systemUpTime = wrappedSystemTime.doubleValue;
        } else if (wrappedTimeType.unsignedIntegerValue == MTREventTimeTypeTimestampDate) {
            if (!CheckMemberOfType(responseValue, MTREventTimestampDateKey, [NSDate class],
                    @"response-value event timestampe is not an NSDate", error)) {
                return nil;
            }
            _timestampDate = responseValue[MTREventTimestampDateKey];
        } else {
            LogStringAndReturnError([NSString stringWithFormat:@"Invalid event time type: %lu", wrappedTimeType.unsignedLongValue],
                MTRErrorCodeInvalidArgument, error);
            return nil;
        }
        _eventTimeType = static_cast<MTREventTimeType>(wrappedTimeType.unsignedIntegerValue);

        _path = path;
        _value = decodedValue;
        _error = nil;
        return self;
    }

    if (errorCode == CHIP_ERROR_IM_MALFORMED_EVENT_PATH_IB) {
        LogStringAndReturnError(@"No known schema for decoding event payload.", MTRErrorCodeUnknownSchema, error);
        return nil;
    }

    // Treat all other errors as schema errors.
    LogStringAndReturnError(@"Event payload decoding failed schema check.", MTRErrorCodeSchemaMismatch, error);
    return nil;
}
@end

@implementation MTREventReport (Deprecated)
- (NSNumber *)timestamp
{
    return _timestampValue;
}
@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;
    }

    if (error != nil) {
        [mEventReports addObject:[[MTREventReport alloc] initWithPath:aEventHeader.mPath error:error]];
    } else {
        [mEventReports addObject:[[MTREventReport alloc] initWithPath:aEventHeader.mPath
                                                          eventNumber:@(aEventHeader.mEventNumber)
                                                             priority:aEventHeader.mPriorityLevel
                                                            timestamp:aEventHeader.mTimestamp
                                                                value:value]];
    }
}

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
