/*
 *
 *    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()
{
    // KVS will already be initialized in qvCHIP_Init before this is called from CHIP stack
    return CHIP_NO_ERROR;
}

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
