/*
 *   Copyright (c) 2022 Project CHIP Authors
 *   All rights reserved.
 *
 *   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.
 *
 */

#pragma once

#include <app/BufferedReadCallback.h>
#include <app/ChunkedWriteCallback.h>
#include <app/CommandSender.h>
#include <app/DeviceProxy.h>
#include <app/InteractionModelEngine.h>
#include <app/ReadClient.h>
#include <app/WriteClient.h>
#include <lib/support/CodeUtils.h>
#include <lib/support/UnitTestUtils.h>

inline constexpr uint8_t kMaxAllowedPaths = 64;

namespace chip {
namespace test_utils {
void BusyWaitMillis(uint16_t busyWaitForMs);
} // namespace test_utils
} // namespace chip

class InteractionModelConfig
{
public:
    struct AttributePathsConfig
    {
        size_t count = 0;
        std::unique_ptr<chip::app::AttributePathParams[]> attributePathParams;
        std::unique_ptr<chip::app::DataVersionFilter[]> dataVersionFilter;
    };

    static CHIP_ERROR GetAttributePaths(std::vector<chip::EndpointId> endpointIds, std::vector<chip::ClusterId> clusterIds,
                                        std::vector<chip::AttributeId> attributeIds,
                                        const chip::Optional<std::vector<chip::DataVersion>> & dataVersions,
                                        AttributePathsConfig & pathsConfig);
};

class InteractionModelReports
{
public:
    InteractionModelReports(chip::app::ReadClient::Callback * callback) : mBufferedReadAdapter(*callback) { ResetOptions(); }

protected:
    CHIP_ERROR ReadAttribute(chip::DeviceProxy * device, std::vector<chip::EndpointId> endpointIds,
                             std::vector<chip::ClusterId> clusterIds, std::vector<chip::AttributeId> attributeIds)
    {
        return ReportAttribute(device, endpointIds, clusterIds, attributeIds, chip::app::ReadClient::InteractionType::Read);
    }

    CHIP_ERROR SubscribeAttribute(chip::DeviceProxy * device, std::vector<chip::EndpointId> endpointIds,
                                  std::vector<chip::ClusterId> clusterIds, std::vector<chip::AttributeId> attributeIds)
    {
        return ReportAttribute(device, endpointIds, clusterIds, attributeIds, chip::app::ReadClient::InteractionType::Subscribe);
    }

    CHIP_ERROR ReportAttribute(chip::DeviceProxy * device, std::vector<chip::EndpointId> endpointIds,
                               std::vector<chip::ClusterId> clusterIds, std::vector<chip::AttributeId> attributeIds,
                               chip::app::ReadClient::InteractionType interactionType);

    CHIP_ERROR ReadEvent(chip::DeviceProxy * device, std::vector<chip::EndpointId> endpointIds,
                         std::vector<chip::ClusterId> clusterIds, std::vector<chip::EventId> eventIds)
    {
        return ReportEvent(device, endpointIds, clusterIds, eventIds, chip::app::ReadClient::InteractionType::Read);
    }

    CHIP_ERROR SubscribeEvent(chip::DeviceProxy * device, std::vector<chip::EndpointId> endpointIds,
                              std::vector<chip::ClusterId> clusterIds, std::vector<chip::EventId> eventIds)
    {
        return ReportEvent(device, endpointIds, clusterIds, eventIds, chip::app::ReadClient::InteractionType::Subscribe);
    }

    CHIP_ERROR ReportEvent(chip::DeviceProxy * device, std::vector<chip::EndpointId> endpointIds,
                           std::vector<chip::ClusterId> clusterIds, std::vector<chip::EventId> eventIds,
                           chip::app::ReadClient::InteractionType interactionType);

    CHIP_ERROR ReadNone(chip::DeviceProxy * device) { return ReportNone(device, chip::app::ReadClient::InteractionType::Read); }

    CHIP_ERROR ReadAll(chip::DeviceProxy * device, std::vector<chip::EndpointId> endpointIds,
                       std::vector<chip::ClusterId> clusterIds, std::vector<chip::AttributeId> attributeIds,
                       std::vector<chip::EventId> eventIds)
    {
        return ReportAll(device, endpointIds, clusterIds, attributeIds, eventIds, chip::app::ReadClient::InteractionType::Read);
    }

    CHIP_ERROR SubscribeNone(chip::DeviceProxy * device)
    {
        return ReportNone(device, chip::app::ReadClient::InteractionType::Subscribe);
    }

    CHIP_ERROR SubscribeAll(chip::DeviceProxy * device, std::vector<chip::EndpointId> endpointIds,
                            std::vector<chip::ClusterId> clusterIds, std::vector<chip::AttributeId> attributeIds,
                            std::vector<chip::EventId> eventIds)
    {
        return ReportAll(device, endpointIds, clusterIds, attributeIds, eventIds,
                         chip::app::ReadClient::InteractionType::Subscribe);
    }

    CHIP_ERROR ReportNone(chip::DeviceProxy * device, chip::app::ReadClient::InteractionType interactionType);

    CHIP_ERROR ReportAll(chip::DeviceProxy * device, std::vector<chip::EndpointId> endpointIds,
                         std::vector<chip::ClusterId> clusterIds, std::vector<chip::AttributeId> attributeIds,
                         std::vector<chip::EventId> eventIds, chip::app::ReadClient::InteractionType interactionType);

    void OnDeallocatePaths(chip::app::ReadPrepareParams && aReadPrepareParams);

    void Shutdown() { mReadClients.clear(); }

    void CleanupReadClient(chip::app::ReadClient * aReadClient);

    std::vector<std::unique_ptr<chip::app::ReadClient>> mReadClients;
    chip::app::BufferedReadCallback mBufferedReadAdapter;

    InteractionModelReports & SetDataVersions(const std::vector<chip::DataVersion> & dataVersions)
    {
        mDataVersions.SetValue(dataVersions);
        return *this;
    }

    InteractionModelReports & SetDataVersions(const chip::Optional<std::vector<chip::DataVersion>> & dataVersions)
    {
        mDataVersions = dataVersions;
        return *this;
    }

    InteractionModelReports & SetIsUrgents(const std::vector<bool> isUrgents)
    {
        mIsUrgents.SetValue(isUrgents);
        return *this;
    }

    InteractionModelReports & SetIsUrgents(const chip::Optional<std::vector<bool>> & isUrgents)
    {
        mIsUrgents = isUrgents;
        return *this;
    }

    InteractionModelReports & SetEventNumber(const chip::Optional<chip::EventNumber> & eventNumber)
    {
        mEventNumber = eventNumber;
        return *this;
    }

    InteractionModelReports & SetEventNumber(chip::EventNumber eventNumber)
    {
        mEventNumber.SetValue(eventNumber);
        return *this;
    }

    InteractionModelReports & SetFabricFiltered(bool fabricFiltered)
    {
        mFabricFiltered.SetValue(fabricFiltered);
        return *this;
    }

    InteractionModelReports & SetKeepSubscriptions(bool keepSubscriptions)
    {
        mKeepSubscriptions.SetValue(keepSubscriptions);
        return *this;
    }

    InteractionModelReports & SetKeepSubscriptions(const chip::Optional<bool> & keepSubscriptions)
    {
        mKeepSubscriptions = keepSubscriptions;
        return *this;
    }

    InteractionModelReports & SetAutoResubscribe(bool autoResubscribe)
    {
        mAutoResubscribe.SetValue(autoResubscribe);
        return *this;
    }

    InteractionModelReports & SetAutoResubscribe(const chip::Optional<bool> & autoResubscribe)
    {
        mAutoResubscribe = autoResubscribe;
        return *this;
    }

    InteractionModelReports & SetMinInterval(uint16_t minInterval)
    {
        mMinInterval = minInterval;
        return *this;
    }

    InteractionModelReports & SetMaxInterval(uint16_t maxInterval)
    {
        mMaxInterval = maxInterval;
        return *this;
    }

    InteractionModelReports & SetPeerLIT(bool isPeerLIT)
    {
        mIsPeerLIT = isPeerLIT;
        return *this;
    }

    void ResetOptions()
    {
        mDataVersions      = chip::NullOptional;
        mIsUrgents         = chip::NullOptional;
        mEventNumber       = chip::NullOptional;
        mFabricFiltered    = chip::Optional<bool>(true);
        mKeepSubscriptions = chip::NullOptional;
        mAutoResubscribe   = chip::NullOptional;
        mIsPeerLIT         = false;
        mMinInterval       = 0;
        mMaxInterval       = 0;
    }

    chip::Optional<std::vector<chip::DataVersion>> mDataVersions;
    chip::Optional<std::vector<bool>> mIsUrgents;
    chip::Optional<chip::EventNumber> mEventNumber;
    chip::Optional<bool> mFabricFiltered;
    chip::Optional<bool> mKeepSubscriptions;
    chip::Optional<bool> mAutoResubscribe;
    bool mIsPeerLIT;
    uint16_t mMinInterval;
    uint16_t mMaxInterval;
};

class InteractionModelCommands
{
public:
    InteractionModelCommands(chip::app::CommandSender::Callback * callback) : mCallback(callback) { ResetOptions(); }

protected:
    template <class T>
    CHIP_ERROR SendCommand(chip::DeviceProxy * device, chip::EndpointId endpointId, chip::ClusterId clusterId,
                           chip::CommandId commandId, const T & value)
    {
        uint16_t repeat = mRepeatCount.ValueOr(1);
        while (repeat--)
        {

            chip::app::CommandPathParams commandPath = { endpointId, clusterId, commandId,
                                                         (chip::app::CommandPathFlags::kEndpointIdValid) };
            auto commandSender                       = std::make_unique<chip::app::CommandSender>(
                mCallback, device->GetExchangeManager(), mTimedInteractionTimeoutMs.HasValue(), mSuppressResponse.ValueOr(false));
            VerifyOrReturnError(commandSender != nullptr, CHIP_ERROR_NO_MEMORY);

            chip::app::CommandSender::AddRequestDataParameters addRequestDataParams(mTimedInteractionTimeoutMs);
            // Using TestOnly AddRequestData to allow for an intentionally malformed request for server validation testing.
            ReturnErrorOnFailure(commandSender->TestOnlyAddRequestDataNoTimedCheck(commandPath, value, addRequestDataParams));
            ReturnErrorOnFailure(commandSender->SendCommandRequest(device->GetSecureSession().Value()));
            mCommandSender.push_back(std::move(commandSender));

            if (mBusyWaitForMs.HasValue())
            {
                chip::test_utils::BusyWaitMillis(mBusyWaitForMs.Value());
            }

            if (mRepeatDelayInMs.HasValue())
            {
                chip::test_utils::SleepMillis(mRepeatDelayInMs.Value());
            }
        }
        return CHIP_NO_ERROR;
    }

    template <class T>
    CHIP_ERROR SendGroupCommand(chip::GroupId groupId, chip::FabricIndex fabricIndex, chip::ClusterId clusterId,
                                chip::CommandId commandId, const T & value)
    {
        chip::app::CommandPathParams commandPath = { groupId, clusterId, commandId, (chip::app::CommandPathFlags::kGroupIdValid) };

        chip::Messaging::ExchangeManager * exchangeManager = chip::app::InteractionModelEngine::GetInstance()->GetExchangeManager();
        VerifyOrReturnError(exchangeManager != nullptr, CHIP_ERROR_INCORRECT_STATE);

        chip::app::CommandSender commandSender(mCallback, exchangeManager);
        chip::app::CommandSender::AddRequestDataParameters addRequestDataParams;
        // Using TestOnly AddRequestData to allow for an intentionally malformed request for server validation testing.
        ReturnErrorOnFailure(commandSender.TestOnlyAddRequestDataNoTimedCheck(commandPath, value, addRequestDataParams));

        chip::Transport::OutgoingGroupSession session(groupId, fabricIndex);
        return commandSender.SendGroupCommandRequest(chip::SessionHandle(session));
    }

    void Shutdown()
    {
        for (auto & commandSender : mCommandSender)
        {
            commandSender.reset();
        }
        mCommandSender.clear();
    }

    std::vector<std::unique_ptr<chip::app::CommandSender>> mCommandSender;
    chip::app::CommandSender::Callback * mCallback;

    InteractionModelCommands & SetTimedInteractionTimeoutMs(uint16_t timedInteractionTimeoutMs)
    {
        mTimedInteractionTimeoutMs.SetValue(timedInteractionTimeoutMs);
        return *this;
    }

    InteractionModelCommands & SetTimedInteractionTimeoutMs(const chip::Optional<uint16_t> & timedInteractionTimeoutMs)
    {
        mTimedInteractionTimeoutMs = timedInteractionTimeoutMs;
        return *this;
    }

    InteractionModelCommands & SetSuppressResponse(bool suppressResponse)
    {
        mSuppressResponse.SetValue(suppressResponse);
        return *this;
    }

    InteractionModelCommands & SetSuppressResponse(const chip::Optional<bool> & suppressResponse)
    {
        mSuppressResponse = suppressResponse;
        return *this;
    }

    InteractionModelCommands & SetRepeatCount(uint16_t repeatCount)
    {
        mRepeatCount.SetValue(repeatCount);
        return *this;
    }

    InteractionModelCommands & SetRepeatCount(const chip::Optional<uint16_t> & repeatCount)
    {
        mRepeatCount = repeatCount;
        return *this;
    }

    InteractionModelCommands & SetRepeatDelayInMs(uint16_t repeatDelayInMs)
    {
        mRepeatDelayInMs.SetValue(repeatDelayInMs);
        return *this;
    }

    InteractionModelCommands & SetRepeatDelayInMs(const chip::Optional<uint16_t> & repeatDelayInMs)
    {
        mRepeatDelayInMs = repeatDelayInMs;
        return *this;
    }

    InteractionModelCommands & SetBusyWaitForMs(uint16_t busyWaitForMs)
    {
        mBusyWaitForMs.SetValue(busyWaitForMs);
        return *this;
    }

    InteractionModelCommands & SetBusyWaitForMs(const chip::Optional<uint16_t> & busyWaitForMs)
    {
        mBusyWaitForMs = busyWaitForMs;
        return *this;
    }

    void ResetOptions()
    {
        mTimedInteractionTimeoutMs = chip::NullOptional;
        mSuppressResponse          = chip::NullOptional;
        mRepeatCount               = chip::NullOptional;
        mRepeatDelayInMs           = chip::NullOptional;
        mBusyWaitForMs             = chip::NullOptional;
    }

    chip::Optional<uint16_t> mTimedInteractionTimeoutMs;
    chip::Optional<bool> mSuppressResponse;
    chip::Optional<uint16_t> mRepeatCount;
    chip::Optional<uint16_t> mRepeatDelayInMs;
    chip::Optional<uint16_t> mBusyWaitForMs;
};

class InteractionModelWriter
{
public:
    InteractionModelWriter(chip::app::WriteClient::Callback * callback) : mChunkedWriteCallback(callback) {}

protected:
    template <class T>
    CHIP_ERROR WriteAttribute(chip::DeviceProxy * device, std::vector<chip::EndpointId> endpointIds,
                              std::vector<chip::ClusterId> clusterIds, std::vector<chip::AttributeId> attributeIds,
                              const std::vector<T> & values)
    {
        InteractionModelConfig::AttributePathsConfig pathsConfig;
        ReturnErrorOnFailure(
            InteractionModelConfig::GetAttributePaths(endpointIds, clusterIds, attributeIds, mDataVersions, pathsConfig));

        VerifyOrReturnError(pathsConfig.count == values.size() || values.size() == 1, CHIP_ERROR_INVALID_ARGUMENT);

        uint16_t repeat = mRepeatCount.ValueOr(1);
        while (repeat--)
        {

            mWriteClient = std::make_unique<chip::app::WriteClient>(device->GetExchangeManager(), &mChunkedWriteCallback,
                                                                    mTimedInteractionTimeoutMs, mSuppressResponse.ValueOr(false));
            VerifyOrReturnError(mWriteClient != nullptr, CHIP_ERROR_NO_MEMORY);

            for (uint8_t i = 0; i < pathsConfig.count; i++)
            {
                auto & path        = pathsConfig.attributePathParams[i];
                auto & dataVersion = pathsConfig.dataVersionFilter[i].mDataVersion;
                const T & value    = i >= values.size() ? values.at(0) : values.at(i);
                ReturnErrorOnFailure(EncodeAttribute<T>(path, dataVersion, value));
            }

            ReturnErrorOnFailure(mWriteClient->SendWriteRequest(device->GetSecureSession().Value()));

            if (mBusyWaitForMs.HasValue())
            {
                chip::test_utils::BusyWaitMillis(mBusyWaitForMs.Value());
            }

            if (mRepeatDelayInMs.HasValue())
            {
                chip::test_utils::SleepMillis(mRepeatDelayInMs.Value());
            }
        }

        return CHIP_NO_ERROR;
    }

    template <class T>
    CHIP_ERROR WriteAttribute(chip::DeviceProxy * device, std::vector<chip::EndpointId> endpointIds,
                              std::vector<chip::ClusterId> clusterIds, std::vector<chip::AttributeId> attributeIds, const T & value)
    {
        std::vector<T> values = { value };
        return WriteAttribute(device, endpointIds, clusterIds, attributeIds, values);
    }

    template <class T>
    CHIP_ERROR WriteGroupAttribute(chip::GroupId groupId, chip::FabricIndex fabricIndex, chip::ClusterId clusterId,
                                   chip::AttributeId attributeId, const std::vector<T> & value,
                                   const chip::Optional<chip::DataVersion> & dataVersion = chip::NullOptional)
    {
        return CHIP_ERROR_NOT_IMPLEMENTED;
    }

    template <class T>
    CHIP_ERROR WriteGroupAttribute(chip::GroupId groupId, chip::FabricIndex fabricIndex, chip::ClusterId clusterId,
                                   chip::AttributeId attributeId, const T & value,
                                   const chip::Optional<chip::DataVersion> & dataVersion = chip::NullOptional)
    {
        chip::app::AttributePathParams attributePathParams;

        if (clusterId != chip::kInvalidClusterId)
        {
            attributePathParams.mClusterId = clusterId;
        }

        if (attributeId != chip::kInvalidAttributeId)
        {
            attributePathParams.mAttributeId = attributeId;
        }

        chip::Messaging::ExchangeManager * exchangeManager = chip::app::InteractionModelEngine::GetInstance()->GetExchangeManager();
        VerifyOrReturnError(exchangeManager != nullptr, CHIP_ERROR_INCORRECT_STATE);

        chip::app::WriteClient writeClient(exchangeManager, &mChunkedWriteCallback, chip::NullOptional);
        ReturnErrorOnFailure(writeClient.EncodeAttribute(attributePathParams, value, dataVersion));

        chip::Transport::OutgoingGroupSession session(groupId, fabricIndex);
        return writeClient.SendWriteRequest(chip::SessionHandle(session));
    }

    void Shutdown() { mWriteClient.reset(); }

    std::unique_ptr<chip::app::WriteClient> mWriteClient;
    chip::app::ChunkedWriteCallback mChunkedWriteCallback;

    InteractionModelWriter & SetTimedInteractionTimeoutMs(uint16_t timedInteractionTimeoutMs)
    {
        mTimedInteractionTimeoutMs.SetValue(timedInteractionTimeoutMs);
        return *this;
    }

    InteractionModelWriter & SetTimedInteractionTimeoutMs(const chip::Optional<uint16_t> & timedInteractionTimeoutMs)
    {
        mTimedInteractionTimeoutMs = timedInteractionTimeoutMs;
        return *this;
    }

    InteractionModelWriter & SetSuppressResponse(bool suppressResponse)
    {
        mSuppressResponse.SetValue(suppressResponse);
        return *this;
    }

    InteractionModelWriter & SetSuppressResponse(const chip::Optional<bool> & suppressResponse)
    {
        mSuppressResponse = suppressResponse;
        return *this;
    }

    InteractionModelWriter & SetDataVersions(const std::vector<chip::DataVersion> & dataVersions)
    {
        mDataVersions.SetValue(dataVersions);
        return *this;
    }

    InteractionModelWriter & SetDataVersions(const chip::Optional<std::vector<chip::DataVersion>> & dataVersions)
    {
        mDataVersions = dataVersions;
        return *this;
    }

    InteractionModelWriter & SetRepeatCount(uint16_t repeatCount)
    {
        mRepeatCount.SetValue(repeatCount);
        return *this;
    }

    InteractionModelWriter & SetRepeatCount(const chip::Optional<uint16_t> & repeatCount)
    {
        mRepeatCount = repeatCount;
        return *this;
    }

    InteractionModelWriter & SetRepeatDelayInMs(uint16_t repeatDelayInMs)
    {
        mRepeatDelayInMs.SetValue(repeatDelayInMs);
        return *this;
    }

    InteractionModelWriter & SetRepeatDelayInMs(const chip::Optional<uint16_t> & repeatDelayInMs)
    {
        mRepeatDelayInMs = repeatDelayInMs;
        return *this;
    }

    InteractionModelWriter & SetBusyWaitForMs(uint16_t busyWaitForMs)
    {
        mBusyWaitForMs.SetValue(busyWaitForMs);
        return *this;
    }

    InteractionModelWriter & SetBusyWaitForMs(const chip::Optional<uint16_t> & busyWaitForMs)
    {
        mBusyWaitForMs = busyWaitForMs;
        return *this;
    }

    void ResetOptions()
    {
        mTimedInteractionTimeoutMs = chip::NullOptional;
        mSuppressResponse          = chip::NullOptional;
        mDataVersions              = chip::NullOptional;
        mRepeatCount               = chip::NullOptional;
        mRepeatDelayInMs           = chip::NullOptional;
        mBusyWaitForMs             = chip::NullOptional;
    }

    chip::Optional<uint16_t> mTimedInteractionTimeoutMs;
    chip::Optional<std::vector<chip::DataVersion>> mDataVersions;
    chip::Optional<bool> mSuppressResponse;
    chip::Optional<uint16_t> mRepeatCount;
    chip::Optional<uint16_t> mRepeatDelayInMs;
    chip::Optional<uint16_t> mBusyWaitForMs;

private:
    template <typename T>
    CHIP_ERROR EncodeAttribute(const chip::app::AttributePathParams & path, const chip::Optional<chip::DataVersion> & dataVersion,
                               T value, typename std::enable_if<!std::is_pointer<T>::value>::type * = 0)
    {
        return mWriteClient->EncodeAttribute(path, value, dataVersion);
    }

    template <typename T>
    CHIP_ERROR EncodeAttribute(const chip::app::AttributePathParams & path, const chip::Optional<chip::DataVersion> & dataVersion,
                               T value, typename std::enable_if<std::is_pointer<T>::value>::type * = 0)
    {
        return mWriteClient->EncodeAttribute(path, *value, dataVersion);
    }
};

class InteractionModel : public InteractionModelReports,
                         public InteractionModelCommands,
                         public InteractionModelWriter,
                         public chip::app::ReadClient::Callback,
                         public chip::app::WriteClient::Callback,
                         public chip::app::CommandSender::Callback
{
public:
    InteractionModel() : InteractionModelReports(this), InteractionModelCommands(this), InteractionModelWriter(this){};
    virtual ~InteractionModel(){};

    virtual void OnResponse(const chip::app::StatusIB & status, chip::TLV::TLVReader * data) = 0;
    virtual CHIP_ERROR ContinueOnChipMainThread(CHIP_ERROR err)                              = 0;
    virtual chip::DeviceProxy * GetDevice(const char * identity)                             = 0;

    CHIP_ERROR ReadAttribute(const char * identity, chip::EndpointId endpointId, chip::ClusterId clusterId,
                             chip::AttributeId attributeId, bool fabricFiltered = true,
                             const chip::Optional<chip::DataVersion> & dataVersion = chip::NullOptional);

    CHIP_ERROR SubscribeAttribute(const char * identity, chip::EndpointId endpointId, chip::ClusterId clusterId,
                                  chip::AttributeId attributeId, uint16_t minInterval, uint16_t maxInterval, bool fabricFiltered,
                                  const chip::Optional<chip::DataVersion> & dataVersion,
                                  const chip::Optional<bool> & keepSubscriptions, const chip::Optional<bool> & autoResubscribe);

    CHIP_ERROR ReadEvent(const char * identity, chip::EndpointId endpointId, chip::ClusterId clusterId, chip::EventId eventId,
                         bool fabricFiltered = true, const chip::Optional<chip::EventNumber> & eventNumber = chip::NullOptional);

    CHIP_ERROR SubscribeEvent(const char * identity, chip::EndpointId endpointId, chip::ClusterId clusterId, chip::EventId eventId,
                              uint16_t minInterval, uint16_t maxInterval, bool fabricFiltered,
                              const chip::Optional<chip::EventNumber> & eventNumber, const chip::Optional<bool> & keepSubscriptions,
                              const chip::Optional<bool> & autoResubscribe);

    CHIP_ERROR WaitForReport() { return CHIP_NO_ERROR; }

    template <class T>
    CHIP_ERROR WriteAttribute(const char * identity, chip::EndpointId endpointId, chip::ClusterId clusterId,
                              chip::AttributeId attributeId, const T & value,
                              const chip::Optional<uint16_t> & timedInteractionTimeoutMs = chip::NullOptional,
                              const chip::Optional<bool> & suppressResponse              = chip::NullOptional,
                              const chip::Optional<chip::DataVersion> & dataVersion      = chip::NullOptional)
    {
        chip::DeviceProxy * device = GetDevice(identity);
        VerifyOrReturnError(device != nullptr, CHIP_ERROR_INCORRECT_STATE);

        std::vector<chip::EndpointId> endpointIds   = { endpointId };
        std::vector<chip::ClusterId> clusterIds     = { clusterId };
        std::vector<chip::AttributeId> attributeIds = { attributeId };

        chip::Optional<std::vector<chip::DataVersion>> optionalDataVersions;
        if (dataVersion.HasValue())
        {
            std::vector<chip::DataVersion> dataVersions = { dataVersion.Value() };
            optionalDataVersions.SetValue(dataVersions);
        }

        InteractionModelWriter::ResetOptions();
        InteractionModelWriter::SetTimedInteractionTimeoutMs(timedInteractionTimeoutMs);
        InteractionModelWriter::SetSuppressResponse(suppressResponse);
        InteractionModelWriter::SetDataVersions(optionalDataVersions);

        return InteractionModelWriter::WriteAttribute(device, endpointIds, clusterIds, attributeIds, value);
    }

    template <class T>
    CHIP_ERROR WriteGroupAttribute(const char * identity, chip::GroupId groupId, chip::ClusterId clusterId,
                                   chip::AttributeId attributeId, const T & value,
                                   const chip::Optional<chip::DataVersion> & dataVersion = chip::NullOptional)
    {
        chip::DeviceProxy * device = GetDevice(identity);
        VerifyOrReturnError(device != nullptr, CHIP_ERROR_INCORRECT_STATE);

        chip::FabricIndex fabricIndex = device->GetSecureSession().Value()->GetFabricIndex();
        return InteractionModelWriter::WriteGroupAttribute(groupId, fabricIndex, clusterId, attributeId, value, dataVersion);
    }

    template <class T>
    CHIP_ERROR SendCommand(const char * identity, chip::EndpointId endpointId, chip::ClusterId clusterId, chip::CommandId commandId,
                           const T & value, chip::Optional<uint16_t> timedInteractionTimeoutMs = chip::NullOptional,
                           const chip::Optional<bool> & suppressResponse = chip::NullOptional)
    {
        chip::DeviceProxy * device = GetDevice(identity);
        VerifyOrReturnError(device != nullptr, CHIP_ERROR_INCORRECT_STATE);

        InteractionModelCommands::ResetOptions();
        InteractionModelCommands::SetTimedInteractionTimeoutMs(timedInteractionTimeoutMs);
        InteractionModelCommands::SetSuppressResponse(suppressResponse);

        return InteractionModelCommands::SendCommand(device, endpointId, clusterId, commandId, value);
    }

    template <class T>
    CHIP_ERROR SendGroupCommand(const char * identity, chip::GroupId groupId, chip::ClusterId clusterId, chip::CommandId commandId,
                                const T & value)
    {
        chip::DeviceProxy * device = GetDevice(identity);
        VerifyOrReturnError(device != nullptr, CHIP_ERROR_INCORRECT_STATE);

        chip::FabricIndex fabricIndex = device->GetSecureSession().Value()->GetFabricIndex();
        return InteractionModelCommands::SendGroupCommand(groupId, fabricIndex, clusterId, commandId, value);
    }

    void Shutdown();

    /////////// ReadClient Callback Interface /////////
    void OnAttributeData(const chip::app::ConcreteDataAttributePath & path, chip::TLV::TLVReader * data,
                         const chip::app::StatusIB & status) override;
    void OnEventData(const chip::app::EventHeader & eventHeader, chip::TLV::TLVReader * data,
                     const chip::app::StatusIB * status) override;
    void OnError(CHIP_ERROR error) override;
    void OnDone(chip::app::ReadClient * aReadClient) override;
    void OnSubscriptionEstablished(chip::SubscriptionId subscriptionId) override;
    void OnDeallocatePaths(chip::app::ReadPrepareParams && aReadPrepareParams) override;
    /////////// WriteClient Callback Interface /////////
    void OnResponse(const chip::app::WriteClient * client, const chip::app::ConcreteDataAttributePath & path,
                    chip::app::StatusIB status) override;
    void OnError(const chip::app::WriteClient * client, CHIP_ERROR error) override;
    void OnDone(chip::app::WriteClient * client) override;

    /////////// CommandSender Callback Interface /////////
    void OnResponse(chip::app::CommandSender * client, const chip::app::ConcreteCommandPath & path,
                    const chip::app::StatusIB & status, chip::TLV::TLVReader * data) override;
    void OnError(const chip::app::CommandSender * client, CHIP_ERROR error) override;
    void OnDone(chip::app::CommandSender * client) override;
};
