/*
 *
 *    Copyright (c) 2020 Project CHIP Authors
 *
 *    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
 *          Utilities for accessing persisted device configuration on
 *          platforms based on the Qorvo QPG platforms.
 */
/* this file behaves like a config.h, comes first */
#include <platform/internal/CHIPDeviceLayerInternal.h>

#include <platform/qpg/qpgConfig.h>

#include <lib/core/CHIPEncoding.h>
#include <lib/core/CHIPSafeCasts.h>
#include <lib/support/CodeUtils.h>
#include <lib/support/logging/CHIPLogging.h>
#include <platform/internal/testing/ConfigUnitTest.h>

#include "FreeRTOS.h"
#include "qvCHIP.h"

namespace chip {
namespace DeviceLayer {
namespace Internal {

CHIP_ERROR QPGConfig::Init()
{
    const qvStatus_t status = qvCHIP_KvsInit();

    if (QV_STATUS_NO_ERROR == status)
    {
        return CHIP_NO_ERROR;
    }
    else if (QV_STATUS_BUFFER_TOO_SMALL == status)
    {
        return CHIP_ERROR_BUFFER_TOO_SMALL;
    }

    return CHIP_ERROR_INTERNAL;
}

CHIP_ERROR QPGConfig::ReadConfigValue(Key key, bool & val)
{
    uint16_t length;

    length = sizeof(bool);

    return MapNVMError(qvCHIP_Nvm_Restore(key, reinterpret_cast<uint8_t *>(&val), &length));
}

CHIP_ERROR QPGConfig::ReadConfigValue(Key key, uint32_t & val)
{
    uint16_t length;

    length = sizeof(uint32_t);

    return MapNVMError(qvCHIP_Nvm_Restore(key, reinterpret_cast<uint8_t *>(&val), &length));
}

CHIP_ERROR QPGConfig::ReadConfigValue(Key key, uint64_t & val)
{
    uint16_t length;

    length = sizeof(uint64_t);

    return MapNVMError(qvCHIP_Nvm_Restore(key, reinterpret_cast<uint8_t *>(&val), &length));
}

CHIP_ERROR QPGConfig::ReadConfigValueStr(Key key, char * buf, size_t bufSize, size_t & outLen)
{
    qvStatus_t res;
    uint16_t length;

    if ((buf == NULL) || (bufSize > UINT16_MAX))
    {
        return CHIP_ERROR_INVALID_ARGUMENT;
    }

    length = static_cast<uint16_t>(bufSize);
    res    = qvCHIP_Nvm_Restore(key, Uint8::from_char(buf), &length);
    if (length > bufSize)
    {
        return CHIP_ERROR_BUFFER_TOO_SMALL;
    }
    if (res == QV_STATUS_NO_ERROR)
    {
        outLen      = length;
        buf[outLen] = 0;
    }

    return MapNVMError(res);
}

CHIP_ERROR QPGConfig::ReadConfigValueBin(Key key, uint8_t * buf, size_t bufSize, size_t & outLen)
{
    uint8_t buffer[255];
    uint16_t length;
    qvStatus_t res;

    if ((buf == NULL) || (bufSize > UINT16_MAX))
    {
        return CHIP_ERROR_INVALID_ARGUMENT;
    }

    length = static_cast<uint16_t>(bufSize);

    res = qvCHIP_Nvm_Restore(key, buffer, &length);
    if (res == QV_STATUS_NO_ERROR)
    {
        outLen = length;
        if (outLen > bufSize)
        {
            return CHIP_ERROR_BUFFER_TOO_SMALL;
        }

        memcpy(buf, buffer, outLen);
        buf[outLen] = 0;
    }

    return MapNVMError(res);
}

CHIP_ERROR QPGConfig::WriteConfigValue(Key key, bool val)
{
    uint16_t length;

    length = sizeof(bool);

    return MapNVMError(qvCHIP_Nvm_Backup(key, reinterpret_cast<uint8_t *>(&val), length));
}

CHIP_ERROR QPGConfig::WriteConfigValue(Key key, uint32_t val)
{
    uint16_t length;

    length = sizeof(uint32_t);

    return MapNVMError(qvCHIP_Nvm_Backup(key, reinterpret_cast<uint8_t *>(&val), length));
}

CHIP_ERROR QPGConfig::WriteConfigValue(Key key, uint64_t val)
{
    uint16_t length;

    length = sizeof(uint64_t);

    return MapNVMError(qvCHIP_Nvm_Backup(key, reinterpret_cast<uint8_t *>(&val), length));
}

CHIP_ERROR QPGConfig::WriteConfigValueStr(Key key, const char * str)
{
    return WriteConfigValueStr(key, str, (str != NULL) ? strlen(str) : 0);
}

CHIP_ERROR QPGConfig::WriteConfigValueStr(Key key, const char * str, size_t strLen)
{
    if (strLen > UINT16_MAX)
    {
        return CHIP_ERROR_INVALID_ARGUMENT;
    }
    if (str == NULL)
    {
        qvCHIP_Nvm_ClearValue(key);
    }
    else
    {
        return MapNVMError(qvCHIP_Nvm_Backup(key, Uint8::from_const_char(str), static_cast<uint16_t>(strLen)));
    }

    return CHIP_NO_ERROR;
}

CHIP_ERROR QPGConfig::WriteConfigValueBin(Key key, const uint8_t * data, size_t dataLen)
{
    if (dataLen > UINT16_MAX)
    {
        return CHIP_ERROR_BUFFER_TOO_SMALL;
    }
    if (data == NULL)
    {
        qvCHIP_Nvm_ClearValue(key);
    }
    else
    {
        return MapNVMError(qvCHIP_Nvm_Backup(key, data, static_cast<uint16_t>(dataLen)));
    }

    return CHIP_NO_ERROR;
}

CHIP_ERROR QPGConfig::ClearConfigValue(Key key)
{
    qvCHIP_Nvm_ClearValue(key);
    return CHIP_NO_ERROR;
}

bool QPGConfig::ConfigValueExists(Key key)
{
    uint16_t dummy = 0;
    return qvCHIP_Nvm_ValueExists(key, &dummy);
}

CHIP_ERROR QPGConfig::FactoryResetConfig(void)
{
    for (Key key = kMinConfigKey_ChipConfig; key <= kMaxConfigKey_ChipConfig; key++)
    {
        ClearConfigValue(key);
    }

    return CHIP_NO_ERROR;
}

CHIP_ERROR QPGConfig::ForEachRecord(Key firstKey, Key lastKey, bool addNewRecord, ForEachRecordFunct funct)
{
    CHIP_ERROR err = CHIP_NO_ERROR;
    uint16_t length;

    for (Key nvmKey = firstKey; nvmKey <= lastKey; ++nvmKey)
    {
        if (qvCHIP_Nvm_ValueExists(nvmKey, &length))
        {
            if (!addNewRecord)
            {
                // Invoke the caller's function
                // (for retrieve,store,delete,enumerate GroupKey operations).
                err = funct(nvmKey, length);
            }
        }
        else
        {
            if (addNewRecord)
            {
                // Invoke caller's function
                // (for add GroupKey operation).
                err = funct(nvmKey, length);
            }
        }

        SuccessOrExit(err);
    }

exit:
    return err;
}

CHIP_ERROR QPGConfig::MapNVMError(qvStatus_t aStatus)
{
    switch (aStatus)
    {
    case QV_STATUS_NO_ERROR:
        return CHIP_NO_ERROR;
    case QV_STATUS_BUFFER_TOO_SMALL:
        return CHIP_ERROR_BUFFER_TOO_SMALL;
    case QV_STATUS_INVALID_ARGUMENT:
        return CHIP_ERROR_INVALID_ARGUMENT;
    case QV_STATUS_KEY_LEN_TOO_SMALL:
        return CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND;
    case QV_STATUS_INVALID_DATA:
        return CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND;
    default:
        break;
    }
    return CHIP_ERROR_INTERNAL;
}

void QPGConfig::RunConfigUnitTest()
{
    // Run common unit test
    ::chip::DeviceLayer::Internal::RunConfigUnitTest<QPGConfig>();
}

} // namespace Internal
} // namespace DeviceLayer
} // namespace chip
