/*
 *   Copyright (c) 2024 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.
 *
 */

/**
 *    @file
 *      Implementation of ICD Client API for Android Platform
 *
 */

#include "AndroidICDClient.h"

#include <app/icd/client/ICDClientInfo.h>
#include <lib/support/JniTypeWrappers.h>

chip::app::DefaultICDClientStorage sICDClientStorage;
static CHIP_ERROR ParseICDClientInfo(JNIEnv * env, jint jFabricIndex, jobject jIcdClientInfo,
                                     chip::app::ICDClientInfo & icdClientInfo);

jobject getICDClientInfo(JNIEnv * env, const char * icdClientInfoSign, jint jFabricIndex)
{
    CHIP_ERROR err = CHIP_NO_ERROR;

    jobject jInfo = nullptr;
    chip::app::ICDClientInfo info;
    chip::FabricIndex fabricIndex = static_cast<chip::FabricIndex>(jFabricIndex);

    ChipLogProgress(Controller, "getICDClientInfo(%u) called", fabricIndex);

    err = chip::JniReferences::GetInstance().CreateArrayList(jInfo);
    VerifyOrReturnValue(err == CHIP_NO_ERROR, nullptr,
                        ChipLogError(Controller, "CreateArrayList failed!: %" CHIP_ERROR_FORMAT, err.Format()));

    auto iter = getICDClientStorage()->IterateICDClientInfo();
    VerifyOrReturnValue(iter != nullptr, nullptr, ChipLogError(Controller, "IterateICDClientInfo failed!"));
    chip::app::DefaultICDClientStorage::ICDClientInfoIteratorWrapper clientInfoIteratorWrapper(iter);

    jmethodID constructor;
    jclass infoClass;
    chip::JniLocalReferenceScope scope(env);

    err = chip::JniReferences::GetInstance().GetLocalClassRef(env, icdClientInfoSign, infoClass);
    VerifyOrReturnValue(err == CHIP_NO_ERROR, nullptr,
                        ChipLogError(Controller, "Find ICDClientInfo class: %" CHIP_ERROR_FORMAT, err.Format()));

    env->ExceptionClear();
    constructor = env->GetMethodID(infoClass, "<init>", "(JJJJ[B[B)V");
    VerifyOrReturnValue(constructor != nullptr, nullptr, ChipLogError(Controller, "Find GetMethodID error!"));

    while (iter->Next(info))
    {
        jbyteArray jIcdAesKey  = nullptr;
        jbyteArray jIcdHmacKey = nullptr;
        jobject jICDClientInfo = nullptr;

        if (info.peer_node.GetFabricIndex() != fabricIndex)
        {
            continue;
        }

        err = chip::JniReferences::GetInstance().N2J_ByteArray(env,
                                                               info.aes_key_handle.As<chip::Crypto::Symmetric128BitsKeyByteArray>(),
                                                               chip::Crypto::CHIP_CRYPTO_SYMMETRIC_KEY_LENGTH_BYTES, jIcdAesKey);
        VerifyOrReturnValue(err == CHIP_NO_ERROR, nullptr,
                            ChipLogError(Controller, "ICD AES KEY N2J_ByteArray error!: %" CHIP_ERROR_FORMAT, err.Format()));

        err = chip::JniReferences::GetInstance().N2J_ByteArray(
            env, info.hmac_key_handle.As<chip::Crypto::Symmetric128BitsKeyByteArray>(),
            chip::Crypto::CHIP_CRYPTO_SYMMETRIC_KEY_LENGTH_BYTES, jIcdHmacKey);
        VerifyOrReturnValue(err == CHIP_NO_ERROR, nullptr,
                            ChipLogError(Controller, "ICD HMAC KEY N2J_ByteArray error!: %" CHIP_ERROR_FORMAT, err.Format()));

        jICDClientInfo = (jobject) env->NewObject(infoClass, constructor, static_cast<jlong>(info.peer_node.GetNodeId()),
                                                  static_cast<jlong>(info.start_icd_counter), static_cast<jlong>(info.offset),
                                                  static_cast<jlong>(info.monitored_subject), jIcdAesKey, jIcdHmacKey);

        err = chip::JniReferences::GetInstance().AddToList(jInfo, jICDClientInfo);
        VerifyOrReturnValue(err == CHIP_NO_ERROR, nullptr,
                            ChipLogError(Controller, "AddToList error!: %" CHIP_ERROR_FORMAT, err.Format()));
    }

    return jInfo;
}

CHIP_ERROR StoreICDEntryWithKey(JNIEnv * env, jint jFabricIndex, jobject jicdClientInfo, jbyteArray jKey)
{
    CHIP_ERROR err = CHIP_NO_ERROR;

    chip::app::ICDClientInfo clientInfo;
    chip::JniByteArray jniKey(env, jKey);

    err = ParseICDClientInfo(env, jFabricIndex, jicdClientInfo, clientInfo);
    VerifyOrReturnValue(err == CHIP_NO_ERROR, err,
                        ChipLogError(Controller, "Failed to parse ICD Client info: %" CHIP_ERROR_FORMAT, err.Format()));

    err = getICDClientStorage()->SetKey(clientInfo, jniKey.byteSpan());

    if (err == CHIP_NO_ERROR)
    {
        err = getICDClientStorage()->StoreEntry(clientInfo);
    }
    else
    {
        getICDClientStorage()->RemoveKey(clientInfo);
        ChipLogError(Controller, "Failed to persist symmetric key with error: %" CHIP_ERROR_FORMAT, err.Format());
    }

    return err;
}

CHIP_ERROR RemoveICDEntryWithKey(JNIEnv * env, jint jFabricIndex, jobject jicdClientInfo)
{
    CHIP_ERROR err = CHIP_NO_ERROR;

    chip::app::ICDClientInfo info;
    err = ParseICDClientInfo(env, jFabricIndex, jicdClientInfo, info);
    VerifyOrReturnValue(err == CHIP_NO_ERROR, err,
                        ChipLogError(Controller, "Failed to parse ICD Client info: %" CHIP_ERROR_FORMAT, err.Format()));

    getICDClientStorage()->RemoveKey(info);

    return err;
}

CHIP_ERROR ClearICDClientInfo(JNIEnv * env, jint jFabricIndex, jlong jNodeId)
{
    CHIP_ERROR err = CHIP_NO_ERROR;

    chip::ScopedNodeId scopedNodeId(static_cast<chip::NodeId>(jNodeId), static_cast<chip::FabricIndex>(jFabricIndex));
    err = getICDClientStorage()->DeleteEntry(scopedNodeId);
    if (err != CHIP_NO_ERROR)
    {
        ChipLogError(Controller, "ClearICDClientInfo error!: %" CHIP_ERROR_FORMAT, err.Format());
    }
    return err;
}

CHIP_ERROR ParseICDClientInfo(JNIEnv * env, jint jFabricIndex, jobject jIcdClientInfo, chip::app::ICDClientInfo & icdClientInfo)
{
    VerifyOrReturnError(jIcdClientInfo != nullptr, CHIP_ERROR_INVALID_ARGUMENT);

    jmethodID getPeerNodeIdMethod       = nullptr;
    jmethodID getStartCounterMethod     = nullptr;
    jmethodID getOffsetMethod           = nullptr;
    jmethodID getMonitoredSubjectMethod = nullptr;
    jmethodID getIcdAesKeyMethod        = nullptr;
    jmethodID getIcdHmacKeyMethod       = nullptr;

    ReturnErrorOnFailure(
        chip::JniReferences::GetInstance().FindMethod(env, jIcdClientInfo, "getPeerNodeId", "()J", &getPeerNodeIdMethod));
    ReturnErrorOnFailure(
        chip::JniReferences::GetInstance().FindMethod(env, jIcdClientInfo, "getStartCounter", "()J", &getStartCounterMethod));
    ReturnErrorOnFailure(chip::JniReferences::GetInstance().FindMethod(env, jIcdClientInfo, "getOffset", "()J", &getOffsetMethod));
    ReturnErrorOnFailure(chip::JniReferences::GetInstance().FindMethod(env, jIcdClientInfo, "getMonitoredSubject", "()J",
                                                                       &getMonitoredSubjectMethod));
    ReturnErrorOnFailure(
        chip::JniReferences::GetInstance().FindMethod(env, jIcdClientInfo, "getIcdAesKey", "()[B", &getIcdAesKeyMethod));
    ReturnErrorOnFailure(
        chip::JniReferences::GetInstance().FindMethod(env, jIcdClientInfo, "getIcdHmacKey", "()[B", &getIcdHmacKeyMethod));

    jlong jPeerNodeId       = env->CallLongMethod(jIcdClientInfo, getPeerNodeIdMethod);
    jlong jStartCounter     = env->CallLongMethod(jIcdClientInfo, getStartCounterMethod);
    jlong jOffset           = env->CallLongMethod(jIcdClientInfo, getOffsetMethod);
    jlong jMonitoredSubject = env->CallLongMethod(jIcdClientInfo, getMonitoredSubjectMethod);
    jbyteArray jIcdAesKey   = static_cast<jbyteArray>(env->CallObjectMethod(jIcdClientInfo, getIcdAesKeyMethod));
    jbyteArray jIcdHmacKey  = static_cast<jbyteArray>(env->CallObjectMethod(jIcdClientInfo, getIcdHmacKeyMethod));

    chip::ScopedNodeId scopedNodeId(static_cast<chip::NodeId>(jPeerNodeId), static_cast<chip::FabricIndex>(jFabricIndex));
    chip::JniByteArray jniIcdAesKey(env, jIcdAesKey);
    chip::JniByteArray jniIcdHmacKey(env, jIcdHmacKey);

    icdClientInfo.peer_node         = scopedNodeId;
    icdClientInfo.start_icd_counter = static_cast<uint32_t>(jStartCounter);
    icdClientInfo.offset            = static_cast<uint32_t>(jOffset);
    icdClientInfo.monitored_subject = static_cast<uint64_t>(jMonitoredSubject);
    memcpy(icdClientInfo.aes_key_handle.AsMutable<chip::Crypto::Symmetric128BitsKeyByteArray>(), jniIcdAesKey.data(),
           sizeof(chip::Crypto::Symmetric128BitsKeyByteArray));
    memcpy(icdClientInfo.hmac_key_handle.AsMutable<chip::Crypto::Symmetric128BitsKeyByteArray>(), jniIcdHmacKey.data(),
           sizeof(chip::Crypto::Symmetric128BitsKeyByteArray));

    return CHIP_NO_ERROR;
}

chip::app::DefaultICDClientStorage * getICDClientStorage()
{
    return &sICDClientStorage;
}
