/**
 *
 *    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 <Matter/MTRClusterConstants.h>
#import <Matter/MTRDefines.h>

#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 "MTRMetricKeys.h"
#import "MTRSetupPayload_Internal.h"
#import "NSDataSpanConversion.h"
#import "NSStringSpanConversion.h"
#import "zap-generated/MTRCommandPayloads_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/data-model/List.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::Optional;
using chip::SessionHandle;
using chip::Messaging::ExchangeManager;
using namespace chip::Tracing::DarwinFramework;

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";
NSString * const MTREventIsHistoricalKey = @"eventIsHistorical";

class MTRDataValueDictionaryCallbackBridge;
class MTRDataValueDictionaryDecodableType;
template <typename DecodableValueType>
class BufferedReadClientCallback;

@interface MTRReadClientContainer : NSObject
@property (nonatomic, readwrite) app::ReadClient * readClientPtr;
@property (nonatomic, readwrite) BufferedReadClientCallback<MTRDataValueDictionaryDecodableType> * callback;
@property (nonatomic, readwrite) app::AttributePathParams * pathParams;
@property (nonatomic, readwrite) app::EventPathParams * eventPathParams;
@property (nonatomic, readwrite) uint64_t deviceID;

- (void)cleanup;
- (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) {
                [container cleanup];
            }
            [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];
}

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)cleanup
{
    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;
    }
    if (_callback) {
        Platform::Delete(_callback);
        _callback = nullptr;
    }
}

- (void)onDone
{
    [self cleanup];

    PurgeCompletedReadClientContainers(_deviceID);
}

@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, NSNumber * _Nullable retryDelay) {
                                      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();
                                  }];
}

static NSDictionary<NSString *, id> * _MakeDataValueDictionary(NSString * type, id _Nullable value, NSNumber * _Nullable dataVersion)
{
    if (value && dataVersion) {
        return @ { MTRTypeKey : type, MTRValueKey : value, MTRDataVersionKey : dataVersion };
    } else if (value) {
        return @ { MTRTypeKey : type, MTRValueKey : value };
    } else if (dataVersion) {
        return @ { MTRTypeKey : type, MTRDataVersionKey : dataVersion };
    } else {
        return @ { MTRTypeKey : type };
    }
}

// Convert TLV data into data-value dictionary as described in MTRDeviceResponseHandler
NSDictionary<NSString *, id> * _Nullable MTRDecodeDataValueDictionaryFromCHIPTLV(chip::TLV::TLVReader * data, NSNumber * dataVersion)
{
    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 _MakeDataValueDictionary(MTRSignedIntegerValueType, @(val), dataVersion);
    }
    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 _MakeDataValueDictionary(MTRUnsignedIntegerValueType, @(val), dataVersion);
    }
    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 _MakeDataValueDictionary(MTRBooleanValueType, @(val), dataVersion);
    }
    case chip::TLV::kTLVType_FloatingPointNumber: {
        // Try float first
        float floatValue;
        CHIP_ERROR err = data->Get(floatValue);
        if (err == CHIP_NO_ERROR) {
            return _MakeDataValueDictionary(MTRFloatValueType, @(floatValue), dataVersion);
        }
        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 _MakeDataValueDictionary(MTRDoubleValueType, @(val), dataVersion);
    }
    case chip::TLV::kTLVType_UTF8String: {
        CharSpan stringValue;
        CHIP_ERROR err = data->Get(stringValue);
        if (err != CHIP_NO_ERROR) {
            MTR_LOG_ERROR("Error(%s): TLV UTF8String decoding failed", chip::ErrorStr(err));
            return nil;
        }
        NSString * stringObj = AsString(stringValue);
        if (stringObj == nil) {
            MTR_LOG_ERROR("Error(%s): TLV UTF8String value is not actually UTF-8", err.AsString());
            return nil;
        }
        return _MakeDataValueDictionary(MTRUTF8StringValueType, stringObj, dataVersion);
    }
    case chip::TLV::kTLVType_ByteString: {
        ByteSpan bytesValue;
        CHIP_ERROR err = data->Get(bytesValue);
        if (err != CHIP_NO_ERROR) {
            MTR_LOG_ERROR("Error(%s): TLV ByteString decoding failed", chip::ErrorStr(err));
            return nil;
        }
        return _MakeDataValueDictionary(MTROctetStringValueType, AsData(bytesValue), dataVersion);
    }
    case chip::TLV::kTLVType_Null: {
        return _MakeDataValueDictionary(MTRNullValueType, nil, dataVersion);
    }
    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 of type %s", typeName.UTF8String);
                return nil;
            }
            NSMutableDictionary * arrayElement = [NSMutableDictionary dictionary];
            [arrayElement setObject:value forKey:MTRDataKey];
            if (dataTLVType == chip::TLV::kTLVType_Structure) {
                uint64_t tagNum;
                if (IsContextTag(tag)) {
                    tagNum = TagNumFromTag(tag);
                } else if (IsProfileTag(tag)) {
                    uint64_t profile = ProfileIdFromTag(tag);
                    tagNum = (profile << kProfileIdShift) | TagNumFromTag(tag);
                } else {
                    MTR_LOG_ERROR("Skipping unknown tag type when decoding TLV structure.");
                    continue;
                }
                [arrayElement setObject:[NSNumber numberWithUnsignedLongLong:tagNum] 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 _MakeDataValueDictionary(typeName, array, dataVersion);
    }
    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 isKindOfClass:[NSString class]]) {
        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 UTF8String]);
    }
    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;
            }
            id 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;
            }
            if (![elementTag isKindOfClass:NSNumber.class]) {
                MTR_LOG_ERROR("Error: Structure element to encode has corrupt tag type: %@", [elementTag class]);
                return CHIP_ERROR_INVALID_ARGUMENT;
            }

            // Our tag might actually be a profile tag.
            uint64_t tagValue = [elementTag unsignedLongLongValue];
            TLV::Tag tag;
            if (tagValue > UINT8_MAX) {
                tag = TLV::ProfileTag(tagValue >> kProfileIdShift,
                    (tagValue & ((1ull << kProfileIdShift) - 1)));
            } else {
                tag = TLV::ContextTag(static_cast<uint8_t>(tagValue));
            }
            ReturnErrorOnFailure(
                MTREncodeTLVFromDataValueDictionary(elementValue, writer, tag));
        }
        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;
}

NSData * _Nullable MTREncodeTLVFromDataValueDictionary(NSDictionary<NSString *, id> * value, NSError * __autoreleasing * error)
{
    // A single data item cannot be bigger than a packet, so just use 1200 bytes
    // as the max size of our buffer.  This assumes that lists will not be
    // passed as-is to this method but will get chunked, with each list item
    // passed to this method separately.
    uint8_t buffer[1200];
    TLV::TLVWriter writer;
    writer.Init(buffer);

    CHIP_ERROR err = MTREncodeTLVFromDataValueDictionary(value, writer, TLV::AnonymousTag());
    if (err != CHIP_NO_ERROR) {
        if (error) {
            *error = [MTRError errorForCHIPErrorCode:err];
        }
        return nil;
    }

    return AsData(ByteSpan(buffer, writer.GetLengthWritten()));
}

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

    NSDictionary<NSString *, id> * _Nullable GetDecodedObject() const { return decodedObj; }

private:
    NSDictionary<NSString *, 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 ConcreteDataAttributePath & 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(
            std::find_if(mAttributePathParamsList, mAttributePathParamsList + mAttributePathParamsSize,
                [aPath](app::AttributePathParams & pathParam) -> bool { return pathParam.IsAttributePathSupersetOf(aPath); })
                != mAttributePathParamsList + mAttributePathParamsSize,
            err = CHIP_ERROR_SCHEMA_MISMATCH);

        VerifyOrExit(aStatus.IsSuccess(), err = aStatus.ToChipError());

        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(apStatus == nullptr, err = apStatus->ToChipError());

        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)_readKnownAttributeWithEndpointID:(NSNumber *)endpointID
                                clusterID:(NSNumber *)clusterID
                              attributeID:(NSNumber *)attributeID
                                   params:(MTRReadParams * _Nullable)params
                                    queue:(dispatch_queue_t)queue
                               completion:(void (^)(id _Nullable value, NSError * _Nullable error))completion
{
    auto * attributePath = [MTRAttributePath attributePathWithEndpointID:endpointID clusterID:clusterID attributeID:attributeID];

    auto innerCompletion = ^(NSArray<NSDictionary<NSString *, id> *> * _Nullable values, NSError * _Nullable error) {
        if (error != nil) {
            completion(nil, error);
            return;
        }

        // Preserving the old behavior: we don't fail on multiple reports, but
        // just report the first one.
        if (values.count == 0) {
            completion(nil, [NSError errorWithDomain:MTRErrorDomain code:MTRErrorCodeSchemaMismatch userInfo:nil]);
            return;
        }

        NSDictionary<NSString *, id> * value = values[0];
        NSError * initError;
        auto * report = [[MTRAttributeReport alloc] initWithResponseValue:value error:&initError];
        if (initError != nil) {
            completion(nil, initError);
            return;
        }

        if (![report.path isEqual:attributePath]) {
            // For some reason the server returned data for the wrong
            // attribute, even though it happened to decode to our type.
            completion(nil, [NSError errorWithDomain:MTRErrorDomain code:MTRErrorCodeSchemaMismatch userInfo:nil]);
            return;
        }

        completion(report.value, report.error);
    };

    [self readAttributesWithEndpointID:endpointID
                             clusterID:clusterID
                           attributeID:attributeID
                                params:params
                                 queue:queue
                            completion:innerCompletion];
}

- (void)readAttributePaths:(NSArray<MTRAttributeRequestPath *> * _Nullable)attributePaths
                eventPaths:(NSArray<MTREventRequestPath *> * _Nullable)eventPaths
                    params:(MTRReadParams * _Nullable)params
                     queue:(dispatch_queue_t)queue
                completion:(MTRDeviceResponseHandler)completion
{
    [self readAttributePaths:attributePaths eventPaths:eventPaths params:params includeDataVersion:NO queue:queue completion:completion];
}

- (void)readAttributePaths:(NSArray<MTRAttributeRequestPath *> * _Nullable)attributePaths
                eventPaths:(NSArray<MTREventRequestPath *> * _Nullable)eventPaths
                    params:(MTRReadParams * _Nullable)params
        includeDataVersion:(BOOL)includeDataVersion
                     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, includeDataVersion](const ConcreteDataAttributePath & aAttributePath, const MTRDataValueDictionaryDecodableType & aData) {
                      // TODO: move this logic into MTRDataValueDictionaryDecodableType
                      if (includeDataVersion && aAttributePath.mDataVersion.HasValue()) {
                          NSDictionary * dataValue = aData.GetDecodedObject();
                          [resultArray addObject:@{
                              MTRAttributePathKey : [[MTRAttributePath alloc] initWithPath:aAttributePath],
                              MTRDataKey : _MakeDataValueDictionary(dataValue[MTRTypeKey], dataValue[MTRValueKey], @(aAttributePath.mDataVersion.Value()))
                          }];
                      } else {
                          [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();
            IgnoreUnusedVariable(attributePathParamsList.Release());
            IgnoreUnusedVariable(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); };

            // To handle list chunking properly, we have to convert lists into
            // DataModel::List here, because that's special-cased in
            // WriteClient.
            if (![value isKindOfClass:NSDictionary.class]) {
                MTR_LOG_ERROR("Error: Unsupported object to write as attribute value: %@", value);
                return CHIP_ERROR_INVALID_ARGUMENT;
            }

            NSDictionary<NSString *, id> * dataValue = value;
            NSString * typeName = dataValue[MTRTypeKey];
            if (![typeName isKindOfClass:NSString.class]) {
                MTR_LOG_ERROR("Error: Object to encode is corrupt: %@", dataValue);
                return CHIP_ERROR_INVALID_ARGUMENT;
            }

            if (![typeName isEqualToString:MTRArrayValueType]) {
                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]));
            }

            // Now we are dealing with a list.
            NSArray<NSDictionary<NSString *, id> *> * arrayValue = value[MTRValueKey];
            if (![arrayValue isKindOfClass:NSArray.class]) {
                MTR_LOG_ERROR("Error: Object to encode claims to be a list but isn't: %@", arrayValue);
                return CHIP_ERROR_INVALID_ARGUMENT;
            }

            std::vector<MTRDataValueDictionaryDecodableType> encodableVector;
            encodableVector.reserve(arrayValue.count);

            for (NSDictionary<NSString *, id> * arrayItem in arrayValue) {
                if (![arrayItem isKindOfClass:NSDictionary.class]) {
                    MTR_LOG_ERROR("Error: Can't encode corrupt list: %@", arrayValue);
                    return CHIP_ERROR_INVALID_ARGUMENT;
                }

                encodableVector.push_back(MTRDataValueDictionaryDecodableType(arrayItem[MTRDataKey]));
            }

            DataModel::List<MTRDataValueDictionaryDecodableType> encodableList(encodableVector.data(), encodableVector.size());
            return chip::Controller::WriteAttribute<DataModel::List<MTRDataValueDictionaryDecodableType>>(session,
                static_cast<chip::EndpointId>([endpointID unsignedShortValue]),
                static_cast<chip::ClusterId>([clusterID unsignedLongValue]),
                static_cast<chip::AttributeId>([attributeID unsignedLongValue]), encodableList,
                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
{
    // 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
    [self _invokeCommandWithEndpointID:endpointID
                             clusterID:clusterID
                             commandID:commandID
                         commandFields:commandFields
                    timedInvokeTimeout:timeoutMs
           serverSideProcessingTimeout:nil
                                 queue:queue
                            completion:completion];
}

- (void)_invokeCommandWithEndpointID:(NSNumber *)endpointID
                           clusterID:(NSNumber *)clusterID
                           commandID:(NSNumber *)commandID
                       commandFields:(id)commandFields
                  timedInvokeTimeout:(NSNumber * _Nullable)timeoutMs
         serverSideProcessingTimeout:(NSNumber * _Nullable)serverSideProcessingTimeout
                               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];

    serverSideProcessingTimeout = [serverSideProcessingTimeout copy];
    if (serverSideProcessingTimeout != nil) {
        serverSideProcessingTimeout = MTRClampedNumber(serverSideProcessingTimeout, @(0), @(UINT16_MAX));
    }

    timeoutMs = [timeoutMs copy];
    if (timeoutMs != nil) {
        timeoutMs = MTRClampedNumber(timeoutMs, @(1), @(UINT16_MAX));
    }

    auto * bridge = new MTRDataValueDictionaryCallbackBridge(queue, completion,
        ^(ExchangeManager & exchangeManager, const SessionHandle & session, MTRDataValueDictionaryCallback successCb,
            MTRErrorCallback failureCb, MTRCallbackBridgeBase * bridge) {
            NSData * attestationChallenge;
            if ([clusterID isEqualToNumber:@(MTRClusterIDTypeOperationalCredentialsID)] &&
                [commandID isEqualToNumber:@(MTRCommandIDTypeClusterOperationalCredentialsCommandAttestationRequestID)] && session->IsSecureSession()) {
                // An AttestationResponse command needs to have an attestationChallenge
                // to make sense of the results.  If we are doing an
                // AttestationRequest, store the challenge now.
                attestationChallenge = AsData(session->AsSecureSession()->GetCryptoContext().GetAttestationChallenge());
            }
            // NSObjectCommandCallback guarantees that there will be exactly one call to either the success callback or the failure
            // callback.
            auto onSuccessCb = [successCb, bridge, attestationChallenge](const app::ConcreteCommandPath & commandPath, const app::StatusIB & status,
                                   const MTRDataValueDictionaryDecodableType & responseData) {
                auto resultArray = [[NSMutableArray alloc] init];
                if (responseData.GetDecodedObject()) {
                    auto response = responseData.GetDecodedObject();
                    if (attestationChallenge != nil) {
                        // Add the attestationChallenge to our data.
                        NSArray<NSDictionary<NSString *, id> *> * value = response[MTRValueKey];
                        NSMutableArray<NSDictionary<NSString *, id> *> * newValue = [[NSMutableArray alloc] initWithCapacity:(value.count + 1)];
                        [newValue addObjectsFromArray:value];
                        [newValue addObject:@{
                            MTRContextTagKey : @(kAttestationChallengeTagValue),
                            MTRDataKey : @ {
                                MTRTypeKey : MTROctetStringValueType,
                                MTRValueKey : attestationChallenge,
                            },
                        }];
                        auto * newResponse = [NSMutableDictionary dictionaryWithCapacity:(response.count + 1)];
                        [newResponse addEntriesFromDictionary:response];
                        newResponse[MTRValueKey] = newValue;
                        response = newResponse;
                    }
                    [resultArray addObject:@ {
                        MTRCommandPathKey : [[MTRCommandPath alloc] initWithPath:commandPath],
                        MTRDataKey : response,
                    }];
                } 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])));

            Optional<System::Clock::Timeout> invokeTimeout;
            if (serverSideProcessingTimeout != nil) {
                // Clamp to a number of seconds that will not overflow 32-bit
                // int when converted to ms.
                auto serverTimeoutInSeconds = System::Clock::Seconds16(serverSideProcessingTimeout.unsignedShortValue);
                invokeTimeout.SetValue(session->ComputeRoundTripTimeout(serverTimeoutInSeconds));
            }
            ReturnErrorOnFailure(commandSender->SendCommandRequest(session, invokeTimeout));

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

- (void)_invokeKnownCommandWithEndpointID:(NSNumber *)endpointID
                                clusterID:(NSNumber *)clusterID
                                commandID:(NSNumber *)commandID
                           commandPayload:(id)commandPayload
                       timedInvokeTimeout:(NSNumber * _Nullable)timeout
              serverSideProcessingTimeout:(NSNumber * _Nullable)serverSideProcessingTimeout
                            responseClass:(Class _Nullable)responseClass
                                    queue:(dispatch_queue_t)queue
                               completion:(void (^)(id _Nullable response, NSError * _Nullable error))completion
{
    NSError * encodingError;
    auto * commandFields = [commandPayload _encodeAsDataValue:&encodingError];
    if (commandFields == nil) {
        dispatch_async(queue, ^{
            completion(nil, encodingError);
        });
        return;
    }

    auto responseHandler = ^(NSArray<NSDictionary<NSString *, id> *> * _Nullable values, NSError * _Nullable error) {
        id _Nullable response = nil;
        if (error == nil) {
            if (values.count != 1) {
                error = [NSError errorWithDomain:MTRErrorDomain code:MTRErrorCodeSchemaMismatch userInfo:nil];
            } else if (responseClass != nil) {
                response = [[responseClass alloc] initWithResponseValue:values[0] error:&error];
            }
        }
        completion(response, error);
    };

    [self _invokeCommandWithEndpointID:endpointID
                             clusterID:clusterID
                             commandID:commandID
                         commandFields:commandFields
                    timedInvokeTimeout:timeout
           serverSideProcessingTimeout:serverSideProcessingTimeout
                                 queue:queue
                            completion:responseHandler];
}

- (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)_subscribeToKnownAttributeWithEndpointID:(NSNumber *)endpointID
                                       clusterID:(NSNumber *)clusterID
                                     attributeID:(NSNumber *)attributeID
                                          params:(MTRSubscribeParams *)params
                                           queue:(dispatch_queue_t)queue
                                   reportHandler:(void (^)(id _Nullable value, NSError * _Nullable error))reportHandler
                         subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptionEstablished
{
    auto * attributePath = [MTRAttributePath attributePathWithEndpointID:endpointID clusterID:clusterID attributeID:attributeID];

    auto innerReportHandler = ^(NSArray<NSDictionary<NSString *, id> *> * _Nullable values, NSError * _Nullable error) {
        if (error != nil) {
            reportHandler(nil, error);
            return;
        }

        for (NSDictionary<NSString *, id> * value in values) {
            NSError * initError;
            auto * report = [[MTRAttributeReport alloc] initWithResponseValue:value error:&initError];
            if (initError != nil) {
                reportHandler(nil, initError);
                continue;
            }

            if (![report.path isEqual:attributePath]) {
                // For some reason the server returned data for the wrong
                // attribute, even though it happened to decode to our type.
                reportHandler(nil, [NSError errorWithDomain:MTRErrorDomain code:MTRErrorCodeSchemaMismatch userInfo:nil]);
                continue;
            }

            reportHandler(report.value, report.error);
        }
    };

    [self subscribeToAttributesWithEndpointID:endpointID
                                    clusterID:clusterID
                                  attributeID:attributeID
                                       params:params
                                        queue:queue
                                reportHandler:innerReportHandler
                      subscriptionEstablished:subscriptionEstablished];
}

- (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, NSNumber * _Nullable retryDelay) {
                   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(@[ @ {
                                   MTREventPathKey : [[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]);
                           });
                           [container cleanup];
                           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]);
                           });
                           [container cleanup];
                           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];
                   };

                   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);

                   container.readClientPtr = readClient;
                   container.callback = callback.release();

                   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]);
                       });
                       [container cleanup];
                       return;
                   }

                   // Read clients will be purged when deregistered.
                   AddReadClientContainer(container.deviceID, container);
               }];
}

- (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 OpenCommissioningWindowHelper(controller, callback);
    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
{
    MATTER_LOG_METRIC_BEGIN(kMetricOpenPairingWindow);

    if (self.isPASEDevice) {
        MTR_LOG_ERROR("Can't open a commissioning window over PASE");
        dispatch_async(queue, ^{
            MATTER_LOG_METRIC_END(kMetricOpenPairingWindow, CHIP_ERROR_INCORRECT_STATE);
            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, ^{
            MATTER_LOG_METRIC_END(kMetricOpenPairingWindow, CHIP_ERROR_INVALID_INTEGER_VALUE);
            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, ^{
            MATTER_LOG_METRIC_END(kMetricOpenPairingWindow, CHIP_ERROR_INVALID_INTEGER_VALUE);
            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, ^{
                MATTER_LOG_METRIC_END(kMetricOpenPairingWindow, CHIP_ERROR_INVALID_INTEGER_VALUE);
                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, ^{
                        MATTER_LOG_METRIC_END(kMetricOpenPairingWindow, status);
                        completion(nil, [MTRError errorForCHIPErrorCode:status]);
                    });
                    return;
                }
                auto * payloadObj = [[MTRSetupPayload alloc] initWithSetupPayload:payload];
                if (payloadObj == nil) {
                    dispatch_async(queue, ^{
                        MATTER_LOG_METRIC_END(kMetricOpenPairingWindow, CHIP_ERROR_NO_MEMORY);
                        completion(nil, [MTRError errorForCHIPErrorCode:CHIP_ERROR_NO_MEMORY]);
                    });
                    return;
                }

                dispatch_async(queue, ^{
                    MATTER_LOG_METRIC_END(kMetricOpenPairingWindow, CHIP_NO_ERROR);
                    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, ^{
                    MATTER_LOG_METRIC_END(kMetricOpenPairingWindow, errorCode);
                    completion(nil, [MTRError errorForCHIPErrorCode:errorCode]);
                });
                return;
            }

            // resultCallback will handle things now.
        }
        errorHandler:^(NSError * error) {
            dispatch_async(queue, ^{
                MATTER_LOG_METRIC_END(kMetricOpenPairingWindow, [MTRError errorToCHIPErrorCode:error]);
                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
// 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();
}
#endif

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

- (void)downloadLogOfType:(MTRDiagnosticLogType)type
                  timeout:(NSTimeInterval)timeout
                    queue:(dispatch_queue_t)queue
               completion:(void (^)(NSURL * _Nullable url, NSError * _Nullable error))completion
{
    [_deviceController downloadLogFromNodeWithID:@(_nodeID)
                                            type:type
                                         timeout:timeout
                                           queue:queue
                                      completion:completion];
}

@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 class] != [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 class] != [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 class] != [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];
}

static NSString * const sEndpointKey = @"endpointKey";
static NSString * const sClusterKey = @"clusterKey";

+ (BOOL)supportsSecureCoding
{
    return YES;
}

- (nullable instancetype)initWithCoder:(NSCoder *)decoder
{
    self = [super init];
    if (self == nil) {
        return nil;
    }

    _endpoint = [decoder decodeObjectOfClass:[NSNumber class] forKey:sEndpointKey];
    if (_endpoint && ![_endpoint isKindOfClass:[NSNumber class]]) {
        MTR_LOG_ERROR("MTRClusterPath decoded %@ for endpoint, not NSNumber.", _endpoint);
        return nil;
    }

    _cluster = [decoder decodeObjectOfClass:[NSNumber class] forKey:sClusterKey];
    if (_cluster && ![_cluster isKindOfClass:[NSNumber class]]) {
        MTR_LOG_ERROR("MTRClusterPath decoded %@ for cluster, not NSNumber.", _cluster);
        return nil;
    }

    return self;
}

- (void)encodeWithCoder:(NSCoder *)coder
{
    [coder encodeObject:_endpoint forKey:sEndpointKey];
    [coder encodeObject:_cluster forKey:sClusterKey];
}

@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 class] != [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]));
}

static NSString * const sAttributeKey = @"attributeKey";

+ (BOOL)supportsSecureCoding
{
    return YES;
}

- (nullable instancetype)initWithCoder:(NSCoder *)decoder
{
    self = [super initWithCoder:decoder];
    if (self == nil) {
        return nil;
    }

    _attribute = [decoder decodeObjectOfClass:[NSNumber class] forKey:sAttributeKey];
    if (_attribute && ![_attribute isKindOfClass:[NSNumber class]]) {
        MTR_LOG_ERROR("MTRAttributePath decoded %@ for attribute, not NSNumber.", _attribute);
        return nil;
    }

    return self;
}

- (void)encodeWithCoder:(NSCoder *)coder
{
    [super encodeWithCoder:coder];
    [coder encodeObject:_attribute forKey:sAttributeKey];
}

@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];
}

- (BOOL)isEqualToEventPath:(MTREventPath *)eventPath
{
    return [self isEqualToClusterPath:eventPath] && [_event isEqualToNumber:eventPath.event];
}

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

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

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

static NSString * const sEventKey = @"eventKey";

+ (BOOL)supportsSecureCoding
{
    return YES;
}

- (nullable instancetype)initWithCoder:(NSCoder *)decoder
{
    self = [super initWithCoder:decoder];
    if (self == nil) {
        return nil;
    }

    _event = [decoder decodeObjectOfClass:[NSNumber class] forKey:sEventKey];
    if (_event && ![_event isKindOfClass:[NSNumber class]]) {
        MTR_LOG_ERROR("MTREventPath decoded %@ for event, not NSNumber.", _event);
        return nil;
    }

    return self;
}

- (void)encodeWithCoder:(NSCoder *)coder
{
    [super encodeWithCoder:coder];
    [coder encodeObject:_event forKey:sEventKey];
}
@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;
}

- (NSString *)description
{
    return
        [NSString stringWithFormat:@"<MTRCommandPath endpoint %u cluster %lu command %lu>", self.endpoint.unsignedShortValue,
                  self.cluster.unsignedLongValue, _command.unsignedLongValue];
}

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

- (BOOL)isEqualToCommandPath:(MTRCommandPath *)commandPath
{
    return [self isEqualToClusterPath:commandPath] && [_command isEqualToNumber:commandPath.command];
}

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

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

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

static NSString * const sCommandKey = @"commandKey";

+ (BOOL)supportsSecureCoding
{
    return YES;
}

- (nullable instancetype)initWithCoder:(NSCoder *)decoder
{
    self = [super initWithCoder:decoder];
    if (self == nil) {
        return nil;
    }

    _command = [decoder decodeObjectOfClass:[NSNumber class] forKey:sCommandKey];
    if (_command && ![_command isKindOfClass:[NSNumber class]]) {
        MTR_LOG_ERROR("MTRCommandPath decoded %@ for command, not NSNumber.", _command);
        return nil;
    }

    return self;
}

- (void)encodeWithCoder:(NSCoder *)coder
{
    [super encodeWithCoder:coder];
    [coder encodeObject:_command forKey:sCommandKey];
}
@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

@implementation MTREventReport {
    NSNumber * _timestampValue;
}

+ (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
