/*
 *
 *    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.
 */
#include "AndroidCallbacks.h"
#include <controller/java/AndroidConnectionFailureExceptions.h>
#include <controller/java/AndroidControllerExceptions.h>
#ifdef USE_JAVA_TLV_ENCODE_DECODE
#include <controller/java/CHIPAttributeTLVValueDecoder.h>
#include <controller/java/CHIPEventTLVValueDecoder.h>
#endif
#include <app/EventLoggingTypes.h>
#include <jni.h>
#include <lib/core/ErrorStr.h>
#include <lib/support/CHIPJNIError.h>
#include <lib/support/CodeUtils.h>
#include <lib/support/JniReferences.h>
#include <lib/support/jsontlv/JsonToTlv.h>
#include <lib/support/jsontlv/TlvToJson.h>
#include <lib/support/logging/CHIPLogging.h>
#include <platform/PlatformManager.h>
#include <string>
#include <type_traits>

namespace chip {
namespace Controller {

static const int MILLIS_SINCE_BOOT  = 0;
static const int MILLIS_SINCE_EPOCH = 1;
// Add the bytes for attribute tag(1:control + 8:tag + 8:length) and structure(1:struct + 1:close container)
static const int EXTRA_SPACE_FOR_ATTRIBUTE_TAG = 19;

jobject DecodeGeneralTLVValue(JNIEnv * env, TLV::TLVReader & readerForGeneralValueObject, CHIP_ERROR & err);

GetConnectedDeviceCallback::GetConnectedDeviceCallback(jobject wrapperCallback, jobject javaCallback,
                                                       const char * callbackClassSignature) :
    mOnSuccess(OnDeviceConnectedFn, this),
    mOnFailure(OnDeviceConnectionFailureFn, this), mCallbackClassSignature(callbackClassSignature)
{
    VerifyOrReturn(mWrapperCallbackRef.Init(wrapperCallback) == CHIP_NO_ERROR,
                   ChipLogError(Controller, "Could not init mWrapperCallbackRef in %s", __func__));
    VerifyOrReturn(mJavaCallbackRef.Init(javaCallback) == CHIP_NO_ERROR,
                   ChipLogError(Controller, "Could not init mJavaCallbackRef in %s", __func__));
}

GetConnectedDeviceCallback::~GetConnectedDeviceCallback() {}

void GetConnectedDeviceCallback::OnDeviceConnectedFn(void * context, Messaging::ExchangeManager & exchangeMgr,
                                                     const SessionHandle & sessionHandle)
{
    JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread();
    VerifyOrReturn(env != nullptr, ChipLogError(Controller, "Could not get JNIEnv for current thread"));
    auto * self = static_cast<GetConnectedDeviceCallback *>(context);
    VerifyOrReturn(self->mJavaCallbackRef.HasValidObjectRef(),
                   ChipLogError(Controller, "mJavaCallbackRef is not valid in %s", __func__));
    jobject javaCallback = self->mJavaCallbackRef.ObjectRef();
    JniLocalReferenceScope scope(env);
    // Release wrapper's global ref so application can clean up the actual callback underneath.
    VerifyOrReturn(self->mWrapperCallbackRef.HasValidObjectRef(),
                   ChipLogError(Controller, "mWrapperCallbackRef is not valid in %s", __func__));
    JniGlobalReference globalRef(std::move(self->mWrapperCallbackRef));

    jclass getConnectedDeviceCallbackCls = nullptr;
    CHIP_ERROR err =
        JniReferences::GetInstance().GetLocalClassRef(env, self->mCallbackClassSignature, getConnectedDeviceCallbackCls);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Controller, "GetLocalClassRef Error! : %" CHIP_ERROR_FORMAT, err.Format()));
    VerifyOrReturn(getConnectedDeviceCallbackCls != nullptr,
                   ChipLogError(Controller, "Could not find GetConnectedDeviceCallback class"));

    jmethodID successMethod;
    err = JniReferences::GetInstance().FindMethod(env, javaCallback, "onDeviceConnected", "(J)V", &successMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Controller, "FindMethod Error! : %" CHIP_ERROR_FORMAT, err.Format()));
    VerifyOrReturn(successMethod != nullptr, ChipLogError(Controller, "Could not find onDeviceConnected method"));

    static_assert(sizeof(jlong) >= sizeof(void *), "Need to store a pointer in a Java handle");

    OperationalDeviceProxy * device = new OperationalDeviceProxy(&exchangeMgr, sessionHandle);
    DeviceLayer::StackUnlock unlock;
    env->CallVoidMethod(javaCallback, successMethod, reinterpret_cast<jlong>(device));
    VerifyOrReturn(!env->ExceptionCheck(), env->ExceptionDescribe());
}

void GetConnectedDeviceCallback::OnDeviceConnectionFailureFn(void * context,
                                                             const OperationalSessionSetup::ConnectionFailureInfo & failureInfo)
{
    JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread();
    VerifyOrReturn(env != nullptr, ChipLogError(Controller, "Could not get JNIEnv for current thread"));
    auto * self = static_cast<GetConnectedDeviceCallback *>(context);
    VerifyOrReturn(self->mJavaCallbackRef.HasValidObjectRef(),
                   ChipLogError(Controller, "mJavaCallbackRef is not valid in %s", __func__));
    jobject javaCallback = self->mJavaCallbackRef.ObjectRef();
    JniLocalReferenceScope scope(env);

    jclass getConnectedDeviceCallbackCls = nullptr;
    CHIP_ERROR err =
        JniReferences::GetInstance().GetLocalClassRef(env, self->mCallbackClassSignature, getConnectedDeviceCallbackCls);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Controller, "GetLocalClassRef Error! : %" CHIP_ERROR_FORMAT, err.Format()));
    VerifyOrReturn(getConnectedDeviceCallbackCls != nullptr,
                   ChipLogError(Controller, "Could not find GetConnectedDeviceCallback class"));

    jmethodID failureMethod;
    err = JniReferences::GetInstance().FindMethod(env, javaCallback, "onConnectionFailure", "(JLjava/lang/Exception;)V",
                                                  &failureMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Controller, "FindMethod Error! : %" CHIP_ERROR_FORMAT, err.Format()));
    VerifyOrReturn(failureMethod != nullptr, ChipLogError(Controller, "Could not find onConnectionFailure method"));

    jthrowable exception;
    err = AndroidConnectionFailureExceptions::GetInstance().CreateAndroidConnectionFailureException(
        env, failureInfo.error.Format(), failureInfo.error.AsInteger(), failureInfo.sessionStage, exception);
    VerifyOrReturn(err == CHIP_NO_ERROR,
                   ChipLogError(Controller,
                                "Unable to create AndroidControllerException on "
                                "GetConnectedDeviceCallback::OnDeviceConnectionFailureFn: %" CHIP_ERROR_FORMAT,
                                err.Format()));
    DeviceLayer::StackUnlock unlock;
    env->CallVoidMethod(javaCallback, failureMethod, failureInfo.peerId.GetNodeId(), exception);
    VerifyOrReturn(!env->ExceptionCheck(), env->ExceptionDescribe());
}

CHIP_ERROR CreateOptional(chip::Optional<uint8_t> value, jobject & outObj)
{

    return CHIP_NO_ERROR;
}
jobject GetNodeStateObj(JNIEnv * env, const char * nodeStateClassSignature, jobject wrapperCallback)
{
    jmethodID getNodeStateMethod;
    CHIP_ERROR err =
        JniReferences::GetInstance().FindMethod(env, wrapperCallback, "getNodeState", nodeStateClassSignature, &getNodeStateMethod);
    VerifyOrReturnValue(err == CHIP_NO_ERROR, nullptr, ChipLogError(Controller, "Could not find getNodeState method"));

    jobject ret = env->CallObjectMethod(wrapperCallback, getNodeStateMethod);
    VerifyOrReturnValue(!env->ExceptionCheck(), nullptr, env->ExceptionDescribe());

    return ret;
}

ReportCallback::ReportCallback(jobject wrapperCallback, jobject subscriptionEstablishedCallback,
                               jobject resubscriptionAttemptCallback, const char * nodeStateClassSignature) :
    mClusterCacheAdapter(*this, Optional<EventNumber>::Missing(), false /*cacheData*/),
    mNodeStateClassSignature(nodeStateClassSignature)
{
    JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread();
    VerifyOrReturn(env != nullptr, ChipLogError(Controller, "Could not get JNIEnv for current thread"));
    if (subscriptionEstablishedCallback != nullptr)
    {
        VerifyOrReturn(mSubscriptionEstablishedCallbackRef.Init(subscriptionEstablishedCallback) == CHIP_NO_ERROR,
                       ChipLogError(Controller, "Could not init mSubscriptionEstablishedCallbackRef in %s", __func__));
    }

    VerifyOrReturn(mWrapperCallbackRef.Init(wrapperCallback) == CHIP_NO_ERROR,
                   ChipLogError(Controller, "Could not init mWrapperCallbackRef in %s", __func__));

    if (resubscriptionAttemptCallback != nullptr)
    {
        VerifyOrReturn(mResubscriptionAttemptCallbackRef.Init(resubscriptionAttemptCallback) == CHIP_NO_ERROR,
                       ChipLogError(Controller, "Could not init mResubscriptionAttemptCallbackRef in %s", __func__));
    }
}

ReportCallback::~ReportCallback()
{
    if (mReadClient != nullptr)
    {
        Platform::Delete(mReadClient);
    }
}

void ReportCallback::OnReportBegin()
{
    JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread();
    VerifyOrReturn(env != nullptr, ChipLogError(Controller, "Could not get JNIEnv for current thread"));

    JniLocalReferenceScope scope(env);

    VerifyOrReturn(mWrapperCallbackRef.HasValidObjectRef(),
                   ChipLogError(Controller, "mReportCallbackRef is not valid in %s", __func__));
    jobject wrapperCallback = mWrapperCallbackRef.ObjectRef();
    jmethodID onReportBeginMethod;
    CHIP_ERROR err = JniReferences::GetInstance().FindMethod(env, wrapperCallback, "onReportBegin", "()V", &onReportBeginMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Controller, "Could not find onReportBegin method"));

    DeviceLayer::StackUnlock unlock;
    env->CallVoidMethod(wrapperCallback, onReportBeginMethod);
    VerifyOrReturn(!env->ExceptionCheck(), env->ExceptionDescribe());
}

void ReportCallback::OnDeallocatePaths(app::ReadPrepareParams && aReadPrepareParams)
{
    if (aReadPrepareParams.mpAttributePathParamsList != nullptr && aReadPrepareParams.mAttributePathParamsListSize != 0)
    {
        delete[] aReadPrepareParams.mpAttributePathParamsList;
        aReadPrepareParams.mpAttributePathParamsList    = nullptr;
        aReadPrepareParams.mAttributePathParamsListSize = 0;
    }

    if (aReadPrepareParams.mpEventPathParamsList != nullptr && aReadPrepareParams.mEventPathParamsListSize != 0)
    {
        delete[] aReadPrepareParams.mpEventPathParamsList;
        aReadPrepareParams.mpEventPathParamsList    = nullptr;
        aReadPrepareParams.mEventPathParamsListSize = 0;
    }

    if (aReadPrepareParams.mpDataVersionFilterList != nullptr && aReadPrepareParams.mDataVersionFilterListSize != 0)
    {
        delete[] aReadPrepareParams.mpDataVersionFilterList;
        aReadPrepareParams.mpDataVersionFilterList    = nullptr;
        aReadPrepareParams.mDataVersionFilterListSize = 0;
    }
}

void ReportCallback::OnReportEnd()
{
    UpdateClusterDataVersion();

    // Transform C++ jobject pair list to a Java HashMap, and call onReport() on the Java callback.
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = JniReferences::GetInstance().GetEnvForCurrentThread();
    VerifyOrReturn(env != nullptr, ChipLogError(Controller, "Could not get JNIEnv for current thread"));

    JniLocalReferenceScope scope(env);
    VerifyOrReturn(mWrapperCallbackRef.HasValidObjectRef(),
                   ChipLogError(Controller, "mWrapperCallbackRef is not valid in %s", __func__));
    jobject wrapperCallback = mWrapperCallbackRef.ObjectRef();
    jmethodID onReportEndMethod;
    err = JniReferences::GetInstance().FindMethod(env, wrapperCallback, "onReportEnd", "()V", &onReportEndMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Controller, "Could not find onReportEnd method"));

    DeviceLayer::StackUnlock unlock;
    env->CallVoidMethod(wrapperCallback, onReportEndMethod);
    VerifyOrReturn(!env->ExceptionCheck(), env->ExceptionDescribe());
}

// Convert TLV blob to Json with structure, the element's tag is replaced with the actual attributeId.
CHIP_ERROR ConvertReportTlvToJson(const uint32_t id, TLV::TLVReader & data, std::string & json)
{
    TLV::TLVWriter writer;
    TLV::TLVReader readerForJavaTLV;
    uint32_t size = 0;
    readerForJavaTLV.Init(data);
    size_t bufferLen                  = readerForJavaTLV.GetTotalLength() + EXTRA_SPACE_FOR_ATTRIBUTE_TAG;
    std::unique_ptr<uint8_t[]> buffer = std::unique_ptr<uint8_t[]>(new uint8_t[bufferLen]);
    writer.Init(buffer.get(), bufferLen);
    TLV::TLVType outer;

    ReturnErrorOnFailure(writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, outer));
    TLV::Tag tag;
    ReturnErrorOnFailure(ConvertTlvTag(id, tag));
    ReturnErrorOnFailure(writer.CopyElement(tag, readerForJavaTLV));
    ReturnErrorOnFailure(writer.EndContainer(outer));
    size = writer.GetLengthWritten();

    TLV::TLVReader readerForJson;
    readerForJson.Init(buffer.get(), size);
    ReturnErrorOnFailure(readerForJson.Next());
    // Convert TLV to JSON
    return TlvToJson(readerForJson, json);
}

void ReportCallback::OnAttributeData(const app::ConcreteDataAttributePath & aPath, TLV::TLVReader * apData,
                                     const app::StatusIB & aStatus)
{
    DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = JniReferences::GetInstance().GetEnvForCurrentThread();
    VerifyOrReturn(env != nullptr, ChipLogError(Controller, "Could not get JNIEnv for current thread"));
    JniLocalReferenceScope scope(env);
    VerifyOrReturn(!aPath.IsListItemOperation(), ChipLogError(Controller, "Expect non-list item operation"); aPath.LogPath());

    VerifyOrReturn(mWrapperCallbackRef.HasValidObjectRef(),
                   ChipLogError(Controller, "mReportCallbackRef is not valid in %s", __func__));
    jobject wrapperCallback = mWrapperCallbackRef.ObjectRef();

    jobject nodeState = GetNodeStateObj(env, mNodeStateClassSignature, wrapperCallback);

    {
        // Add Attribute Status to wrapperCallback
        jmethodID addAttributeStatusMethod = nullptr;
        err = JniReferences::GetInstance().FindMethod(env, nodeState, "addAttributeStatus", "(IJJILjava/lang/Integer;)V",
                                                      &addAttributeStatusMethod);
        VerifyOrReturn(
            err == CHIP_NO_ERROR,
            ChipLogError(Controller, "Could not find addAttributeStatus method with error %" CHIP_ERROR_FORMAT, err.Format()));

        jobject jClusterState = nullptr;
        if (aStatus.mClusterStatus.has_value())
        {
            err = JniReferences::GetInstance().CreateBoxedObject<jint>("java/lang/Integer", "(I)V",
                                                                       static_cast<jint>(*aStatus.mClusterStatus), jClusterState);
            VerifyOrReturn(err == CHIP_NO_ERROR,
                           ChipLogError(Controller, "Could not CreateBoxedObject with error %" CHIP_ERROR_FORMAT, err.Format()));
        }

        env->CallVoidMethod(nodeState, addAttributeStatusMethod, static_cast<jint>(aPath.mEndpointId),
                            static_cast<jlong>(aPath.mClusterId), static_cast<jlong>(aPath.mAttributeId),
                            static_cast<jint>(aStatus.mStatus), jClusterState);
        VerifyOrReturn(!env->ExceptionCheck(), env->ExceptionDescribe());
    }

    VerifyOrReturn(aStatus.IsSuccess(),
                   ChipLogError(Controller, "Receive bad status %" CHIP_ERROR_FORMAT, aStatus.ToChipError().Format());
                   aPath.LogPath());
    VerifyOrReturn(apData != nullptr, ChipLogError(Controller, "Receive empty apData"); aPath.LogPath());

    TLV::TLVReader readerForJavaTLV;
    readerForJavaTLV.Init(*apData);

    jobject value = nullptr;
    TLV::TLVReader readerForJavaObject;
    readerForJavaObject.Init(*apData);
#ifdef USE_JAVA_TLV_ENCODE_DECODE
    value = DecodeAttributeValue(aPath, readerForJavaObject, &err);
    // If we don't know this attribute, suppress it.
    if (err == CHIP_ERROR_IM_MALFORMED_ATTRIBUTE_PATH_IB)
    {
        TLV::TLVReader readerForGeneralValueObject;
        readerForGeneralValueObject.Init(*apData);
        value = DecodeGeneralTLVValue(env, readerForGeneralValueObject, err);
        err   = CHIP_NO_ERROR;
    }

    VerifyOrReturn(err == CHIP_NO_ERROR,
                   ChipLogError(Controller, "Fail to decode attribute with error %" CHIP_ERROR_FORMAT, err.Format());
                   aPath.LogPath());
    VerifyOrReturn(!env->ExceptionCheck(), env->ExceptionDescribe());
#else
    value = DecodeGeneralTLVValue(env, readerForJavaObject, err);
#endif
    // Create TLV byte array to pass to Java layer
    size_t bufferLen                  = readerForJavaTLV.GetRemainingLength() + readerForJavaTLV.GetLengthRead();
    std::unique_ptr<uint8_t[]> buffer = std::unique_ptr<uint8_t[]>(new uint8_t[bufferLen]);
    uint32_t size                     = 0;

    // The TLVReader's read head is not pointing to the first element in the container, instead of the container itself, use
    // a TLVWriter to get a TLV with a normalized TLV buffer (Wrapped with an anonymous tag, no extra "end of container" tag
    // at the end.)
    TLV::TLVWriter writer;
    writer.Init(buffer.get(), bufferLen);
    err = writer.CopyElement(TLV::AnonymousTag(), readerForJavaTLV);
    VerifyOrReturn(err == CHIP_NO_ERROR,
                   ChipLogError(Controller, "Fail to copy tlv element with error %" CHIP_ERROR_FORMAT, err.Format());
                   aPath.LogPath());
    size = writer.GetLengthWritten();
    chip::ByteArray jniByteArray(env, reinterpret_cast<jbyte *>(buffer.get()), static_cast<jint>(size));

    // Convert TLV to JSON
    std::string json;
    err = ConvertReportTlvToJson(static_cast<uint32_t>(aPath.mAttributeId), *apData, json);
    VerifyOrReturn(err == CHIP_NO_ERROR,
                   ChipLogError(Controller, "Fail to convert report tlv to json with error %" CHIP_ERROR_FORMAT, err.Format());
                   aPath.LogPath());
    UtfString jsonString(env, json.c_str());

    // Add AttributeState to wrapperCallback
    jmethodID addAttributeMethod;
    err = JniReferences::GetInstance().FindMethod(env, nodeState, "addAttribute", "(IJJLjava/lang/Object;[BLjava/lang/String;)V",
                                                  &addAttributeMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR,
                   ChipLogError(Controller, "Could not find addAttribute method with error %" CHIP_ERROR_FORMAT, err.Format()));
    env->CallVoidMethod(nodeState, addAttributeMethod, static_cast<jint>(aPath.mEndpointId), static_cast<jlong>(aPath.mClusterId),
                        static_cast<jlong>(aPath.mAttributeId), value, jniByteArray.jniValue(), jsonString.jniValue());
    VerifyOrReturn(!env->ExceptionCheck(), env->ExceptionDescribe());

    UpdateClusterDataVersion();
}

void ReportCallback::UpdateClusterDataVersion()
{
    JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread();
    VerifyOrReturn(env != nullptr, ChipLogError(Controller, "Could not get JNIEnv for current thread"));
    chip::app::ConcreteClusterPath lastConcreteClusterPath;

    if (mClusterCacheAdapter.GetLastReportDataPath(lastConcreteClusterPath) != CHIP_NO_ERROR)
    {
        return;
    }

    if (!lastConcreteClusterPath.IsValidConcreteClusterPath())
    {
        return;
    }

    chip::Optional<chip::DataVersion> committedDataVersion;
    if (mClusterCacheAdapter.GetVersion(lastConcreteClusterPath, committedDataVersion) != CHIP_NO_ERROR)
    {
        return;
    }
    if (!committedDataVersion.HasValue())
    {
        return;
    }

    VerifyOrReturn(mWrapperCallbackRef.HasValidObjectRef(),
                   ChipLogError(Controller, "mReportCallbackRef is not valid in %s", __func__));
    jobject wrapperCallback = mWrapperCallbackRef.ObjectRef();
    jobject nodeState       = GetNodeStateObj(env, mNodeStateClassSignature, wrapperCallback);

    // SetDataVersion to NodeState
    jmethodID setDataVersionMethod;
    CHIP_ERROR err = JniReferences::GetInstance().FindMethod(env, nodeState, "setDataVersion", "(IJJ)V", &setDataVersionMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Controller, "Could not find setDataVersion method"));
    env->CallVoidMethod(nodeState, setDataVersionMethod, static_cast<jint>(lastConcreteClusterPath.mEndpointId),
                        static_cast<jlong>(lastConcreteClusterPath.mClusterId), static_cast<jlong>(committedDataVersion.Value()));
    VerifyOrReturn(!env->ExceptionCheck(), env->ExceptionDescribe());
}

void ReportCallback::OnEventData(const app::EventHeader & aEventHeader, TLV::TLVReader * apData, const app::StatusIB * apStatus)
{
    DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = JniReferences::GetInstance().GetEnvForCurrentThread();
    VerifyOrReturn(env != nullptr, ChipLogError(Controller, "Could not get JNIEnv for current thread"));

    VerifyOrReturn(mWrapperCallbackRef.HasValidObjectRef(),
                   ChipLogError(Controller, "mReportCallbackRef is not valid in %s", __func__));
    jobject wrapperCallback = mWrapperCallbackRef.ObjectRef();
    jobject nodeState       = GetNodeStateObj(env, mNodeStateClassSignature, wrapperCallback);
    if (apStatus != nullptr)
    {
        // Add Event Status to NodeState
        jmethodID addEventStatusMethod;
        err = JniReferences::GetInstance().FindMethod(env, nodeState, "addEventStatus", "(IJJILjava/lang/Integer;)V",
                                                      &addEventStatusMethod);
        VerifyOrReturn(
            err == CHIP_NO_ERROR,
            ChipLogError(Controller, "Could not find addEventStatus method with error %" CHIP_ERROR_FORMAT, err.Format()));

        jobject jClusterState = nullptr;
        if (apStatus->mClusterStatus.has_value())
        {
            err = JniReferences::GetInstance().CreateBoxedObject<jint>("java/lang/Integer", "(I)V",
                                                                       static_cast<jint>(*apStatus->mClusterStatus), jClusterState);
            VerifyOrReturn(err == CHIP_NO_ERROR,
                           ChipLogError(Controller, "Could not CreateBoxedObject with error %" CHIP_ERROR_FORMAT, err.Format()));
        }

        env->CallVoidMethod(nodeState, addEventStatusMethod, static_cast<jint>(aEventHeader.mPath.mEndpointId),
                            static_cast<jlong>(aEventHeader.mPath.mClusterId), static_cast<jlong>(aEventHeader.mPath.mEventId),
                            static_cast<jint>(apStatus->mStatus), jClusterState);
        VerifyOrReturn(!env->ExceptionCheck(), env->ExceptionDescribe());
        return;
    }
    VerifyOrReturn(apData != nullptr, ChipLogError(Controller, "Receive empty apData"); aEventHeader.LogPath());

    TLV::TLVReader readerForJavaTLV;
    readerForJavaTLV.Init(*apData);

    jlong eventNumber    = static_cast<jlong>(aEventHeader.mEventNumber);
    jint priorityLevel   = static_cast<jint>(aEventHeader.mPriorityLevel);
    jlong timestampValue = static_cast<jlong>(aEventHeader.mTimestamp.mValue);

    jint timestampType = 0;
    if (aEventHeader.mTimestamp.mType == app::Timestamp::Type::kSystem)
    {
        timestampType = static_cast<jint>(MILLIS_SINCE_BOOT);
    }
    else if (aEventHeader.mTimestamp.mType == app::Timestamp::Type::kEpoch)
    {
        timestampType = static_cast<jint>(MILLIS_SINCE_EPOCH);
    }
    else
    {
        ChipLogError(Controller, "Unsupported event timestamp type");
        aEventHeader.LogPath();
        return;
    }

    jobject value = nullptr;
    TLV::TLVReader readerForJavaObject;
    readerForJavaObject.Init(*apData);
#ifdef USE_JAVA_TLV_ENCODE_DECODE
    value = DecodeEventValue(aEventHeader.mPath, readerForJavaObject, &err);
    // If we don't know this event, just skip it.
    if (err == CHIP_ERROR_IM_MALFORMED_EVENT_PATH_IB)
    {
        TLV::TLVReader readerForGeneralValueObject;
        readerForGeneralValueObject.Init(*apData);
        value = DecodeGeneralTLVValue(env, readerForGeneralValueObject, err);
        err   = CHIP_NO_ERROR;
    }
    VerifyOrReturn(err == CHIP_NO_ERROR,
                   ChipLogError(Controller, "Fail to decode event with error %" CHIP_ERROR_FORMAT, err.Format());
                   aEventHeader.LogPath());
    VerifyOrReturn(!env->ExceptionCheck(), env->ExceptionDescribe());
#else
    value = DecodeGeneralTLVValue(env, readerForJavaObject, err);
#endif

    // Create TLV byte array to pass to Java layer
    size_t bufferLen                  = readerForJavaTLV.GetRemainingLength() + readerForJavaTLV.GetLengthRead();
    std::unique_ptr<uint8_t[]> buffer = std::unique_ptr<uint8_t[]>(new uint8_t[bufferLen]);
    uint32_t size                     = 0;
    // The TLVReader's read head is not pointing to the first element in the container, instead of the container itself, use
    // a TLVWriter to get a TLV with a normalized TLV buffer (Wrapped with an anonymous tag, no extra "end of container" tag
    // at the end.)
    TLV::TLVWriter writer;
    writer.Init(buffer.get(), bufferLen);
    err = writer.CopyElement(TLV::AnonymousTag(), readerForJavaTLV);

    VerifyOrReturn(err == CHIP_NO_ERROR,
                   ChipLogError(Controller, "Fail to copy element with error %" CHIP_ERROR_FORMAT, err.Format());
                   aEventHeader.LogPath());
    size = writer.GetLengthWritten();
    chip::ByteArray jniByteArray(env, reinterpret_cast<jbyte *>(buffer.get()), static_cast<jint>(size));

    // Convert TLV to JSON
    std::string json;
    err = ConvertReportTlvToJson(static_cast<uint32_t>(aEventHeader.mPath.mEventId), *apData, json);
    VerifyOrReturn(err == CHIP_NO_ERROR,
                   ChipLogError(Controller, "Fail to convert report tlv to Json with error %" CHIP_ERROR_FORMAT, err.Format());
                   aEventHeader.LogPath());
    UtfString jsonString(env, json.c_str());

    jmethodID addEventMethod;
    err = JniReferences::GetInstance().FindMethod(env, nodeState, "addEvent", "(IJJJIIJLjava/lang/Object;[BLjava/lang/String;)V",
                                                  &addEventMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR,
                   ChipLogError(Controller, "Could not find addEvent method with error %" CHIP_ERROR_FORMAT, err.Format());
                   aEventHeader.LogPath());
    env->CallVoidMethod(nodeState, addEventMethod, static_cast<jint>(aEventHeader.mPath.mEndpointId),
                        static_cast<jlong>(aEventHeader.mPath.mClusterId), static_cast<jlong>(aEventHeader.mPath.mEventId),
                        eventNumber, priorityLevel, timestampType, timestampValue, value, jniByteArray.jniValue(),
                        jsonString.jniValue());
    VerifyOrReturn(!env->ExceptionCheck(), env->ExceptionDescribe(); aEventHeader.LogPath());
}

void ReportCallback::OnError(CHIP_ERROR aError)
{
    ReportError(nullptr, nullptr, aError);
}

void ReportCallback::OnDone(app::ReadClient *)
{
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = JniReferences::GetInstance().GetEnvForCurrentThread();
    VerifyOrReturn(env != nullptr, ChipLogError(Controller, "Could not get JNIEnv for current thread"));
    JniLocalReferenceScope scope(env);
    VerifyOrReturn(mWrapperCallbackRef.HasValidObjectRef(),
                   ChipLogError(Controller, "mWrapperCallbackRef is not valid in %s", __func__));
    jmethodID onDoneMethod;
    jobject wrapperCallback = mWrapperCallbackRef.ObjectRef();
    JniGlobalReference globalRef(std::move(mWrapperCallbackRef));

    err = JniReferences::GetInstance().FindMethod(env, wrapperCallback, "onDone", "()V", &onDoneMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Controller, "Could not find onDone method"));

    if (mReadClient != nullptr)
    {
        Platform::Delete(mReadClient);
    }
    mReadClient = nullptr;

    DeviceLayer::StackUnlock unlock;
    env->CallVoidMethod(wrapperCallback, onDoneMethod);
    VerifyOrReturn(!env->ExceptionCheck(), env->ExceptionDescribe());
}

void ReportCallback::OnSubscriptionEstablished(SubscriptionId aSubscriptionId)
{
    JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread();
    VerifyOrReturn(env != nullptr, ChipLogError(Controller, "Could not get JNIEnv for current thread"));
    JniLocalReferenceScope scope(env);
    DeviceLayer::StackUnlock unlock;
    VerifyOrReturn(mSubscriptionEstablishedCallbackRef.HasValidObjectRef(),
                   ChipLogError(Controller, " mSubscriptionEstablishedCallbackRef is not valid in %s", __func__));
    CHIP_ERROR err =
        JniReferences::GetInstance().CallSubscriptionEstablished(mSubscriptionEstablishedCallbackRef.ObjectRef(), aSubscriptionId);
    VerifyOrReturn(err == CHIP_NO_ERROR,
                   ChipLogError(Controller, "CallSubscriptionEstablished error! : %" CHIP_ERROR_FORMAT, err.Format()));
}

CHIP_ERROR ReportCallback::OnResubscriptionNeeded(app::ReadClient * apReadClient, CHIP_ERROR aTerminationCause)
{
    JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread();
    VerifyOrReturnError(env != nullptr, CHIP_JNI_ERROR_NULL_OBJECT);
    ReturnErrorOnFailure(app::ReadClient::Callback::OnResubscriptionNeeded(apReadClient, aTerminationCause));
    JniLocalReferenceScope scope(env);
    jmethodID onResubscriptionAttemptMethod;
    VerifyOrReturnLogError(mResubscriptionAttemptCallbackRef.HasValidObjectRef(), CHIP_ERROR_INCORRECT_STATE);
    jobject resubscriptionAttemptCallbackRef = mResubscriptionAttemptCallbackRef.ObjectRef();
    ReturnLogErrorOnFailure(JniReferences::GetInstance().FindMethod(
        env, resubscriptionAttemptCallbackRef, "onResubscriptionAttempt", "(JJ)V", &onResubscriptionAttemptMethod));

    DeviceLayer::StackUnlock unlock;
    env->CallVoidMethod(resubscriptionAttemptCallbackRef, onResubscriptionAttemptMethod,
                        static_cast<jlong>(aTerminationCause.AsInteger()),
                        static_cast<jlong>(apReadClient->ComputeTimeTillNextSubscription()));
    VerifyOrReturnError(!env->ExceptionCheck(), CHIP_JNI_ERROR_EXCEPTION_THROWN);
    return CHIP_NO_ERROR;
}

void ReportCallback::ReportError(const app::ConcreteAttributePath * attributePath, const app::ConcreteEventPath * eventPath,
                                 CHIP_ERROR err)
{
    ReportError(attributePath, eventPath, ErrorStr(err), err.AsInteger());
}

void ReportCallback::ReportError(const app::ConcreteAttributePath * attributePath, const app::ConcreteEventPath * eventPath,
                                 Protocols::InteractionModel::Status status)
{
    ReportError(attributePath, eventPath, "IM Status",
                static_cast<std::underlying_type_t<Protocols::InteractionModel::Status>>(status));
}

void ReportCallback::ReportError(const app::ConcreteAttributePath * attributePath, const app::ConcreteEventPath * eventPath,
                                 const char * message, ChipError::StorageType errorCode)
{
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = JniReferences::GetInstance().GetEnvForCurrentThread();
    VerifyOrReturn(env != nullptr, ChipLogError(Controller, "Could not get JNIEnv for current thread"));
    JniLocalReferenceScope scope(env);
    VerifyOrReturn(mWrapperCallbackRef.HasValidObjectRef(),
                   ChipLogError(Controller, "mWrapperCallbackRef is not valid in %s", __func__));
    jobject wrapperCallback = mWrapperCallbackRef.ObjectRef();
    jthrowable exception;
    err = AndroidControllerExceptions::GetInstance().CreateAndroidControllerException(env, message, errorCode, exception);
    VerifyOrReturn(err == CHIP_NO_ERROR,
                   ChipLogError(Controller,
                                "Unable to create AndroidControllerException on ReportCallback::ReportError: %" CHIP_ERROR_FORMAT,
                                err.Format()));
    jmethodID onErrorMethod;
    err = JniReferences::GetInstance().FindMethod(env, wrapperCallback, "onError", "(ZIJJZIJJLjava/lang/Exception;)V",
                                                  &onErrorMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR,
                   ChipLogError(Controller, "Unable to find onError method: %" CHIP_ERROR_FORMAT, err.Format()));

    DeviceLayer::StackUnlock unlock;

    jboolean isAttributePath = JNI_FALSE;
    jint attributeEndpointId = static_cast<jint>(kInvalidEndpointId);
    jlong attributeClusterId = static_cast<jlong>(kInvalidClusterId);
    jlong attributeId        = static_cast<jlong>(kInvalidAttributeId);

    jboolean isEventPath = JNI_FALSE;
    jint eventEndpointId = static_cast<jint>(kInvalidEndpointId);
    jlong eventClusterId = static_cast<jlong>(kInvalidClusterId);
    jlong eventId        = static_cast<jlong>(kInvalidAttributeId);

    if (attributePath != nullptr)
    {
        isAttributePath     = JNI_TRUE;
        attributeEndpointId = static_cast<jint>(attributePath->mEndpointId);
        attributeClusterId  = static_cast<jlong>(attributePath->mClusterId);
        attributeId         = static_cast<jlong>(attributePath->mAttributeId);
    }

    if (eventPath != nullptr)
    {
        isEventPath     = JNI_TRUE;
        eventEndpointId = static_cast<jint>(eventPath->mEndpointId);
        eventClusterId  = static_cast<jlong>(eventPath->mClusterId);
        eventId         = static_cast<jlong>(eventPath->mEventId);
    }
    env->CallVoidMethod(wrapperCallback, onErrorMethod, isAttributePath, attributeEndpointId, attributeClusterId, attributeId,
                        isEventPath, eventEndpointId, eventClusterId, eventId, exception);
    VerifyOrReturn(!env->ExceptionCheck(), env->ExceptionDescribe());
}

WriteAttributesCallback::WriteAttributesCallback(jobject wrapperCallback) : mChunkedWriteCallback(this)
{
    VerifyOrReturn(mWrapperCallbackRef.Init(wrapperCallback) == CHIP_NO_ERROR,
                   ChipLogError(Controller, "Could not init mWrapperCallbackRef for WriteAttributesCallback"));
}

WriteAttributesCallback::~WriteAttributesCallback()
{
    if (mWriteClient != nullptr)
    {
        Platform::Delete(mWriteClient);
    }
}

void WriteAttributesCallback::OnResponse(const app::WriteClient * apWriteClient, const app::ConcreteDataAttributePath & aPath,
                                         app::StatusIB aStatus)
{
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = JniReferences::GetInstance().GetEnvForCurrentThread();
    VerifyOrReturn(env != nullptr, ChipLogError(Controller, "Could not get JNIEnv for current thread"));
    JniLocalReferenceScope scope(env);
    jmethodID onResponseMethod;
    VerifyOrReturn(mWrapperCallbackRef.HasValidObjectRef(),
                   ChipLogError(Controller, "mWrapperCallbackRef is not valid in %s", __func__));
    jobject wrapperCallback = mWrapperCallbackRef.ObjectRef();
    err = JniReferences::GetInstance().FindMethod(env, wrapperCallback, "onResponse", "(IJJILjava/lang/Integer;)V",
                                                  &onResponseMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR,
                   ChipLogError(Controller, "Unable to find onError method: %" CHIP_ERROR_FORMAT, err.Format()));

    jobject jClusterState = nullptr;
    if (aStatus.mClusterStatus.has_value())
    {
        err = JniReferences::GetInstance().CreateBoxedObject<jint>("java/lang/Integer", "(I)V",
                                                                   static_cast<jint>(*aStatus.mClusterStatus), jClusterState);
        VerifyOrReturn(err == CHIP_NO_ERROR,
                       ChipLogError(Controller, "Could not CreateBoxedObject with error %" CHIP_ERROR_FORMAT, err.Format()));
    }

    DeviceLayer::StackUnlock unlock;
    env->CallVoidMethod(wrapperCallback, onResponseMethod, static_cast<jint>(aPath.mEndpointId),
                        static_cast<jlong>(aPath.mClusterId), static_cast<jlong>(aPath.mAttributeId), aStatus.mStatus,
                        jClusterState);
    VerifyOrReturn(!env->ExceptionCheck(), env->ExceptionDescribe());
}

void WriteAttributesCallback::OnError(const app::WriteClient * apWriteClient, CHIP_ERROR aError)
{
    ReportError(nullptr, aError);
}

void WriteAttributesCallback::OnDone(app::WriteClient *)
{
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = JniReferences::GetInstance().GetEnvForCurrentThread();
    VerifyOrReturn(env != nullptr, ChipLogError(Controller, "Could not get JNIEnv for current thread"));
    JniLocalReferenceScope scope(env);
    VerifyOrReturn(mWrapperCallbackRef.HasValidObjectRef(),
                   ChipLogError(Controller, "mWrapperCallbackRef is not valid in %s", __func__));
    jmethodID onDoneMethod;
    jobject wrapperCallback = mWrapperCallbackRef.ObjectRef();
    JniGlobalReference globalRef(std::move(mWrapperCallbackRef));

    err = JniReferences::GetInstance().FindMethod(env, wrapperCallback, "onDone", "()V", &onDoneMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Controller, "Could not find onDone method"));

    DeviceLayer::StackUnlock unlock;
    env->CallVoidMethod(wrapperCallback, onDoneMethod);
    VerifyOrReturn(!env->ExceptionCheck(), env->ExceptionDescribe());
}

void WriteAttributesCallback::ReportError(const app::ConcreteAttributePath * attributePath, CHIP_ERROR err)
{
    ReportError(attributePath, ErrorStr(err), err.AsInteger());
}

void WriteAttributesCallback::ReportError(const app::ConcreteAttributePath * attributePath,
                                          Protocols::InteractionModel::Status status)
{
    ReportError(attributePath, "IM Status", static_cast<std::underlying_type_t<Protocols::InteractionModel::Status>>(status));
}

void WriteAttributesCallback::ReportError(const app::ConcreteAttributePath * attributePath, const char * message,
                                          ChipError::StorageType errorCode)
{
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = JniReferences::GetInstance().GetEnvForCurrentThread();
    VerifyOrReturn(env != nullptr, ChipLogError(Controller, "Could not get JNIEnv for current thread"));
    JniLocalReferenceScope scope(env);
    ChipLogError(Controller, "WriteAttributesCallback::ReportError is called with %u", errorCode);
    jthrowable exception;
    err = AndroidControllerExceptions::GetInstance().CreateAndroidControllerException(env, message, errorCode, exception);
    VerifyOrReturn(
        err == CHIP_NO_ERROR,
        ChipLogError(Controller,
                     "Unable to create AndroidControllerException on WriteAttributesCallback::ReportError: %" CHIP_ERROR_FORMAT,
                     err.Format()));
    jmethodID onErrorMethod;
    VerifyOrReturn(mWrapperCallbackRef.HasValidObjectRef(),
                   ChipLogError(Controller, "mWrapperCallbackRef is not valid in %s", __func__));
    jobject wrapperCallback = mWrapperCallbackRef.ObjectRef();
    err = JniReferences::GetInstance().FindMethod(env, wrapperCallback, "onError", "(ZIJJLjava/lang/Exception;)V", &onErrorMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR,
                   ChipLogError(Controller, "Unable to find onError method: %" CHIP_ERROR_FORMAT, err.Format()));

    jboolean isAttributePath = JNI_FALSE;
    jint attributeEndpointId = static_cast<jint>(kInvalidEndpointId);
    jlong attributeClusterId = static_cast<jlong>(kInvalidClusterId);
    jlong attributeId        = static_cast<jlong>(kInvalidAttributeId);

    if (attributePath != nullptr)
    {
        isAttributePath     = JNI_TRUE;
        attributeEndpointId = static_cast<jint>(attributePath->mEndpointId);
        attributeClusterId  = static_cast<jint>(attributePath->mClusterId);
        attributeId         = static_cast<jint>(attributePath->mAttributeId);
    }

    DeviceLayer::StackUnlock unlock;
    env->CallVoidMethod(wrapperCallback, onErrorMethod, isAttributePath, attributeEndpointId, attributeClusterId, attributeId,
                        exception);
    VerifyOrReturn(!env->ExceptionCheck(), env->ExceptionDescribe());
}

InvokeCallback::InvokeCallback(jobject wrapperCallback)
{
    VerifyOrReturn(mWrapperCallbackRef.Init(wrapperCallback) == CHIP_NO_ERROR,
                   ChipLogError(Controller, "Could not init mWrapperCallbackRef for InvokeCallback"));
}

InvokeCallback::~InvokeCallback()
{
    if (mCommandSender != nullptr)
    {
        Platform::Delete(mCommandSender);
        mCommandSender = nullptr;
    }
}

void InvokeCallback::OnResponse(app::CommandSender * apCommandSender, const app::ConcreteCommandPath & aPath,
                                const app::StatusIB & aStatusIB, TLV::TLVReader * apData)
{
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = JniReferences::GetInstance().GetEnvForCurrentThread();
    VerifyOrReturn(env != nullptr, ChipLogError(Controller, "Could not get JNIEnv for current thread"));
    jmethodID onResponseMethod;
    JniLocalReferenceScope scope(env);
    VerifyOrReturn(mWrapperCallbackRef.HasValidObjectRef(),
                   ChipLogError(Controller, "mWrapperCallbackRef is not valid in %s", __func__));
    jobject wrapperCallbackRef = mWrapperCallbackRef.ObjectRef();
    err = JniReferences::GetInstance().FindMethod(env, wrapperCallbackRef, "onResponse", "(IJJ[BLjava/lang/String;J)V",
                                                  &onResponseMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR,
                   ChipLogError(Controller, "Unable to find onResponse method: %" CHIP_ERROR_FORMAT, err.Format()));

    DeviceLayer::StackUnlock unlock;

    if (apData != nullptr)
    {
        TLV::TLVReader readerForJavaTLV;
        TLV::TLVReader readerForJson;
        readerForJavaTLV.Init(*apData);

        // Create TLV byte array to pass to Java layer
        size_t bufferLen                  = readerForJavaTLV.GetRemainingLength() + readerForJavaTLV.GetLengthRead();
        std::unique_ptr<uint8_t[]> buffer = std::unique_ptr<uint8_t[]>(new uint8_t[bufferLen]);
        uint32_t size                     = 0;

        TLV::TLVWriter writer;
        writer.Init(buffer.get(), bufferLen);
        err = writer.CopyElement(TLV::AnonymousTag(), readerForJavaTLV);
        VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Controller, "Failed CopyElement: %" CHIP_ERROR_FORMAT, err.Format()));
        size = writer.GetLengthWritten();

        chip::ByteArray jniByteArray(env, reinterpret_cast<jbyte *>(buffer.get()), static_cast<jint>(size));

        // Convert TLV to JSON
        std::string json;
        readerForJson.Init(buffer.get(), size);
        err = readerForJson.Next();
        VerifyOrReturn(err == CHIP_NO_ERROR,
                       ChipLogError(Controller, "Failed readerForJson next: %" CHIP_ERROR_FORMAT, err.Format()));
        err = TlvToJson(readerForJson, json);
        VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Controller, "Failed TlvToJson: %" CHIP_ERROR_FORMAT, err.Format()));
        UtfString jsonString(env, json.c_str());

        env->CallVoidMethod(
            wrapperCallbackRef, onResponseMethod, static_cast<jint>(aPath.mEndpointId), static_cast<jlong>(aPath.mClusterId),
            static_cast<jlong>(aPath.mCommandId), jniByteArray.jniValue(), jsonString.jniValue(),
            aStatusIB.mClusterStatus.has_value() ? static_cast<jlong>(*aStatusIB.mClusterStatus)
                                                 : static_cast<jlong>(Protocols::InteractionModel::Status::Success));
    }
    else
    {
        env->CallVoidMethod(wrapperCallbackRef, onResponseMethod, static_cast<jint>(aPath.mEndpointId),
                            static_cast<jlong>(aPath.mClusterId), static_cast<jlong>(aPath.mCommandId), nullptr, nullptr,
                            aStatusIB.mClusterStatus.has_value()
                                ? static_cast<jlong>(*aStatusIB.mClusterStatus)
                                : static_cast<jlong>(Protocols::InteractionModel::Status::Success));
    }

    VerifyOrReturn(!env->ExceptionCheck(), env->ExceptionDescribe());
}

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

void InvokeCallback::OnDone(app::CommandSender * apCommandSender)
{
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = JniReferences::GetInstance().GetEnvForCurrentThread();
    VerifyOrReturn(env != nullptr, ChipLogError(Controller, "Could not get JNIEnv for current thread"));
    JniLocalReferenceScope scope(env);
    jmethodID onDoneMethod;
    VerifyOrReturn(mWrapperCallbackRef.HasValidObjectRef(),
                   ChipLogError(Controller, "mWrapperCallbackRef is not valid in %s", __func__));
    jobject wrapperCallback = mWrapperCallbackRef.ObjectRef();
    JniGlobalReference globalRef(std::move(mWrapperCallbackRef));

    err = JniReferences::GetInstance().FindMethod(env, wrapperCallback, "onDone", "()V", &onDoneMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Controller, "Could not find onDone method"));

    DeviceLayer::StackUnlock unlock;
    env->CallVoidMethod(wrapperCallback, onDoneMethod);
    VerifyOrReturn(!env->ExceptionCheck(), env->ExceptionDescribe());
}

void InvokeCallback::ReportError(CHIP_ERROR err)
{
    ReportError(ErrorStr(err), err.AsInteger());
}

void InvokeCallback::ReportError(Protocols::InteractionModel::Status status)
{
    ReportError("IM Status", static_cast<std::underlying_type_t<Protocols::InteractionModel::Status>>(status));
}

void InvokeCallback::ReportError(const char * message, ChipError::StorageType errorCode)
{
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = JniReferences::GetInstance().GetEnvForCurrentThread();
    VerifyOrReturn(env != nullptr, ChipLogError(Controller, "Could not get JNIEnv for current thread"));
    JniLocalReferenceScope scope(env);
    ChipLogError(Controller, "InvokeCallback::ReportError is called with %u", errorCode);
    jthrowable exception;
    err = AndroidControllerExceptions::GetInstance().CreateAndroidControllerException(env, message, errorCode, exception);
    VerifyOrReturn(err == CHIP_NO_ERROR,
                   ChipLogError(Controller,
                                "Unable to create AndroidControllerException on InvokeCallback::ReportError: %" CHIP_ERROR_FORMAT,
                                err.Format()));

    jmethodID onErrorMethod;
    VerifyOrReturn(mWrapperCallbackRef.HasValidObjectRef(),
                   ChipLogError(Controller, "mWrapperCallbackRef is not valid in %s", __func__));
    jobject wrapperCallback = mWrapperCallbackRef.ObjectRef();
    err = JniReferences::GetInstance().FindMethod(env, wrapperCallback, "onError", "(Ljava/lang/Exception;)V", &onErrorMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR,
                   ChipLogError(Controller, "Unable to find onError method: %" CHIP_ERROR_FORMAT, err.Format()));

    DeviceLayer::StackUnlock unlock;
    env->CallVoidMethod(wrapperCallback, onErrorMethod, exception);
    VerifyOrReturn(!env->ExceptionCheck(), env->ExceptionDescribe());
}

jobject DecodeGeneralTLVValue(JNIEnv * env, TLV::TLVReader & readerForGeneralValueObject, CHIP_ERROR & err)
{
    jobject retValue = nullptr;

    switch (readerForGeneralValueObject.GetType())
    {
    case TLV::kTLVType_SignedInteger: {
        int64_t signedValue = 0;
        VerifyOrReturnValue(readerForGeneralValueObject.Get(signedValue) == CHIP_NO_ERROR, nullptr,
                            ChipLogProgress(Controller, "Get TLV Value fail!"));
        err = JniReferences::GetInstance().CreateBoxedObject<jlong>("java/lang/Long", "(J)V", static_cast<jlong>(signedValue),
                                                                    retValue);
        VerifyOrReturnValue(err == CHIP_NO_ERROR, nullptr, ChipLogProgress(Controller, "Create Boxed Object fail!"));
        return retValue;
    }
    case TLV::kTLVType_UnsignedInteger: {
        uint64_t unsignedValue = 0;
        VerifyOrReturnValue(readerForGeneralValueObject.Get(unsignedValue) == CHIP_NO_ERROR, nullptr,
                            ChipLogProgress(Controller, "Get TLV Value fail!"));
        err = JniReferences::GetInstance().CreateBoxedObject<jlong>("java/lang/Long", "(J)V", static_cast<jlong>(unsignedValue),
                                                                    retValue);
        VerifyOrReturnValue(err == CHIP_NO_ERROR, nullptr, ChipLogProgress(Controller, "Create Boxed Object fail!"));
        return retValue;
    }
    case TLV::kTLVType_Boolean: {
        bool booleanValue = false;
        VerifyOrReturnValue(readerForGeneralValueObject.Get(booleanValue) == CHIP_NO_ERROR, nullptr,
                            ChipLogProgress(Controller, "Get TLV Value fail!"));
        err = JniReferences::GetInstance().CreateBoxedObject<jboolean>("java/lang/Boolean", "(Z)V",
                                                                       static_cast<jboolean>(booleanValue), retValue);
        VerifyOrReturnValue(err == CHIP_NO_ERROR, nullptr, ChipLogProgress(Controller, "Create Boxed Object fail!"));
        return retValue;
    }
    case TLV::kTLVType_FloatingPointNumber: {
        double doubleValue = 0.0;
        VerifyOrReturnValue(readerForGeneralValueObject.Get(doubleValue) == CHIP_NO_ERROR, nullptr,
                            ChipLogProgress(Controller, "Get TLV Value fail!"));
        err = JniReferences::GetInstance().CreateBoxedObject<jdouble>("java/lang/Double", "(D)V", static_cast<jdouble>(doubleValue),
                                                                      retValue);
        VerifyOrReturnValue(err == CHIP_NO_ERROR, nullptr, ChipLogProgress(Controller, "Create Boxed Object fail!"));
        return retValue;
    }
    case TLV::kTLVType_UTF8String: {
        uint32_t bufferLen             = readerForGeneralValueObject.GetLength();
        std::unique_ptr<char[]> buffer = std::unique_ptr<char[]>(new char[bufferLen + 1]);
        err                            = readerForGeneralValueObject.GetString(buffer.get(), bufferLen + 1);
        VerifyOrReturnValue(err == CHIP_NO_ERROR, nullptr, ChipLogProgress(Controller, "Get TLV Value fail!"));
        chip::CharSpan valueSpan(buffer.get(), bufferLen);
        chip::JniReferences::GetInstance().CharToStringUTF(valueSpan, retValue);
        return retValue;
    }
    case TLV::kTLVType_ByteString: {
        uint32_t bufferLen                = readerForGeneralValueObject.GetLength();
        std::unique_ptr<uint8_t[]> buffer = std::unique_ptr<uint8_t[]>(new uint8_t[bufferLen + 1]);
        err                               = readerForGeneralValueObject.GetBytes(buffer.get(), bufferLen + 1);
        VerifyOrReturnValue(err == CHIP_NO_ERROR, nullptr, ChipLogProgress(Controller, "Get TLV Value fail!"));

        jbyteArray valueByteArray = env->NewByteArray(static_cast<jsize>(bufferLen));
        env->SetByteArrayRegion(valueByteArray, 0, static_cast<jsize>(bufferLen), reinterpret_cast<const jbyte *>(buffer.get()));

        return static_cast<jobject>(valueByteArray);
    }
    case TLV::kTLVType_Array: {
        TLV::TLVType containerType;
        err = readerForGeneralValueObject.EnterContainer(containerType);
        VerifyOrReturnValue(err == CHIP_NO_ERROR, nullptr,
                            ChipLogProgress(Controller, "EnterContainer fail! : %" CHIP_ERROR_FORMAT, err.Format()));
        err = chip::JniReferences::GetInstance().CreateArrayList(retValue);
        VerifyOrReturnValue(err == CHIP_NO_ERROR, nullptr,
                            ChipLogProgress(Controller, "CreateArrayList fail! : %" CHIP_ERROR_FORMAT, err.Format()));
        while (readerForGeneralValueObject.Next() == CHIP_NO_ERROR)
        {
            jobject inValue = DecodeGeneralTLVValue(env, readerForGeneralValueObject, err);
            VerifyOrReturnValue(err == CHIP_NO_ERROR, nullptr,
                                ChipLogProgress(Controller, "Can't parse general value : %" CHIP_ERROR_FORMAT, err.Format()));
            err = chip::JniReferences::GetInstance().AddToList(retValue, inValue);
        }
        return retValue;
    }
    case TLV::kTLVType_List: {
        TLV::TLVType containerType;
        err = readerForGeneralValueObject.EnterContainer(containerType);
        VerifyOrReturnValue(err == CHIP_NO_ERROR, nullptr,
                            ChipLogProgress(Controller, "EnterContainer fail! : %" CHIP_ERROR_FORMAT, err.Format()));
        err = chip::JniReferences::GetInstance().CreateArrayList(retValue);
        VerifyOrReturnValue(err == CHIP_NO_ERROR, nullptr,
                            ChipLogProgress(Controller, "CreateArrayList fail! : %" CHIP_ERROR_FORMAT, err.Format()));
        while (readerForGeneralValueObject.Next() == CHIP_NO_ERROR)
        {
            jobject inValue = DecodeGeneralTLVValue(env, readerForGeneralValueObject, err);
            VerifyOrReturnValue(err == CHIP_NO_ERROR, nullptr,
                                ChipLogProgress(Controller, "Can't parse general value : %" CHIP_ERROR_FORMAT, err.Format()));
            err = chip::JniReferences::GetInstance().AddToList(retValue, inValue);
        }
        return retValue;
    }
    case TLV::kTLVType_Null: {
        return nullptr;
    }
    default:
        err = CHIP_ERROR_WRONG_TLV_TYPE;
        return nullptr;
    }
}

ExtendableInvokeCallback::ExtendableInvokeCallback(jobject wrapperCallback)
{
    VerifyOrReturn(mWrapperCallbackRef.Init(wrapperCallback) == CHIP_NO_ERROR,
                   ChipLogError(Controller, "Could not init mWrapperCallbackRef for ExtendableInvokeCallback"));
}

ExtendableInvokeCallback::~ExtendableInvokeCallback()
{
    if (mCommandSender != nullptr)
    {
        Platform::Delete(mCommandSender);
        mCommandSender = nullptr;
    }
}

void ExtendableInvokeCallback::OnResponse(app::CommandSender * apCommandSender,
                                          const app::CommandSender::ResponseData & aResponseData)
{
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = JniReferences::GetInstance().GetEnvForCurrentThread();
    VerifyOrReturn(env != nullptr, ChipLogError(Controller, "Could not get JNIEnv for current thread"));
    jmethodID onResponseMethod;
    JniLocalReferenceScope scope(env);
    VerifyOrReturn(mWrapperCallbackRef.HasValidObjectRef(),
                   ChipLogError(Controller, "mWrapperCallbackRef is not valid in %s", __func__));
    jobject wrapperCallbackRef = mWrapperCallbackRef.ObjectRef();
    DeviceLayer::StackUnlock unlock;

    jobject jCommandRef = nullptr;
    if (aResponseData.commandRef.HasValue())
    {
        err = JniReferences::GetInstance().CreateBoxedObject<jint>(
            "java/lang/Integer", "(I)V", static_cast<jint>(aResponseData.commandRef.Value()), jCommandRef);
        VerifyOrReturn(err == CHIP_NO_ERROR,
                       ChipLogError(Controller, "Could not CreateBoxedObject with error %" CHIP_ERROR_FORMAT, err.Format()));
    }

    if (aResponseData.data != nullptr)
    {
        TLV::TLVReader readerForJavaTLV;
        TLV::TLVReader readerForJson;
        readerForJavaTLV.Init(*(aResponseData.data));

        // Create TLV byte array to pass to Java layer
        size_t bufferLen                  = readerForJavaTLV.GetRemainingLength() + readerForJavaTLV.GetLengthRead();
        std::unique_ptr<uint8_t[]> buffer = std::unique_ptr<uint8_t[]>(new uint8_t[bufferLen]);
        uint32_t size                     = 0;

        TLV::TLVWriter writer;
        writer.Init(buffer.get(), bufferLen);
        err = writer.CopyElement(TLV::AnonymousTag(), readerForJavaTLV);
        VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Controller, "Failed CopyElement: %" CHIP_ERROR_FORMAT, err.Format()));
        size = writer.GetLengthWritten();

        chip::ByteArray jniByteArray(env, reinterpret_cast<jbyte *>(buffer.get()), static_cast<jint>(size));

        // Convert TLV to JSON
        std::string json;
        readerForJson.Init(buffer.get(), size);
        err = readerForJson.Next();
        VerifyOrReturn(err == CHIP_NO_ERROR,
                       ChipLogError(Controller, "Failed readerForJson next: %" CHIP_ERROR_FORMAT, err.Format()));
        err = TlvToJson(readerForJson, json);
        VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Controller, "Failed TlvToJson: %" CHIP_ERROR_FORMAT, err.Format()));
        UtfString jsonString(env, json.c_str());

        err = JniReferences::GetInstance().FindMethod(env, wrapperCallbackRef, "onResponse",
                                                      "(IJJLjava/lang/Integer;[BLjava/lang/String;)V", &onResponseMethod);
        VerifyOrReturn(err == CHIP_NO_ERROR,
                       ChipLogError(Controller, "Unable to find onResponse method: %" CHIP_ERROR_FORMAT, err.Format()));

        env->CallVoidMethod(wrapperCallbackRef, onResponseMethod, static_cast<jint>(aResponseData.path.mEndpointId),
                            static_cast<jlong>(aResponseData.path.mClusterId), static_cast<jlong>(aResponseData.path.mCommandId),
                            jCommandRef, jniByteArray.jniValue(), jsonString.jniValue());
    }
    else
    {
        err = JniReferences::GetInstance().FindMethod(env, wrapperCallbackRef, "onResponse",
                                                      "(IJJLjava/lang/Integer;ILjava/lang/Integer;)V", &onResponseMethod);
        VerifyOrReturn(err == CHIP_NO_ERROR,
                       ChipLogError(Controller, "Unable to find onResponse method: %" CHIP_ERROR_FORMAT, err.Format()));

        jobject jClusterState = nullptr;
        if (aResponseData.statusIB.mClusterStatus.has_value())
        {
            err = JniReferences::GetInstance().CreateBoxedObject<jint>(
                "java/lang/Integer", "(I)V", static_cast<jint>(*aResponseData.statusIB.mClusterStatus), jClusterState);
            VerifyOrReturn(err == CHIP_NO_ERROR,
                           ChipLogError(Controller, "Could not CreateBoxedObject with error %" CHIP_ERROR_FORMAT, err.Format()));
        }

        env->CallVoidMethod(wrapperCallbackRef, onResponseMethod, static_cast<jint>(aResponseData.path.mEndpointId),
                            static_cast<jlong>(aResponseData.path.mClusterId), static_cast<jlong>(aResponseData.path.mCommandId),
                            jCommandRef, aResponseData.statusIB.mStatus, jClusterState);
    }

    VerifyOrReturn(!env->ExceptionCheck(), env->ExceptionDescribe());
}

void ExtendableInvokeCallback::OnNoResponse(app::CommandSender * commandSender,
                                            const app::CommandSender::NoResponseData & aNoResponseData)
{
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = JniReferences::GetInstance().GetEnvForCurrentThread();
    VerifyOrReturn(env != nullptr, ChipLogError(Controller, "Could not get JNIEnv for current thread"));
    jmethodID onNoResponseMethod;
    JniLocalReferenceScope scope(env);
    VerifyOrReturn(mWrapperCallbackRef.HasValidObjectRef(),
                   ChipLogError(Controller, "mWrapperCallbackRef is not valid in %s", __func__));
    jobject wrapperCallbackRef = mWrapperCallbackRef.ObjectRef();
    DeviceLayer::StackUnlock unlock;

    err = JniReferences::GetInstance().FindMethod(env, wrapperCallbackRef, "onNoResponse", "(I)V", &onNoResponseMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR,
                   ChipLogError(Controller, "Unable to find onNoResponse method: %" CHIP_ERROR_FORMAT, err.Format()));
    env->CallVoidMethod(wrapperCallbackRef, onNoResponseMethod, static_cast<jint>(aNoResponseData.commandRef));
    VerifyOrReturn(!env->ExceptionCheck(), env->ExceptionDescribe());
}

void ExtendableInvokeCallback::OnError(const app::CommandSender * apCommandSender, const app::CommandSender::ErrorData & aErrorData)
{
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = JniReferences::GetInstance().GetEnvForCurrentThread();
    VerifyOrReturn(env != nullptr, ChipLogError(Controller, "Could not get JNIEnv for current thread"));
    JniLocalReferenceScope scope(env);
    ChipLogError(Controller, "ExtendableInvokeCallback::OnError is called with %u", aErrorData.error.AsInteger());
    jthrowable exception;
    err = AndroidControllerExceptions::GetInstance().CreateAndroidControllerException(env, ErrorStr(aErrorData.error),
                                                                                      aErrorData.error.AsInteger(), exception);
    VerifyOrReturn(
        err == CHIP_NO_ERROR,
        ChipLogError(Controller, "Unable to create AndroidControllerException with error: %" CHIP_ERROR_FORMAT, err.Format()));

    jmethodID onErrorMethod;
    VerifyOrReturn(mWrapperCallbackRef.HasValidObjectRef(),
                   ChipLogError(Controller, "mWrapperCallbackRef is not valid in %s", __func__));
    jobject wrapperCallback = mWrapperCallbackRef.ObjectRef();
    err = JniReferences::GetInstance().FindMethod(env, wrapperCallback, "onError", "(Ljava/lang/Exception;)V", &onErrorMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR,
                   ChipLogError(Controller, "Unable to find onError method:  %" CHIP_ERROR_FORMAT, err.Format()));

    DeviceLayer::StackUnlock unlock;
    env->CallVoidMethod(wrapperCallback, onErrorMethod, exception);
    VerifyOrReturn(!env->ExceptionCheck(), env->ExceptionDescribe());
}

void ExtendableInvokeCallback::OnDone(app::CommandSender * apCommandSender)
{
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = JniReferences::GetInstance().GetEnvForCurrentThread();
    VerifyOrReturn(env != nullptr, ChipLogError(Controller, "Could not get JNIEnv for current thread"));
    JniLocalReferenceScope scope(env);
    jmethodID onDoneMethod;
    VerifyOrReturn(mWrapperCallbackRef.HasValidObjectRef(),
                   ChipLogError(Controller, "mWrapperCallbackRef is not valid in %s", __func__));
    jobject wrapperCallback = mWrapperCallbackRef.ObjectRef();
    JniGlobalReference globalRef(std::move(mWrapperCallbackRef));

    err = JniReferences::GetInstance().FindMethod(env, wrapperCallback, "onDone", "()V", &onDoneMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Controller, "Could not find onDone method"));

    DeviceLayer::StackUnlock unlock;
    env->CallVoidMethod(wrapperCallback, onDoneMethod);
    VerifyOrReturn(!env->ExceptionCheck(), env->ExceptionDescribe());
}

jlong newConnectedDeviceCallback(JNIEnv * env, jobject self, jobject callback)
{
    chip::DeviceLayer::StackLock lock;
    GetConnectedDeviceCallback * connectedDeviceCallback = chip::Platform::New<GetConnectedDeviceCallback>(self, callback);
    return reinterpret_cast<jlong>(connectedDeviceCallback);
}

void deleteConnectedDeviceCallback(JNIEnv * env, jobject self, jlong callbackHandle)
{
    chip::DeviceLayer::StackLock lock;
    GetConnectedDeviceCallback * connectedDeviceCallback = reinterpret_cast<GetConnectedDeviceCallback *>(callbackHandle);
    VerifyOrReturn(connectedDeviceCallback != nullptr, ChipLogError(Controller, "GetConnectedDeviceCallback handle is nullptr"));
    chip::Platform::Delete(connectedDeviceCallback);
}

jlong newReportCallback(JNIEnv * env, jobject self, jobject subscriptionEstablishedCallbackJava,
                        jobject resubscriptionAttemptCallbackJava, const char * nodeStateClassSignature)
{
    chip::DeviceLayer::StackLock lock;
    ReportCallback * reportCallback = chip::Platform::New<ReportCallback>(
        self, subscriptionEstablishedCallbackJava, resubscriptionAttemptCallbackJava, nodeStateClassSignature);
    return reinterpret_cast<jlong>(reportCallback);
}

void deleteReportCallback(JNIEnv * env, jobject self, jlong callbackHandle)
{
    chip::DeviceLayer::StackLock lock;
    ReportCallback * reportCallback = reinterpret_cast<ReportCallback *>(callbackHandle);
    VerifyOrReturn(reportCallback != nullptr, ChipLogError(Controller, "ReportCallback handle is nullptr"));
    chip::Platform::Delete(reportCallback);
}

jlong newWriteAttributesCallback(JNIEnv * env, jobject self)
{
    chip::DeviceLayer::StackLock lock;
    WriteAttributesCallback * writeAttributesCallback = chip::Platform::New<WriteAttributesCallback>(self);
    return reinterpret_cast<jlong>(writeAttributesCallback);
}

void deleteWriteAttributesCallback(JNIEnv * env, jobject self, jlong callbackHandle)
{
    chip::DeviceLayer::StackLock lock;
    WriteAttributesCallback * writeAttributesCallback = reinterpret_cast<WriteAttributesCallback *>(callbackHandle);
    VerifyOrReturn(writeAttributesCallback != nullptr, ChipLogError(Controller, "WriteAttributesCallback handle is nullptr"));
    chip::Platform::Delete(writeAttributesCallback);
}

jlong newInvokeCallback(JNIEnv * env, jobject self)
{
    chip::DeviceLayer::StackLock lock;
    InvokeCallback * invokeCallback = chip::Platform::New<InvokeCallback>(self);
    return reinterpret_cast<jlong>(invokeCallback);
}

void deleteInvokeCallback(JNIEnv * env, jobject self, jlong callbackHandle)
{
    chip::DeviceLayer::StackLock lock;
    InvokeCallback * invokeCallback = reinterpret_cast<InvokeCallback *>(callbackHandle);
    VerifyOrReturn(invokeCallback != nullptr, ChipLogError(Controller, "InvokeCallback handle is nullptr"));
    chip::Platform::Delete(invokeCallback);
}

jlong newExtendableInvokeCallback(JNIEnv * env, jobject self)
{
    chip::DeviceLayer::StackLock lock;
    ExtendableInvokeCallback * invokeCallback = chip::Platform::New<ExtendableInvokeCallback>(self);
    return reinterpret_cast<jlong>(invokeCallback);
}

void deleteExtendableInvokeCallback(JNIEnv * env, jobject self, jlong callbackHandle)
{
    chip::DeviceLayer::StackLock lock;
    ExtendableInvokeCallback * invokeCallback = reinterpret_cast<ExtendableInvokeCallback *>(callbackHandle);
    VerifyOrReturn(invokeCallback != nullptr, ChipLogError(Controller, "ExtendableInvokeCallback handle is nullptr"));
    chip::Platform::Delete(invokeCallback);
}
} // namespace Controller
} // namespace chip
