/*
 *
 *    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)
{
    return qvCHIP_Nvm_ValueExists(key, NULL);
}

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
