/*
 *
 *    Copyright (c) 2020-2021 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
 *          Platform-specific implementation of KVS for android.
 */

#include <platform/KeyValueStoreManager.h>

#include <algorithm>
#include <string.h>

#include <lib/support/Base64.h>
#include <lib/support/CHIPJNIError.h>
#include <lib/support/CodeUtils.h>
#include <lib/support/JniTypeWrappers.h>
#include <lib/support/logging/CHIPLogging.h>

namespace chip {
namespace DeviceLayer {
namespace PersistedStorage {

namespace {
constexpr size_t kMaxKvsValueBytes        = 4096;
constexpr size_t kMaxKvsValueEncodedChars = BASE64_ENCODED_LEN(kMaxKvsValueBytes) + 1;
} // namespace

KeyValueStoreManagerImpl KeyValueStoreManagerImpl::sInstance;

void KeyValueStoreManagerImpl::InitializeWithObject(jobject manager)
{
    JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread();
    VerifyOrReturn(env != nullptr, ChipLogError(DeviceLayer, "Failed to GetEnvForCurrentThread for KeyValueStoreManagerImpl"));
    VerifyOrReturn(mKeyValueStoreManagerObject.Init(manager) == CHIP_NO_ERROR,
                   ChipLogError(DeviceLayer, "Failed to Init KeyValueStoreManager"));

    jclass KeyValueStoreManagerClass = env->GetObjectClass(manager);
    VerifyOrReturn(KeyValueStoreManagerClass != nullptr,
                   ChipLogError(DeviceLayer, "Failed to get KeyValueStoreManager Java class"));

    mGetMethod = env->GetMethodID(KeyValueStoreManagerClass, "get", "(Ljava/lang/String;)Ljava/lang/String;");
    if (mGetMethod == nullptr)
    {
        ChipLogError(DeviceLayer, "Failed to access KeyValueStoreManager 'get' method");
        env->ExceptionClear();
    }

    mSetMethod = env->GetMethodID(KeyValueStoreManagerClass, "set", "(Ljava/lang/String;Ljava/lang/String;)V");
    if (mSetMethod == nullptr)
    {
        ChipLogError(DeviceLayer, "Failed to access KeyValueStoreManager 'set' method");
        env->ExceptionClear();
    }

    mDeleteMethod = env->GetMethodID(KeyValueStoreManagerClass, "delete", "(Ljava/lang/String;)V");
    if (mDeleteMethod == nullptr)
    {
        ChipLogError(DeviceLayer, "Failed to access KeyValueStoreManager 'delete' method");
        env->ExceptionClear();
    }
}

CHIP_ERROR KeyValueStoreManagerImpl::_Get(const char * key, void * value, size_t value_size, size_t * read_bytes_size,
                                          size_t offset_bytes)
{
    CHIP_ERROR err = CHIP_NO_ERROR;
    ReturnErrorCodeIf(!mKeyValueStoreManagerObject.HasValidObjectRef(), CHIP_ERROR_INCORRECT_STATE);
    ReturnErrorCodeIf(mGetMethod == nullptr, CHIP_ERROR_INCORRECT_STATE);

    JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread();
    ReturnErrorCodeIf(env == nullptr, CHIP_JNI_ERROR_NO_ENV);

    chip::UtfString javaKey(env, key);

    jobject javaValue = env->CallObjectMethod(mKeyValueStoreManagerObject.ObjectRef(), mGetMethod, javaKey.jniValue());
    if (env->ExceptionCheck())
    {
        ChipLogError(DeviceLayer, "Java exception in KeyValueStoreManager::Get");
        env->ExceptionDescribe();
        env->ExceptionClear();
        return CHIP_JNI_ERROR_EXCEPTION_THROWN;
    }

    if (javaValue == nullptr)
    {
        return CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND;
    }

    chip::JniUtfString utfValue(env, (jstring) javaValue);
    const size_t utfValueLen = strlen(utfValue.c_str());

    if (utfValueLen > kMaxKvsValueEncodedChars)
    {
        ChipLogError(DeviceLayer, "Unexpected large value received from KeyValueStoreManager");
        return CHIP_ERROR_NO_MEMORY;
    }

    std::unique_ptr<uint8_t[]> buffer(new uint8_t[BASE64_MAX_DECODED_LEN(utfValueLen)]);
    uint16_t decodedLength = chip::Base64Decode(utfValue.c_str(), utfValueLen, buffer.get());
    if (decodedLength == UINT16_MAX)
    {
        ChipLogError(DeviceLayer, "KeyValueStoreManager base64 decoding failed");
        return CHIP_ERROR_INTEGRITY_CHECK_FAILED;
    }
    ReturnErrorCodeIf(offset_bytes != 0 && offset_bytes >= decodedLength, CHIP_ERROR_INVALID_ARGUMENT);
    size_t read_size = std::min<size_t>(value_size, decodedLength - offset_bytes);
    if (value_size + offset_bytes < decodedLength)
    {
        err = CHIP_ERROR_BUFFER_TOO_SMALL;
    }

    if (read_bytes_size != nullptr)
    {
        *read_bytes_size = read_size;
    }

    if (value != nullptr)
    {
        memcpy(value, buffer.get() + offset_bytes, read_size);
    }

    return err;
}

CHIP_ERROR KeyValueStoreManagerImpl::_Put(const char * key, const void * value, size_t value_size)
{
    ReturnErrorCodeIf(!mKeyValueStoreManagerObject.HasValidObjectRef(), CHIP_ERROR_INCORRECT_STATE);
    ReturnErrorCodeIf(mSetMethod == nullptr, CHIP_ERROR_INCORRECT_STATE);
    ReturnErrorCodeIf(value_size > kMaxKvsValueBytes, CHIP_ERROR_INVALID_ARGUMENT);

    JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread();
    ReturnErrorCodeIf(env == nullptr, CHIP_ERROR_INTERNAL);

    std::unique_ptr<char[]> buffer(new char[BASE64_ENCODED_LEN(value_size) + 1]);

    size_t length        = chip::Base64Encode(static_cast<const uint8_t *>(value), value_size, buffer.get());
    buffer.get()[length] = 0;

    UtfString utfKey(env, key);
    UtfString utfBase64Value(env, buffer.get());

    env->CallVoidMethod(mKeyValueStoreManagerObject.ObjectRef(), mSetMethod, utfKey.jniValue(), utfBase64Value.jniValue());

    if (env->ExceptionCheck())
    {
        ChipLogError(DeviceLayer, "Java exception in KeyValueStoreManager::Put");
        env->ExceptionDescribe();
        env->ExceptionClear();
        return CHIP_JNI_ERROR_EXCEPTION_THROWN;
    }

    return CHIP_NO_ERROR;
}

CHIP_ERROR KeyValueStoreManagerImpl::_Delete(const char * key)
{
    ReturnErrorCodeIf(!mKeyValueStoreManagerObject.HasValidObjectRef(), CHIP_ERROR_INCORRECT_STATE);
    ReturnErrorCodeIf(mDeleteMethod == nullptr, CHIP_ERROR_INCORRECT_STATE);

    JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread();
    ReturnErrorCodeIf(env == nullptr, CHIP_ERROR_INTERNAL);

    UtfString javaKey(env, key);

    env->CallVoidMethod(mKeyValueStoreManagerObject.ObjectRef(), mDeleteMethod, javaKey.jniValue());

    if (env->ExceptionCheck())
    {
        ChipLogError(DeviceLayer, "Java exception in KeyValueStoreManager::Delete");
        env->ExceptionDescribe();
        env->ExceptionClear();
        return CHIP_JNI_ERROR_EXCEPTION_THROWN;
    }

    return CHIP_NO_ERROR;
}

} // namespace PersistedStorage
} // namespace DeviceLayer
} // namespace chip
