/*
 *
 *    Copyright (c) 2021-2022 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 SILABS
 */

#include "MigrationManager.h"
#include <crypto/CHIPCryptoPAL.h>
#include <platform/CHIPDeviceLayer.h>
#include <platform/KeyValueStoreManager.h>
#include <platform/silabs/SilabsConfig.h>
#include <stdio.h>
#include <string.h>

using namespace ::chip;
using namespace ::chip::Crypto;
using namespace ::chip::DeviceLayer::Internal;

#define CONVERT_KEYMAP_INDEX_TO_NVM3KEY(index) (SilabsConfig::kConfigKey_KvsFirstKeySlot + index)
#define CONVERT_NVM3KEY_TO_KEYMAP_INDEX(nvm3Key) (nvm3Key - SilabsConfig::kConfigKey_KvsFirstKeySlot)

namespace chip {
namespace DeviceLayer {
namespace PersistedStorage {

KeyValueStoreManagerImpl KeyValueStoreManagerImpl::sInstance;
uint16_t mKvsKeyMap[KeyValueStoreManagerImpl::kMaxEntries] = { 0 };

CHIP_ERROR KeyValueStoreManagerImpl::Init(void)
{
    CHIP_ERROR err;
    err = SilabsConfig::Init();
    SuccessOrExit(err);

    Silabs::MigrationManager::GetMigrationInstance().applyMigrations();

    memset(mKvsKeyMap, 0, sizeof(mKvsKeyMap));
    size_t outLen;
    err = SilabsConfig::ReadConfigValueBin(SilabsConfig::kConfigKey_KvsStringKeyMap, reinterpret_cast<uint8_t *>(mKvsKeyMap),
                                           sizeof(mKvsKeyMap), outLen);

    if (err == CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND) // Initial boot
    {
        err = CHIP_NO_ERROR;
    }

exit:
    return err;
}

bool KeyValueStoreManagerImpl::IsValidKvsNvm3Key(uint32_t nvm3Key) const
{
    return ((SilabsConfig::kConfigKey_KvsFirstKeySlot <= nvm3Key) && (nvm3Key <= SilabsConfig::kConfigKey_KvsLastKeySlot));
}

uint16_t KeyValueStoreManagerImpl::hashKvsKeyString(const char * key) const
{
    uint8_t hash256[Crypto::kSHA256_Hash_Length] = { 0 };
    Crypto::Hash_SHA256(reinterpret_cast<const uint8_t *>(key), strlen(key), hash256);

    uint16_t hash16 = 0, i = 0;

    while (!hash16 && (i < (Crypto::kSHA256_Hash_Length - 1)))
    {
        hash16 = (hash256[i] | (hash256[i + 1] << 8));
        i++;
    }
    return hash16;
}

CHIP_ERROR KeyValueStoreManagerImpl::MapKvsKeyToNvm3(const char * key, uint16_t hash, uint32_t & nvm3Key, bool isSlotNeeded) const
{
    CHIP_ERROR err;
    char * strPrefix          = nullptr;
    uint8_t firstEmptyKeySlot = kMaxEntries;
    for (uint8_t keyIndex = 0; keyIndex < kMaxEntries; keyIndex++)
    {
        if (mKvsKeyMap[keyIndex] == hash)
        {
            uint32_t tempNvm3key = CONVERT_KEYMAP_INDEX_TO_NVM3KEY(keyIndex);
            VerifyOrDie(IsValidKvsNvm3Key(tempNvm3key) == true);

            size_t readCount;
            size_t length = strlen(key);
            if (strPrefix == nullptr)
            {
                // Use a calloc to initialize all bits to 0. alloc +1 for a null char
                strPrefix = static_cast<char *>(Platform::MemoryCalloc(1, length + 1));
                VerifyOrDie(strPrefix != nullptr);
            }

            // Collision prevention
            // Read the data from NVM3 it should be prefixed by the kvsString
            // else we will look for another matching hash in the map
            SilabsConfig::ReadConfigValueBin(tempNvm3key, reinterpret_cast<uint8_t *>(strPrefix), length, readCount, 0);
            if (strcmp(key, strPrefix) == 0)
            {
                // String matches we have confirmed the hash pointed us the right key data
                nvm3Key = tempNvm3key;
                Platform::MemoryFree(strPrefix);
                return CHIP_NO_ERROR;
            }
        }

        if (isSlotNeeded && (firstEmptyKeySlot == kMaxEntries) && (mKvsKeyMap[keyIndex] == 0))
        {
            firstEmptyKeySlot = keyIndex;
        }
    }

    Platform::MemoryFree(strPrefix);

    if (isSlotNeeded)
    {
        if (firstEmptyKeySlot != kMaxEntries)
        {
            nvm3Key = CONVERT_KEYMAP_INDEX_TO_NVM3KEY(firstEmptyKeySlot);
            VerifyOrDie(IsValidKvsNvm3Key(nvm3Key) == true);
            err = CHIP_NO_ERROR;
        }
        else
        {
            err = CHIP_ERROR_PERSISTED_STORAGE_FAILED;
        }
    }
    else
    {
        err = CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND;
    }
    return err;
}

void KeyValueStoreManagerImpl::ForceKeyMapSave()
{
    OnScheduledKeyMapSave(nullptr, nullptr);
}

void KeyValueStoreManagerImpl::OnScheduledKeyMapSave(System::Layer * systemLayer, void * appState)
{
    SilabsConfig::WriteConfigValueBin(SilabsConfig::kConfigKey_KvsStringKeyMap, reinterpret_cast<const uint8_t *>(mKvsKeyMap),
                                      sizeof(mKvsKeyMap));
}

void KeyValueStoreManagerImpl::ScheduleKeyMapSave(void)
{
    /*
        During commissioning, the key map will be modified multiples times subsequently.
        Commit the key map in nvm once it as stabilized.
    */
    SystemLayer().StartTimer(
        std::chrono::duration_cast<System::Clock::Timeout>(System::Clock::Seconds32(SILABS_KVS_SAVE_DELAY_SECONDS)),
        KeyValueStoreManagerImpl::OnScheduledKeyMapSave, NULL);
}

CHIP_ERROR KeyValueStoreManagerImpl::_Get(const char * key, void * value, size_t value_size, size_t * read_bytes_size,
                                          size_t offset_bytes) const
{
    VerifyOrReturnError(key != nullptr, CHIP_ERROR_INVALID_ARGUMENT);

    uint32_t nvm3Key;
    uint16_t hash  = hashKvsKeyString(key);
    CHIP_ERROR err = MapKvsKeyToNvm3(key, hash, nvm3Key);
    VerifyOrReturnError(err == CHIP_NO_ERROR, err);

    size_t outLen;
    // The user doesn't need the KeyString prefix, Read data after it
    size_t KeyStringLen = strlen(key);
    err                 = SilabsConfig::ReadConfigValueBin(nvm3Key, reinterpret_cast<uint8_t *>(value), value_size, outLen,
                                           (offset_bytes + KeyStringLen));
    if (read_bytes_size)
    {
        *read_bytes_size = outLen;
    }

    if (err == CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND)
    {
        return CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND;
    }

    return err;
}

CHIP_ERROR KeyValueStoreManagerImpl::_Put(const char * key, const void * value, size_t value_size)
{
    VerifyOrReturnError(key != nullptr, CHIP_ERROR_INVALID_ARGUMENT);

    uint32_t nvm3Key;
    uint16_t hash  = hashKvsKeyString(key);
    CHIP_ERROR err = MapKvsKeyToNvm3(key, hash, nvm3Key, /* isSlotNeeded */ true);
    VerifyOrReturnError(err == CHIP_NO_ERROR, err);

    // add the string Key as prefix to the stored data as a collision prevention mechanism.
    size_t keyStringLen    = strlen(key);
    uint8_t * prefixedData = static_cast<uint8_t *>(Platform::MemoryAlloc(keyStringLen + value_size));
    VerifyOrDie(prefixedData != nullptr);
    memcpy(prefixedData, key, keyStringLen);
    memcpy(prefixedData + keyStringLen, value, value_size);

    err = SilabsConfig::WriteConfigValueBin(nvm3Key, prefixedData, keyStringLen + value_size);
    if (err == CHIP_NO_ERROR)
    {
        uint32_t keyIndex    = CONVERT_NVM3KEY_TO_KEYMAP_INDEX(nvm3Key);
        mKvsKeyMap[keyIndex] = hash;
        ScheduleKeyMapSave();
    }
    Platform::MemoryFree(prefixedData);
    return err;
}

CHIP_ERROR KeyValueStoreManagerImpl::_Delete(const char * key)
{
    VerifyOrReturnError(key != nullptr, CHIP_ERROR_INVALID_ARGUMENT);

    uint32_t nvm3Key;
    uint16_t hash  = hashKvsKeyString(key);
    CHIP_ERROR err = MapKvsKeyToNvm3(key, hash, nvm3Key);
    VerifyOrReturnError(err == CHIP_NO_ERROR, err);

    err = SilabsConfig::ClearConfigValue(nvm3Key);
    if (err == CHIP_NO_ERROR)
    {
        uint32_t keyIndex    = CONVERT_NVM3KEY_TO_KEYMAP_INDEX(nvm3Key);
        mKvsKeyMap[keyIndex] = 0;
        ScheduleKeyMapSave();
    }

    return err;
}

void KeyValueStoreManagerImpl::ErasePartition(void)
{
    // Iterate over all the Matter Kvs nvm3 records and delete each one...
    for (uint32_t nvm3Key = SilabsConfig::kMinConfigKey_MatterKvs; nvm3Key <= SilabsConfig::kMaxConfigKey_MatterKvs; nvm3Key++)
    {
        SilabsConfig::ClearConfigValue(nvm3Key);
    }

    memset(mKvsKeyMap, 0, sizeof(mKvsKeyMap));
}

void KeyValueStoreManagerImpl::KvsMapMigration(void)
{
    size_t readlen                                                                        = 0;
    constexpr uint8_t oldMaxEntires                                                       = 120;
    char mKvsStoredKeyString[oldMaxEntires][PersistentStorageDelegate::kKeyLengthMax + 1] = { 0 };
    CHIP_ERROR err =
        SilabsConfig::ReadConfigValueBin(SilabsConfig::kConfigKey_KvsStringKeyMap, reinterpret_cast<uint8_t *>(mKvsStoredKeyString),
                                         sizeof(mKvsStoredKeyString), readlen);

    if (err == CHIP_NO_ERROR)
    {
        for (uint8_t i = 0; i < oldMaxEntires; i++)
        {
            if (mKvsStoredKeyString[i][0] != 0)
            {
                size_t dataLen   = 0;
                uint32_t nvm3Key = CONVERT_KEYMAP_INDEX_TO_NVM3KEY(i);

                if (SilabsConfig::ConfigValueExists(nvm3Key, dataLen))
                {
                    // Read old data and prefix it with the string Key for the collision prevention mechanism.
                    size_t keyStringLen    = strlen(mKvsStoredKeyString[i]);
                    uint8_t * prefixedData = static_cast<uint8_t *>(Platform::MemoryAlloc(keyStringLen + dataLen));
                    VerifyOrDie(prefixedData != nullptr);
                    memcpy(prefixedData, mKvsStoredKeyString[i], keyStringLen);

                    SilabsConfig::ReadConfigValueBin(nvm3Key, prefixedData + keyStringLen, dataLen, readlen);
                    SilabsConfig::WriteConfigValueBin(nvm3Key, prefixedData, keyStringLen + dataLen);
                    mKvsKeyMap[i] = KeyValueStoreMgrImpl().hashKvsKeyString(mKvsStoredKeyString[i]);
                    Platform::MemoryFree(prefixedData);
                }
            }
        }
        ForceKeyMapSave();
    }
    else if (err != CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND)
    {
        // Error reading the old String Keymap. Cannot not resolve stored data for migration.
        ChipLogError(DeviceLayer, "Migration failed ! Kvs Key map could not be recovered %" CHIP_ERROR_FORMAT, err.Format());
        // start with a fresh kvs section.
        KeyValueStoreMgrImpl().ErasePartition();
    }
}

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