/*
 *    Copyright (c) 2022 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 <Foundation/Foundation.h>

#import "MTRBaseDevice.h"
#import "MTRCluster_internal.h"
#import "zap-generated/MTRCallbackBridge_internal.h"

#include <app/CommandSender.h>
#include <app/ReadClient.h>
#include <app/data-model/NullObject.h>
#include <lib/core/CHIPTLV.h>
#include <lib/core/DataModelTypes.h>
#include <lib/support/CHIPMem.h>

NS_ASSUME_NONNULL_BEGIN

/**
 * Utility functions base clusters use for doing reads and subscribes.
 */
template <typename BridgeType, typename DecodableAttributeType>
class MTRAttributeReportCallback : public chip::app::ReadClient::Callback {
public:
    MTRAttributeReportCallback(BridgeType * _Nonnull bridge, typename BridgeType::SuccessCallbackType _Nonnull onAttributeReport,
        MTRErrorCallback _Nonnull onError, chip::ClusterId clusterID, chip::AttributeId attributeID)
        : mBridge(bridge)
        , mOnAttributeReport(onAttributeReport)
        , mOnError(onError)
        , mClusterID(clusterID)
        , mAttributeID(attributeID)
        , mBufferedReadAdapter(*this)
    {
    }

    ~MTRAttributeReportCallback() {}

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

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

protected:
    void OnAttributeData(
        const chip::app::ConcreteDataAttributePath & path, chip::TLV::TLVReader * data, const chip::app::StatusIB & status) override
    {
        if (mCalledCallback && mReadClient->IsReadType()) {
            return;
        }
        mCalledCallback = true;

        CHIP_ERROR err = CHIP_NO_ERROR;
        DecodableAttributeType value;

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

        VerifyOrExit(status.IsSuccess(), err = status.ToChipError());
        VerifyOrExit(path.mClusterId == mClusterID && path.mAttributeId == mAttributeID, err = CHIP_ERROR_SCHEMA_MISMATCH);
        VerifyOrExit(data != nullptr, err = CHIP_ERROR_INVALID_ARGUMENT);

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

        mOnAttributeReport(mBridge, value);

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

    void OnError(CHIP_ERROR error) override
    {
        if (mCalledCallback && mReadClient->IsReadType()) {
            return;
        }
        mCalledCallback = true;

        mOnError(mBridge, error);
    }

    void OnDone(chip::app::ReadClient *) override { chip::Platform::Delete(this); }

    BridgeType * _Nonnull mBridge;

    chip::ClusterId mClusterID;
    chip::AttributeId mAttributeID;
    typename BridgeType::SuccessCallbackType mOnAttributeReport;
    MTRErrorCallback mOnError;
    chip::app::BufferedReadCallback mBufferedReadAdapter;
    chip::Platform::UniquePtr<chip::app::ReadClient> mReadClient;
    // For reads, we ensure that we make only one data/error callback to our consumer.
    bool mCalledCallback = false;
};

template <typename SubscriptionBridgeType, typename DecodableAttributeType>
class MTRAttributeSubscriptionCallback : public MTRAttributeReportCallback<SubscriptionBridgeType, DecodableAttributeType> {
public:
    MTRAttributeSubscriptionCallback(SubscriptionBridgeType * _Nonnull bridge,
        typename SubscriptionBridgeType::SuccessCallbackType onAttributeReport, MTRErrorCallback onError, chip::ClusterId clusterID,
        chip::AttributeId attributeID)
        : MTRAttributeReportCallback<SubscriptionBridgeType, DecodableAttributeType>(
            bridge, onAttributeReport, onError, clusterID, attributeID)
    {
    }

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

private:
    // The superclass OnResubscriptionNeeded is fine for our purposes.

    void OnDeallocatePaths(chip::app::ReadPrepareParams && readPrepareParams) override
    {
        VerifyOrDie(readPrepareParams.mAttributePathParamsListSize == 1 && readPrepareParams.mpAttributePathParamsList != nullptr);
        chip::Platform::Delete<chip::app::AttributePathParams>(readPrepareParams.mpAttributePathParamsList);

        if (readPrepareParams.mDataVersionFilterListSize == 1 && readPrepareParams.mpDataVersionFilterList != nullptr) {
            chip::Platform::Delete<chip::app::DataVersionFilter>(readPrepareParams.mpDataVersionFilterList);
        }
    }

    void OnSubscriptionEstablished(chip::SubscriptionId subscriptionId) override { this->mBridge->OnSubscriptionEstablished(); }

    void OnDone(chip::app::ReadClient * readClient) override
    {
        this->mBridge->OnDone();
        MTRAttributeReportCallback<SubscriptionBridgeType, DecodableAttributeType>::OnDone(readClient);
    }
};

template <typename DecodableAttributeType, typename BridgeType>
CHIP_ERROR MTRStartReadInteraction(BridgeType * _Nonnull bridge, MTRReadParams * params,
    chip::Messaging::ExchangeManager & exchangeManager, const chip::SessionHandle & session,
    typename BridgeType::SuccessCallbackType successCb, MTRErrorCallback failureCb, chip::EndpointId endpoint,
    chip::ClusterId clusterID, chip::AttributeId attributeID)
{
    auto readPaths = chip::Platform::MakeUnique<chip::app::AttributePathParams>(endpoint, clusterID, attributeID);
    VerifyOrReturnError(readPaths != nullptr, CHIP_ERROR_NO_MEMORY);

    chip::app::ReadPrepareParams readPrepareParams(session);
    [params toReadPrepareParams:readPrepareParams];
    readPrepareParams.mpAttributePathParamsList = readPaths.get();
    readPrepareParams.mAttributePathParamsListSize = 1;

    auto callback = chip::Platform::MakeUnique<MTRAttributeReportCallback<BridgeType, DecodableAttributeType>>(
        bridge, successCb, failureCb, clusterID, attributeID);
    VerifyOrReturnError(callback != nullptr, CHIP_ERROR_NO_MEMORY);

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

    CHIP_ERROR err = readClient->SendRequest(readPrepareParams);
    ReturnErrorOnFailure(err);

    callback->AdoptReadClient(std::move(readClient));
    callback.release();

    return CHIP_NO_ERROR;
}

template <typename DecodableAttributeType, typename BridgeType>
CHIP_ERROR MTRStartSubscribeInteraction(BridgeType * _Nonnull bridge, MTRSubscribeParams * params,
    chip::Messaging::ExchangeManager & exchangeManager, const chip::SessionHandle & session,
    typename BridgeType::SuccessCallbackType successCb, MTRErrorCallback failureCb, chip::EndpointId endpoint,
    chip::ClusterId clusterID, chip::AttributeId attributeID)
{
    auto readPaths = chip::Platform::MakeUnique<chip::app::AttributePathParams>(endpoint, clusterID, attributeID);
    VerifyOrReturnError(readPaths != nullptr, CHIP_ERROR_NO_MEMORY);

    chip::app::ReadPrepareParams readPrepareParams(session);
    [params toReadPrepareParams:readPrepareParams];
    readPrepareParams.mpAttributePathParamsList = readPaths.get();
    readPrepareParams.mAttributePathParamsListSize = 1;

    auto callback = chip::Platform::MakeUnique<MTRAttributeSubscriptionCallback<BridgeType, DecodableAttributeType>>(
        bridge, successCb, failureCb, clusterID, attributeID);
    VerifyOrReturnError(callback != nullptr, CHIP_ERROR_NO_MEMORY);

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

    CHIP_ERROR err;
    if (params.resubscribeIfLost) {
        readPaths.release();

        err = readClient->SendAutoResubscribeRequest(std::move(readPrepareParams));
    } else {
        err = readClient->SendRequest(readPrepareParams);
    }
    ReturnErrorOnFailure(err);

    bridge->KeepAliveOnCallback();

    callback->AdoptReadClient(std::move(readClient));
    callback.release();

    return CHIP_NO_ERROR;
}

template <typename SubscriptionBridgeType, typename AttributeObjCType, typename DecodableAttributeType>
void MTRSubscribeAttribute(MTRSubscribeParams * _Nonnull params,
    MTRSubscriptionEstablishedHandler _Nullable subscriptionEstablished,
    void (^reportHandler)(AttributeObjCType * _Nullable value, NSError * _Nullable error), dispatch_queue_t callbackQueue,
    MTRBaseDevice * device, chip::EndpointId endpoint, chip::ClusterId clusterID, chip::AttributeId attributeID)
{
    // Make a copy of params before we go async.
    params = [params copy];
    auto * callbackBridge = new SubscriptionBridgeType(
        callbackQueue,
        // This treats reportHandler as taking an id for the data.  This is
        // not great from a type-safety perspective, of course.
        reportHandler,
        ^(chip::Messaging::ExchangeManager & exchangeManager, const chip::SessionHandle & session,
            typename SubscriptionBridgeType::SuccessCallbackType successCb, MTRErrorCallback failureCb,
            MTRCallbackBridgeBase * bridge) {
            auto * subscriptionBridge = static_cast<SubscriptionBridgeType *>(bridge);
            return MTRStartSubscribeInteraction<DecodableAttributeType>(
                subscriptionBridge, params, exchangeManager, session, successCb, failureCb, endpoint, clusterID, attributeID);
        },
        subscriptionEstablished);
    std::move(*callbackBridge).DispatchAction(device);
}

template <typename ReadBridgeType, typename AttributeObjCType, typename DecodableAttributeType>
void MTRReadAttribute(MTRReadParams * _Nonnull params,
    void (^reportHandler)(AttributeObjCType * _Nullable value, NSError * _Nullable error), dispatch_queue_t callbackQueue,
    MTRBaseDevice * device, chip::EndpointId endpoint, chip::ClusterId clusterID, chip::AttributeId attributeID)
{
    // Make a copy of params before we go async.
    params = [params copy];
    auto * callbackBridge = new ReadBridgeType(callbackQueue,
        // This treats reportHandler as taking an id for the data.  This is
        // not great from a type-safety perspective, of course.
        reportHandler,
        ^(chip::Messaging::ExchangeManager & exchangeManager, const chip::SessionHandle & session,
            typename ReadBridgeType::SuccessCallbackType successCb, MTRErrorCallback failureCb, MTRCallbackBridgeBase * bridge) {
            auto * readBridge = static_cast<ReadBridgeType *>(bridge);
            return MTRStartReadInteraction<DecodableAttributeType>(
                readBridge, params, exchangeManager, session, successCb, failureCb, endpoint, clusterID, attributeID);
        });
    std::move(*callbackBridge).DispatchAction(device);
}

/**
 * Utility functions base clusters use for doing commands.
 */
template <typename InvokeBridgeType, typename ResponseType> class MTRInvokeCallback : public chip::app::CommandSender::Callback {
public:
    MTRInvokeCallback(InvokeBridgeType * _Nonnull bridge, typename InvokeBridgeType::SuccessCallbackType _Nonnull onResponse,
        MTRErrorCallback _Nonnull onError)
        : mBridge(bridge)
        , mOnResponse(onResponse)
        , mOnError(onError)
    {
    }

    ~MTRInvokeCallback() {}

    void AdoptCommandSender(chip::Platform::UniquePtr<chip::app::CommandSender> commandSender)
    {
        mCommandSender = std::move(commandSender);
    }

protected:
    // We need to have different OnResponse implementations depending on whether
    // ResponseType is DataModel::NullObjectType or not.  Since template class methods
    // can't be partially specialized (either you have to partially specialize
    // the class template, or you have to fully specialize the method), use
    // enable_if to deal with this.
    void OnResponse(chip::app::CommandSender * commandSender, const chip::app::ConcreteCommandPath & commandPath,
        const chip::app::StatusIB & status, chip::TLV::TLVReader * reader) override
    {
        HandleResponse(commandSender, commandPath, status, reader);
    }

    /**
     * Response handler for data responses.
     */
    template <typename T = ResponseType, std::enable_if_t<!std::is_same<T, chip::app::DataModel::NullObjectType>::value, int> = 0>
    void HandleResponse(chip::app::CommandSender * commandSender, const chip::app::ConcreteCommandPath & commandPath,
        const chip::app::StatusIB & status, chip::TLV::TLVReader * reader)
    {
        if (mCalledCallback) {
            return;
        }
        mCalledCallback = true;

        ResponseType response;
        CHIP_ERROR err = CHIP_NO_ERROR;

        //
        // We're expecting response data in this variant of OnResponse. Consequently, reader should always be
        // non-null. If it is, it means we received a success status code instead, which is not what was expected.
        //
        VerifyOrExit(reader != nullptr, err = CHIP_ERROR_SCHEMA_MISMATCH);

        //
        // Validate that the data response we received matches what we expect in terms of its cluster and command IDs.
        //
        VerifyOrExit(
            commandPath.mClusterId == ResponseType::GetClusterId() && commandPath.mCommandId == ResponseType::GetCommandId(),
            err = CHIP_ERROR_SCHEMA_MISMATCH);

        err = chip::app::DataModel::Decode(*reader, response);
        SuccessOrExit(err);

        mOnResponse(mBridge, response);

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

    /**
     * Response handler for status responses.
     */
    template <typename T = ResponseType, std::enable_if_t<std::is_same<T, chip::app::DataModel::NullObjectType>::value, int> = 0>
    void HandleResponse(chip::app::CommandSender * commandSender, const chip::app::ConcreteCommandPath & commandPath,
        const chip::app::StatusIB & status, chip::TLV::TLVReader * reader)
    {
        if (mCalledCallback) {
            return;
        }
        mCalledCallback = true;

        //
        // If we got a valid reader, it means we received response data that we were not expecting to receive.
        //
        if (reader != nullptr) {
            mOnError(mBridge, CHIP_ERROR_SCHEMA_MISMATCH);
            return;
        }

        chip::app::DataModel::NullObjectType nullResp;
        mOnResponse(mBridge, nullResp);
    }

    void OnError(const chip::app::CommandSender * commandSender, CHIP_ERROR error) override
    {
        if (mCalledCallback) {
            return;
        }
        mCalledCallback = true;

        mOnError(mBridge, error);
    }

    void OnDone(chip::app::CommandSender * commandSender) override { chip::Platform::Delete(this); }

    InvokeBridgeType * _Nonnull mBridge;

    typename InvokeBridgeType::SuccessCallbackType mOnResponse;
    MTRErrorCallback mOnError;
    chip::Platform::UniquePtr<chip::app::CommandSender> mCommandSender;
    // For reads, we ensure that we make only one data/error callback to our consumer.
    bool mCalledCallback = false;
};

template <typename BridgeType, typename RequestDataType>
CHIP_ERROR MTRStartInvokeInteraction(BridgeType * _Nonnull bridge, const RequestDataType & requestData,
    chip::Messaging::ExchangeManager & exchangeManager, const chip::SessionHandle & session,
    typename BridgeType::SuccessCallbackType successCb, MTRErrorCallback failureCb, chip::EndpointId endpoint,
    chip::Optional<uint16_t> timedInvokeTimeoutMs)
{
    auto callback = chip::Platform::MakeUnique<MTRInvokeCallback<BridgeType, typename RequestDataType::ResponseType>>(
        bridge, successCb, failureCb);
    VerifyOrReturnError(callback != nullptr, CHIP_ERROR_NO_MEMORY);

    auto commandSender
        = chip::Platform::MakeUnique<chip::app::CommandSender>(callback.get(), &exchangeManager, timedInvokeTimeoutMs.HasValue());
    VerifyOrReturnError(commandSender != nullptr, CHIP_ERROR_NO_MEMORY);

    chip::app::CommandPathParams commandPath(endpoint, 0, RequestDataType::GetClusterId(), RequestDataType::GetCommandId(),
        chip::app::CommandPathFlags::kEndpointIdValid);
    ReturnErrorOnFailure(commandSender->AddRequestData(commandPath, requestData, timedInvokeTimeoutMs));
    ReturnErrorOnFailure(commandSender->SendCommandRequest(session));

    callback->AdoptCommandSender(std::move(commandSender));
    callback.release();

    return CHIP_NO_ERROR;
};

NS_ASSUME_NONNULL_END
