/*
 *
 *    Copyright (c) 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 key value storage implementation for K32W
 */
/* this file behaves like a config.h, comes first */
#include <platform/internal/CHIPDeviceLayerInternal.h>

#include <lib/support/CHIPMem.h>
#include <platform/KeyValueStoreManager.h>
#include <platform/nxp/k32w/k32w0/K32W0Config.h>
#include <platform/nxp/k32w/k32w0/KeyValueStoreManagerImpl.h>
#include <platform/nxp/k32w/k32w0/RamStorage.h>
#include <string>

namespace chip {
namespace DeviceLayer {
namespace PersistedStorage {

constexpr size_t kMaxNumberOfKeys  = 200;
constexpr size_t kMaxKeyValueBytes = 255;

Internal::RamStorage KeyValueStoreManagerImpl::sKeysStorage         = { kNvmId_KvsKeys, "Keys" };
Internal::RamStorage KeyValueStoreManagerImpl::sValuesStorage       = { kNvmId_KvsValues, "Values" };
Internal::RamStorage KeyValueStoreManagerImpl::sSubscriptionStorage = { kNvmId_KvsSubscription, "Subscriptions" };
Internal::RamStorage KeyValueStoreManagerImpl::sGroupsStorage       = { kNvmId_KvsGroups, "Groups" };

KeyValueStoreManagerImpl KeyValueStoreManagerImpl::sInstance;

#if CONFIG_CHIP_K32W0_KVS_MOVE_KEYS_TO_SPECIFIC_STORAGE
static CHIP_ERROR MoveKeysAndValues();
#endif // CONFIG_CHIP_K32W0_KVS_MOVE_KEYS_TO_SPECIFIC_STORAGE

static inline bool IsKeyRelatedToGroups(const char * key)
{
    std::string _key(key);
    if (_key.find("f/") != 0)
        return false;

    return (_key.find("/g") != std::string::npos) || (_key.find("/k/") != std::string::npos);
}

static inline bool IsKeyRelatedToSubscriptions(const char * key)
{
    std::string _key(key);
    return _key.find("g/su") == 0;
}

static Internal::RamStorage * GetValStorage(const char * key)
{
    Internal::RamStorage * storage = nullptr;

    storage = IsKeyRelatedToSubscriptions(key) ? &KeyValueStoreManagerImpl::sSubscriptionStorage
                                               : &KeyValueStoreManagerImpl::sValuesStorage;
    storage = IsKeyRelatedToGroups(key) ? &KeyValueStoreManagerImpl::sGroupsStorage : storage;

    return storage;
}

static Internal::RamStorage * GetKeyStorage(const char * key)
{
    Internal::RamStorage * storage = nullptr;

    storage = IsKeyRelatedToSubscriptions(key) ? &KeyValueStoreManagerImpl::sSubscriptionStorage
                                               : &KeyValueStoreManagerImpl::sKeysStorage;
    storage = IsKeyRelatedToGroups(key) ? &KeyValueStoreManagerImpl::sGroupsStorage : storage;

    return storage;
}

uint16_t GetStringKeyId(const char * key, uint16_t * freeId)
{
    CHIP_ERROR err                    = CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND;
    uint8_t keyId                     = 0;
    bool bFreeIdxFound                = false;
    char keyString[kMaxKeyValueBytes] = { 0 };
    uint16_t pdmInternalId;

    for (keyId = 0; keyId < kMaxNumberOfKeys; keyId++)
    {
        uint16_t keyStringSize = kMaxKeyValueBytes;
        pdmInternalId          = Internal::RamStorageKey::GetInternalId(kKeyId_KvsKeys, keyId);
        err                    = GetKeyStorage(key)->Read(pdmInternalId, 0, (uint8_t *) keyString, &keyStringSize);

        if (err == CHIP_NO_ERROR)
        {
            if (strcmp(key, keyString) == 0)
            {
                // found the entry we are looking for
                break;
            }
        }
        else if ((NULL != freeId) && (false == bFreeIdxFound))
        {
            bFreeIdxFound = true;
            *freeId       = keyId;
        }
    }
    return keyId;
}

CHIP_ERROR KeyValueStoreManagerImpl::Init()
{
    CHIP_ERROR err = CHIP_NO_ERROR;

    err = sKeysStorage.Init(Internal::RamStorage::kRamBufferInitialSize);
    if (err != CHIP_NO_ERROR)
    {
        ChipLogProgress(DeviceLayer, "Cannot init KVS keys storage with id: %d. Error: %s", kNvmId_KvsKeys, ErrorStr(err));
    }

    err = sValuesStorage.Init(Internal::RamStorage::kRamBufferInitialSize, true);
    if (err != CHIP_NO_ERROR)
    {
        ChipLogProgress(DeviceLayer, "Cannot init KVS values storage with id: %d. Error: %s", kNvmId_KvsValues, ErrorStr(err));
    }

    err = sSubscriptionStorage.Init(Internal::RamStorage::kRamBufferInitialSize);
    if (err != CHIP_NO_ERROR)
    {
        ChipLogProgress(DeviceLayer, "Cannot init KVS subscription storage with id: %d. Error: %s", kNvmId_KvsSubscription,
                        ErrorStr(err));
    }

    err = sGroupsStorage.Init(Internal::RamStorage::kRamBufferInitialSize, true);
    if (err != CHIP_NO_ERROR)
    {
        ChipLogProgress(DeviceLayer, "Cannot init KVS groups storage with id: %d. Error: %s", kNvmId_KvsGroups, ErrorStr(err));
    }

#if CONFIG_CHIP_K32W0_KVS_MOVE_KEYS_TO_SPECIFIC_STORAGE
    ChipLogProgress(DeviceLayer, "Moving some keys to dedicated storage");
    MoveKeysAndValues();
#endif /* CONFIG_CHIP_K32W0_KVS_MOVE_KEYS_TO_SPECIFIC_STORAGE */

    return err;
}

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_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND;
    uint8_t keyId          = 0;
    uint16_t pdmInternalId = 0;
    uint16_t valueSize     = value_size;

    VerifyOrExit((key != NULL) && (value != NULL), err = CHIP_ERROR_INVALID_ARGUMENT);

    keyId = GetStringKeyId(key, NULL);

    if (keyId < kMaxNumberOfKeys)
    {
        /* Use kKeyId_KvsValues as base key id for all keys. */
        pdmInternalId = Internal::RamStorageKey::GetInternalId(kKeyId_KvsValues, keyId);
        ChipLogProgress(DeviceLayer, "KVS val: get [%s][%i][%s]", key, pdmInternalId, GetValStorage(key)->GetName());
        err              = GetValStorage(key)->Read(pdmInternalId, 0, (uint8_t *) value, &valueSize);
        *read_bytes_size = valueSize;
    }
    else
    {
        ChipLogProgress(DeviceLayer, "KVS key [%s] not found in persistent storage.", key);
    }

exit:
    ConvertError(err);
    return err;
}

CHIP_ERROR KeyValueStoreManagerImpl::_Put(const char * key, const void * value, size_t value_size)
{
    CHIP_ERROR err         = CHIP_ERROR_INVALID_ARGUMENT;
    bool_t putKey          = false;
    uint16_t pdmInternalId = 0;
    uint16_t freeKeyId;
    uint8_t keyId;

    VerifyOrExit((key != NULL) && (value != NULL), err = CHIP_ERROR_INVALID_ARGUMENT);

    keyId = GetStringKeyId(key, &freeKeyId);

    // Key does not exist. Write both key and value in persistent storage.
    if (kMaxNumberOfKeys == keyId)
    {
        putKey = true;
        keyId  = freeKeyId;
    }

    /* Use kKeyId_KvsValues as base key id for all keys. */
    pdmInternalId = Internal::RamStorageKey::GetInternalId(kKeyId_KvsValues, keyId);
    ChipLogProgress(DeviceLayer, "KVS val: set [%s][%i][%s]", key, pdmInternalId, GetValStorage(key)->GetName());
    err = GetValStorage(key)->Write(pdmInternalId, (uint8_t *) value, value_size);
    /* save the 'key' in flash such that it can be retrieved later on */
    if (err == CHIP_NO_ERROR)
    {
        if (putKey)
        {
            pdmInternalId = Internal::RamStorageKey::GetInternalId(kKeyId_KvsKeys, keyId);
            ChipLogProgress(DeviceLayer, "KVS key: set [%s][%i][%s]", key, pdmInternalId, GetKeyStorage(key)->GetName());

            err = GetKeyStorage(key)->Write(pdmInternalId, (uint8_t *) key, strlen(key) + 1);
            if (err != CHIP_NO_ERROR)
            {
                ChipLogProgress(DeviceLayer, "KVS key: error when setting [%s][%i]", key, pdmInternalId);
            }
        }
    }
    else
    {
        ChipLogProgress(DeviceLayer, "KVS val: error when setting [%s][%i]", key, pdmInternalId);
    }

exit:
    ConvertError(err);
    return err;
}

CHIP_ERROR KeyValueStoreManagerImpl::_Delete(const char * key)
{
    CHIP_ERROR err         = CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND;
    uint8_t keyId          = 0;
    uint16_t pdmInternalId = 0;

    VerifyOrExit((key != NULL), err = CHIP_ERROR_INVALID_ARGUMENT);

    keyId = GetStringKeyId(key, NULL);
    if (keyId < kMaxNumberOfKeys)
    {
        // entry exists so we can remove it
        pdmInternalId = Internal::RamStorageKey::GetInternalId(kKeyId_KvsKeys, keyId);

        ChipLogProgress(DeviceLayer, "KVS key: del [%s][%i][%s]", key, pdmInternalId, GetKeyStorage(key)->GetName());
        err = GetKeyStorage(key)->Delete(pdmInternalId, -1);

        /* also delete the 'key string' from flash */
        if (err == CHIP_NO_ERROR)
        {
            /* Use kKeyId_KvsValues as base key id for all keys. */
            pdmInternalId = Internal::RamStorageKey::GetInternalId(kKeyId_KvsValues, keyId);
            ChipLogProgress(DeviceLayer, "KVS val: del [%s][%i][%s]", key, pdmInternalId, GetValStorage(key)->GetName());

            err = GetValStorage(key)->Delete(pdmInternalId, -1);
            if (err != CHIP_NO_ERROR)
            {
                ChipLogProgress(DeviceLayer, "KVS val: error when deleting [%s][%i]", key, pdmInternalId);
            }
        }
        else
        {
            ChipLogProgress(DeviceLayer, "KVS key: error when deleting [%s][%i]", key, pdmInternalId);
        }
    }
exit:
    ConvertError(err);
    return err;
}

void KeyValueStoreManagerImpl::FactoryResetStorage(void)
{
    sKeysStorage.OnFactoryReset();
    sValuesStorage.OnFactoryReset();
    sSubscriptionStorage.OnFactoryReset();
    sGroupsStorage.OnFactoryReset();
}

void KeyValueStoreManagerImpl::ConvertError(CHIP_ERROR & err)
{
    if (err == CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND)
    {
        err = CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND;
    }
}

#if CONFIG_CHIP_K32W0_KVS_MOVE_KEYS_TO_SPECIFIC_STORAGE
static CHIP_ERROR MoveToDedicatedStorage(const char * key, uint8_t * buffer, uint16_t len, uint16_t keyId, uint16_t valId)
{
    ReturnErrorOnFailure(GetKeyStorage(key)->Write(keyId, (uint8_t *) key, strlen(key) + 1));

    ReturnErrorOnFailure(KeyValueStoreManagerImpl::sValuesStorage.Read(valId, 0, buffer, &len));
    ReturnErrorOnFailure(GetValStorage(key)->Write(valId, buffer, len));

    ReturnErrorOnFailure(KeyValueStoreManagerImpl::sKeysStorage.Delete(keyId, -1));
    ReturnErrorOnFailure(KeyValueStoreManagerImpl::sValuesStorage.Delete(valId, -1));

    return CHIP_NO_ERROR;
}

static CHIP_ERROR MoveKeysAndValues()
{
    uint16_t len                = 1024; // Should be enough for Matter keys
    uint16_t keyId              = 0;
    uint16_t valId              = 0;
    uint16_t keySize            = kMaxKeyValueBytes;
    char key[kMaxKeyValueBytes] = { 0 };
    Platform::ScopedMemoryBuffer<uint8_t> buffer;

    buffer.Calloc(len);
    ReturnErrorCodeIf(buffer.Get() == nullptr, CHIP_ERROR_NO_MEMORY);

    for (uint8_t id = 0; id < kMaxNumberOfKeys; id++)
    {
        keySize = kMaxKeyValueBytes;
        keyId   = Internal::RamStorageKey::GetInternalId(kKeyId_KvsKeys, id);
        valId   = Internal::RamStorageKey::GetInternalId(kKeyId_KvsValues, id);

        auto err = KeyValueStoreManagerImpl::sKeysStorage.Read(keyId, 0, (uint8_t *) key, &keySize);
        if (err == CHIP_NO_ERROR)
        {
            if (!IsKeyRelatedToGroups(key) && !IsKeyRelatedToSubscriptions(key))
                continue;

            err = MoveToDedicatedStorage(key, buffer.Get(), len, keyId, valId);
            VerifyOrDo(err != CHIP_NO_ERROR, ChipLogProgress(DeviceLayer, "Key [%s] was moved successfully", key));
            VerifyOrDo(err == CHIP_NO_ERROR, ChipLogProgress(DeviceLayer, "Error in moving key [%s] to dedicated storage", key));
        }
    }

    return CHIP_NO_ERROR;
}
#endif // CONFIG_CHIP_K32W0_KVS_MOVE_KEYS_TO_SPECIFIC_STORAGE

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