/*
 *
 *    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 Zephyr
 */

#include <platform/internal/CHIPDeviceLayerInternal.h>

#include <lib/support/CodeUtils.h>
#include <lib/support/logging/CHIPLogging.h>
#include <system/SystemError.h>

#include <zephyr/settings/settings.h>

namespace chip {
namespace DeviceLayer {
namespace PersistedStorage {
namespace {

struct ReadEntry
{
    void * destination;           // destination address
    size_t destinationBufferSize; // size of destination buffer
    size_t readSize;              // [out] size of read entry value
    CHIP_ERROR result;            // [out] read result
};

struct DeleteSubtreeEntry
{
    int result;
};

// Random magic bytes to represent an empty value.
// It is needed because Zephyr settings subsystem does not distinguish an empty value from no value.
constexpr uint8_t kEmptyValue[]  = { 0x22, 0xa6, 0x54, 0xd1, 0x39 };
constexpr size_t kEmptyValueSize = sizeof(kEmptyValue);

// Prefix the input key with CHIP_DEVICE_CONFIG_SETTINGS_KEY "/"
CHIP_ERROR MakeFullKey(char (&fullKey)[SETTINGS_MAX_NAME_LEN + 1], const char * key)
{
    VerifyOrReturnError(key != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
    strcpy(fullKey, CHIP_DEVICE_CONFIG_SETTINGS_KEY "/");

    char * dest    = fullKey + strlen(CHIP_DEVICE_CONFIG_SETTINGS_KEY "/");
    char * destEnd = fullKey + SETTINGS_MAX_NAME_LEN;

    while (*key != '\0')
    {
        char keyChar = *key++;
        bool escape  = keyChar == '\\' || keyChar == '=';

        if (keyChar == '=')
        {
            // '=' character is forbidden in a Zephyr setting key, so it must be escaped with "\e".
            keyChar = 'e';
        }

        if (escape)
        {
            VerifyOrReturnError(dest < destEnd, CHIP_ERROR_INVALID_ARGUMENT);
            *dest++ = '\\';
        }

        VerifyOrReturnError(dest < destEnd, CHIP_ERROR_INVALID_ARGUMENT);
        *dest++ = keyChar;
    }

    *dest = 0;

    return CHIP_NO_ERROR;
}

int LoadEntryCallback(const char * name, size_t entrySize, settings_read_cb readCb, void * cbArg, void * param)
{
    ReadEntry & entry = *static_cast<ReadEntry *>(param);

    // If requested key X, process just node X and ignore all its descendants: X/*
    if (name != nullptr && *name != '\0')
        return 0;

    // Found requested key.
    uint8_t emptyValue[kEmptyValueSize];

    if (entrySize == kEmptyValueSize && readCb(cbArg, emptyValue, kEmptyValueSize) == kEmptyValueSize &&
        memcmp(emptyValue, kEmptyValue, kEmptyValueSize) == 0)
    {
        // Special case - an empty value represented by known magic bytes.
        entry.result = CHIP_NO_ERROR;

        // Return 1 to stop processing further keys
        return 1;
    }

    const ssize_t bytesRead = readCb(cbArg, entry.destination, entry.destinationBufferSize);
    entry.readSize          = bytesRead > 0 ? bytesRead : 0;

    if (entrySize > entry.destinationBufferSize)
    {
        entry.result = CHIP_ERROR_BUFFER_TOO_SMALL;
    }
    else
    {
        entry.result = bytesRead > 0 ? CHIP_NO_ERROR : CHIP_ERROR_PERSISTED_STORAGE_FAILED;
    }

    // Return 1 to stop processing further keys
    return 1;
}

int DeleteSubtreeCallback(const char * name, size_t /* entrySize */, settings_read_cb /* readCb */, void * /* cbArg */,
                          void * param)
{
    DeleteSubtreeEntry & entry = *static_cast<DeleteSubtreeEntry *>(param);
    char fullKey[SETTINGS_MAX_NAME_LEN + 1];

    // name comes from Zephyr settings subsystem so it is guaranteed to fit in the buffer.
    (void) snprintf(fullKey, sizeof(fullKey), CHIP_DEVICE_CONFIG_SETTINGS_KEY "/%s", name);
    const int result = settings_delete(fullKey);

    // Return the first error, but continue removing remaining keys anyway.
    if (entry.result == 0)
    {
        entry.result = result;
    }

    return 0;
}

} // namespace

KeyValueStoreManagerImpl KeyValueStoreManagerImpl::sInstance;

void KeyValueStoreManagerImpl::Init()
{
    VerifyOrDie(settings_subsys_init() == 0);
}

CHIP_ERROR KeyValueStoreManagerImpl::_Get(const char * key, void * value, size_t value_size, size_t * read_bytes_size,
                                          size_t offset_bytes) const
{
    // Offset and partial reads are not supported, for now just return NOT_IMPLEMENTED.
    // Support can be added in the future if this is needed.
    VerifyOrReturnError(offset_bytes == 0, CHIP_ERROR_NOT_IMPLEMENTED);

    char fullKey[SETTINGS_MAX_NAME_LEN + 1];
    ReturnErrorOnFailure(MakeFullKey(fullKey, key));

    ReadEntry entry{ value, value_size, 0, CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND };
    settings_load_subtree_direct(fullKey, LoadEntryCallback, &entry);

    // Assign readSize only in case read_bytes_size is not nullptr, as it is optional argument
    if (read_bytes_size)
    {
        *read_bytes_size = entry.readSize;
    }

    return entry.result;
}

CHIP_ERROR KeyValueStoreManagerImpl::_Put(const char * key, const void * value, size_t value_size)
{
    char fullKey[SETTINGS_MAX_NAME_LEN + 1];
    ReturnErrorOnFailure(MakeFullKey(fullKey, key));

    if (value_size == 0)
    {
        value      = kEmptyValue;
        value_size = kEmptyValueSize;
    }

    VerifyOrReturnError(settings_save_one(fullKey, value, value_size) == 0, CHIP_ERROR_PERSISTED_STORAGE_FAILED);

    return CHIP_NO_ERROR;
}

CHIP_ERROR KeyValueStoreManagerImpl::_Delete(const char * key)
{
    char fullKey[SETTINGS_MAX_NAME_LEN + 1];
    ReturnErrorOnFailure(MakeFullKey(fullKey, key));

    ReturnErrorCodeIf(Get(key, nullptr, 0) == CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND,
                      CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND);
    ReturnErrorCodeIf(settings_delete(fullKey) != 0, CHIP_ERROR_PERSISTED_STORAGE_FAILED);

    return CHIP_NO_ERROR;
}

CHIP_ERROR KeyValueStoreManagerImpl::DoFactoryReset()
{
    DeleteSubtreeEntry entry{ /* success */ 0 };
    int result = settings_load_subtree_direct(CHIP_DEVICE_CONFIG_SETTINGS_KEY, DeleteSubtreeCallback, &entry);

    if (result == 0)
    {
        result = entry.result;
    }

    return System::MapErrorZephyr(result);
}

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