/*
 *
 *    Copyright (c) 2020-2022 Project CHIP Authors
 *    Copyright (c) 2019-2020 Google LLC.
 *    Copyright (c) 2018 Nest Labs, Inc.
 *    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
 *          Utilities for interacting with the the ESP32 "NVS" key-value store.
 */
/* this file behaves like a config.h, comes first */
#include <platform/internal/CHIPDeviceLayerInternal.h>

#include <platform/ESP32/ESP32Config.h>

#include <lib/core/CHIPEncoding.h>
#include <lib/support/CHIPMem.h>
#include <lib/support/CHIPMemString.h>
#include <lib/support/CodeUtils.h>
#include <lib/support/logging/CHIPLogging.h>
#include <platform/ESP32/ESP32Utils.h>
#include <platform/ESP32/ScopedNvsHandle.h>

#include "nvs.h"
#include "nvs_flash.h"

namespace chip {
namespace DeviceLayer {
namespace Internal {

// *** CAUTION ***: Changing the names or namespaces of these values will *break* existing devices.

// NVS namespaces used to store device configuration information.
const char ESP32Config::kConfigNamespace_ChipFactory[]  = "chip-factory";
const char ESP32Config::kConfigNamespace_ChipConfig[]   = "chip-config";
const char ESP32Config::kConfigNamespace_ChipCounters[] = "chip-counters";

// Keys stored in the chip-factory namespace
const ESP32Config::Key ESP32Config::kConfigKey_SerialNum             = { kConfigNamespace_ChipFactory, "serial-num" };
const ESP32Config::Key ESP32Config::kConfigKey_MfrDeviceId           = { kConfigNamespace_ChipFactory, "device-id" };
const ESP32Config::Key ESP32Config::kConfigKey_MfrDeviceCert         = { kConfigNamespace_ChipFactory, "device-cert" };
const ESP32Config::Key ESP32Config::kConfigKey_MfrDeviceICACerts     = { kConfigNamespace_ChipFactory, "device-ca-certs" };
const ESP32Config::Key ESP32Config::kConfigKey_MfrDevicePrivateKey   = { kConfigNamespace_ChipFactory, "device-key" };
const ESP32Config::Key ESP32Config::kConfigKey_HardwareVersion       = { kConfigNamespace_ChipFactory, "hardware-ver" };
const ESP32Config::Key ESP32Config::kConfigKey_HardwareVersionString = { kConfigNamespace_ChipFactory, "hw-ver-str" };
const ESP32Config::Key ESP32Config::kConfigKey_ManufacturingDate     = { kConfigNamespace_ChipFactory, "mfg-date" };
const ESP32Config::Key ESP32Config::kConfigKey_SetupPinCode          = { kConfigNamespace_ChipFactory, "pin-code" };
const ESP32Config::Key ESP32Config::kConfigKey_SetupDiscriminator    = { kConfigNamespace_ChipFactory, "discriminator" };
const ESP32Config::Key ESP32Config::kConfigKey_Spake2pIterationCount = { kConfigNamespace_ChipFactory, "iteration-count" };
const ESP32Config::Key ESP32Config::kConfigKey_Spake2pSalt           = { kConfigNamespace_ChipFactory, "salt" };
const ESP32Config::Key ESP32Config::kConfigKey_Spake2pVerifier       = { kConfigNamespace_ChipFactory, "verifier" };
const ESP32Config::Key ESP32Config::kConfigKey_DACCert               = { kConfigNamespace_ChipFactory, "dac-cert" };
const ESP32Config::Key ESP32Config::kConfigKey_DACPrivateKey         = { kConfigNamespace_ChipFactory, "dac-key" };
const ESP32Config::Key ESP32Config::kConfigKey_DACPublicKey          = { kConfigNamespace_ChipFactory, "dac-pub-key" };
const ESP32Config::Key ESP32Config::kConfigKey_PAICert               = { kConfigNamespace_ChipFactory, "pai-cert" };
const ESP32Config::Key ESP32Config::kConfigKey_CertDeclaration       = { kConfigNamespace_ChipFactory, "cert-dclrn" };
const ESP32Config::Key ESP32Config::kConfigKey_VendorId              = { kConfigNamespace_ChipFactory, "vendor-id" };
const ESP32Config::Key ESP32Config::kConfigKey_VendorName            = { kConfigNamespace_ChipFactory, "vendor-name" };
const ESP32Config::Key ESP32Config::kConfigKey_ProductId             = { kConfigNamespace_ChipFactory, "product-id" };
const ESP32Config::Key ESP32Config::kConfigKey_ProductName           = { kConfigNamespace_ChipFactory, "product-name" };
const ESP32Config::Key ESP32Config::kConfigKey_UniqueId              = { kConfigNamespace_ChipFactory, "unique-id" };

// Keys stored in the chip-config namespace
const ESP32Config::Key ESP32Config::kConfigKey_ServiceConfig      = { kConfigNamespace_ChipConfig, "service-config" };
const ESP32Config::Key ESP32Config::kConfigKey_PairedAccountId    = { kConfigNamespace_ChipConfig, "account-id" };
const ESP32Config::Key ESP32Config::kConfigKey_ServiceId          = { kConfigNamespace_ChipConfig, "service-id" };
const ESP32Config::Key ESP32Config::kConfigKey_LastUsedEpochKeyId = { kConfigNamespace_ChipConfig, "last-ek-id" };
const ESP32Config::Key ESP32Config::kConfigKey_FailSafeArmed      = { kConfigNamespace_ChipConfig, "fail-safe-armed" };
const ESP32Config::Key ESP32Config::kConfigKey_WiFiStationSecType = { kConfigNamespace_ChipConfig, "sta-sec-type" };
const ESP32Config::Key ESP32Config::kConfigKey_RegulatoryLocation = { kConfigNamespace_ChipConfig, "reg-location" };
const ESP32Config::Key ESP32Config::kConfigKey_CountryCode        = { kConfigNamespace_ChipConfig, "country-code" };

// Keys stored in the Chip-counters namespace
const ESP32Config::Key ESP32Config::kCounterKey_RebootCount           = { kConfigNamespace_ChipCounters, "reboot-count" };
const ESP32Config::Key ESP32Config::kCounterKey_UpTime                = { kConfigNamespace_ChipCounters, "up-time" };
const ESP32Config::Key ESP32Config::kCounterKey_TotalOperationalHours = { kConfigNamespace_ChipCounters, "total-hours" };

const char * ESP32Config::GetPartitionLabelByNamespace(const char * ns)
{
    if (strcmp(ns, kConfigNamespace_ChipFactory) == 0)
    {
        return CHIP_DEVICE_CONFIG_CHIP_FACTORY_NAMESPACE_PARTITION;
    }
    else if (strcmp(ns, kConfigNamespace_ChipConfig) == 0)
    {
        return CHIP_DEVICE_CONFIG_CHIP_CONFIG_NAMESPACE_PARTITION;
    }
    else if (strcmp(ns, kConfigNamespace_ChipCounters))
    {
        return CHIP_DEVICE_CONFIG_CHIP_COUNTERS_NAMESPACE_PARTITION;
    }

    return NVS_DEFAULT_PART_NAME;
}

CHIP_ERROR ESP32Config::ReadConfigValue(Key key, bool & val)
{
    ScopedNvsHandle handle;
    uint32_t intVal;

    ReturnErrorOnFailure(handle.Open(key.Namespace, NVS_READONLY, GetPartitionLabelByNamespace(key.Namespace)));

    esp_err_t err = nvs_get_u32(handle, key.Name, &intVal);
    if (err == ESP_ERR_NVS_NOT_FOUND)
    {
        return CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND;
    }
    ReturnMappedErrorOnFailure(err);

    val = (intVal != 0);

    return CHIP_NO_ERROR;
}

CHIP_ERROR ESP32Config::ReadConfigValue(Key key, uint32_t & val)
{
    ScopedNvsHandle handle;

    ReturnErrorOnFailure(handle.Open(key.Namespace, NVS_READONLY, GetPartitionLabelByNamespace(key.Namespace)));

    esp_err_t err = nvs_get_u32(handle, key.Name, &val);
    if (err == ESP_ERR_NVS_NOT_FOUND)
    {
        return CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND;
    }
    ReturnMappedErrorOnFailure(err);

    return CHIP_NO_ERROR;
}

CHIP_ERROR ESP32Config::ReadConfigValue(Key key, uint64_t & val)
{
    ScopedNvsHandle handle;

    ReturnErrorOnFailure(handle.Open(key.Namespace, NVS_READONLY, GetPartitionLabelByNamespace(key.Namespace)));

    // Special case the MfrDeviceId value, optionally allowing it to be read as a blob containing
    // a 64-bit big-endian integer, instead of a u64 value.
    //
    // The ESP32 development environment provides a tool for pre-populating the NVS partition using
    // values from a CSV file.  This tool is convenient for provisioning devices during manufacturing.
    // However currently the tool does not support pre-populating u64 values such as MfrDeviceId.
    // Thus we allow MfrDeviceId to be stored as a blob instead.
    //
    if (key == kConfigKey_MfrDeviceId)
    {
        uint8_t deviceIdBytes[sizeof(uint64_t)];
        size_t deviceIdLen = sizeof(deviceIdBytes);
        esp_err_t err      = nvs_get_blob(handle, key.Name, deviceIdBytes, &deviceIdLen);
        if (err == ESP_OK)
        {
            VerifyOrReturnError(deviceIdLen == sizeof(deviceIdBytes), ESP32Utils::MapError(ESP_ERR_NVS_INVALID_LENGTH));
            val = Encoding::BigEndian::Get64(deviceIdBytes);
            return CHIP_NO_ERROR;
        }
    }

    esp_err_t err = nvs_get_u64(handle, key.Name, &val);
    if (err == ESP_ERR_NVS_NOT_FOUND)
    {
        return CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND;
    }
    ReturnMappedErrorOnFailure(err);

    return CHIP_NO_ERROR;
}

CHIP_ERROR ESP32Config::ReadConfigValueStr(Key key, char * buf, size_t bufSize, size_t & outLen)
{
    ScopedNvsHandle handle;

    ReturnErrorOnFailure(handle.Open(key.Namespace, NVS_READONLY, GetPartitionLabelByNamespace(key.Namespace)));

    outLen = bufSize;

    // If buf is null, nvs_get_str() sets the outLen to required length to fit the string
    esp_err_t err = nvs_get_str(handle, key.Name, buf, &outLen);
    if (err == ESP_ERR_NVS_NOT_FOUND)
    {
        outLen = 0;
        return CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND;
    }
    if (buf != NULL)
    {
        if (err == ESP_ERR_NVS_INVALID_LENGTH)
        {
            return CHIP_ERROR_BUFFER_TOO_SMALL;
        }
        ReturnErrorCodeIf(buf[outLen - 1] != 0, CHIP_ERROR_INVALID_STRING_LENGTH);
        ReturnMappedErrorOnFailure(err);
    }

    outLen -= 1; // Don't count trailing nul.

    return CHIP_NO_ERROR;
}

CHIP_ERROR ESP32Config::ReadConfigValueBin(Key key, uint8_t * buf, size_t bufSize, size_t & outLen)
{
    ScopedNvsHandle handle;

    ReturnErrorOnFailure(handle.Open(key.Namespace, NVS_READONLY, GetPartitionLabelByNamespace(key.Namespace)));

    outLen = bufSize;
    // If buf is null, nvs_get_blob() sets the outLen to required length to fit the blob
    esp_err_t err = nvs_get_blob(handle, key.Name, buf, &outLen);
    if (err == ESP_ERR_NVS_NOT_FOUND)
    {
        outLen = 0;
        return CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND;
    }
    if (buf != NULL)
    {
        if (err == ESP_ERR_NVS_INVALID_LENGTH)
        {
            return CHIP_ERROR_BUFFER_TOO_SMALL;
        }
        ReturnMappedErrorOnFailure(err);
    }

    return CHIP_NO_ERROR;
}

CHIP_ERROR ESP32Config::WriteConfigValue(Key key, bool val)
{
    ScopedNvsHandle handle;

    ReturnErrorOnFailure(handle.Open(key.Namespace, NVS_READWRITE, GetPartitionLabelByNamespace(key.Namespace)));
    ReturnMappedErrorOnFailure(nvs_set_u32(handle, key.Name, val ? 1 : 0));

    // Commit the value to the persistent store.
    ReturnMappedErrorOnFailure(nvs_commit(handle));

    ChipLogProgress(DeviceLayer, "NVS set: %s/%s = %s", key.Namespace, key.Name, val ? "true" : "false");
    return CHIP_NO_ERROR;
}

CHIP_ERROR ESP32Config::WriteConfigValue(Key key, uint32_t val)
{
    ScopedNvsHandle handle;

    ReturnErrorOnFailure(handle.Open(key.Namespace, NVS_READWRITE, GetPartitionLabelByNamespace(key.Namespace)));
    ReturnMappedErrorOnFailure(nvs_set_u32(handle, key.Name, val));

    // Commit the value to the persistent store.
    ReturnMappedErrorOnFailure(nvs_commit(handle));

    ChipLogProgress(DeviceLayer, "NVS set: %s/%s = %" PRIu32 " (0x%" PRIX32 ")", key.Namespace, key.Name, val, val);
    return CHIP_NO_ERROR;
}

CHIP_ERROR ESP32Config::WriteConfigValue(Key key, uint64_t val)
{
    ScopedNvsHandle handle;

    ReturnErrorOnFailure(handle.Open(key.Namespace, NVS_READWRITE, GetPartitionLabelByNamespace(key.Namespace)));
    ReturnMappedErrorOnFailure(nvs_set_u64(handle, key.Name, val));

    // Commit the value to the persistent store.
    ReturnMappedErrorOnFailure(nvs_commit(handle));

    ChipLogProgress(DeviceLayer, "NVS set: %s/%s = %" PRIu64 " (0x%" PRIX64 ")", key.Namespace, key.Name, val, val);
    return CHIP_NO_ERROR;
}

CHIP_ERROR ESP32Config::WriteConfigValueStr(Key key, const char * str)
{
    if (str != NULL)
    {
        ScopedNvsHandle handle;

        ReturnErrorOnFailure(handle.Open(key.Namespace, NVS_READWRITE, GetPartitionLabelByNamespace(key.Namespace)));
        ReturnMappedErrorOnFailure(nvs_set_str(handle, key.Name, str));

        // Commit the value to the persistent store.
        ReturnMappedErrorOnFailure(nvs_commit(handle));

        ChipLogProgress(DeviceLayer, "NVS set: %s/%s = \"%s\"", key.Namespace, key.Name, str);
        return CHIP_NO_ERROR;
    }

    return ClearConfigValue(key);
}

CHIP_ERROR ESP32Config::WriteConfigValueStr(Key key, const char * str, size_t strLen)
{
    chip::Platform::ScopedMemoryBuffer<char> strCopy;

    if (str != NULL)
    {
        strCopy.Calloc(strLen + 1);
        VerifyOrReturnError(strCopy, CHIP_ERROR_NO_MEMORY);
        strncpy(strCopy.Get(), str, strLen);
    }
    return ESP32Config::WriteConfigValueStr(key, strCopy.Get());
}

CHIP_ERROR ESP32Config::WriteConfigValueBin(Key key, const uint8_t * data, size_t dataLen)
{
    ScopedNvsHandle handle;

    if (data != NULL)
    {
        ReturnErrorOnFailure(handle.Open(key.Namespace, NVS_READWRITE, GetPartitionLabelByNamespace(key.Namespace)));
        ReturnMappedErrorOnFailure(nvs_set_blob(handle, key.Name, data, dataLen));

        // Commit the value to the persistent store.
        ReturnMappedErrorOnFailure(nvs_commit(handle));

        ChipLogProgress(DeviceLayer, "NVS set: %s/%s = (blob length %" PRId32 ")", key.Namespace, key.Name, dataLen);
        return CHIP_NO_ERROR;
    }

    return ClearConfigValue(key);
}

CHIP_ERROR ESP32Config::ClearConfigValue(Key key)
{
    ScopedNvsHandle handle;

    ReturnErrorOnFailure(handle.Open(key.Namespace, NVS_READWRITE, GetPartitionLabelByNamespace(key.Namespace)));

    esp_err_t err = nvs_erase_key(handle, key.Name);
    if (err == ESP_ERR_NVS_NOT_FOUND)
    {
        return CHIP_NO_ERROR;
    }
    ReturnMappedErrorOnFailure(err);

    // Commit the value to the persistent store.
    ReturnMappedErrorOnFailure(nvs_commit(handle));

    ChipLogProgress(DeviceLayer, "NVS erase: %s/%s", key.Namespace, key.Name);
    return CHIP_NO_ERROR;
}

bool ESP32Config::ConfigValueExists(Key key)
{
    nvs_iterator_t iterator = nvs_entry_find(NVS_DEFAULT_PART_NAME, key.Namespace, NVS_TYPE_ANY);
    for (; iterator; iterator = nvs_entry_next(iterator))
    {
        nvs_entry_info_t info;
        nvs_entry_info(iterator, &info);
        if (strcmp(info.key, key.Name) == 0)
        {
            nvs_release_iterator(iterator);
            return true;
        }
    }
    // if nvs_entry_find() or nvs_entry_next() returns NULL, then no need to release the iterator.
    return false;
}

CHIP_ERROR ESP32Config::EnsureNamespace(const char * ns)
{
    ScopedNvsHandle handle;

    CHIP_ERROR err = handle.Open(ns, NVS_READONLY, GetPartitionLabelByNamespace(ns));
    if (err == CHIP_NO_ERROR)
    {
        return CHIP_NO_ERROR;
    }
    if (err == ESP32Utils::MapError(ESP_ERR_NVS_NOT_FOUND))
    {
        ReturnErrorOnFailure(handle.Open(ns, NVS_READWRITE, GetPartitionLabelByNamespace(ns)));
        ReturnMappedErrorOnFailure(nvs_commit(handle));
        return CHIP_NO_ERROR;
    }
    return err;
}

CHIP_ERROR ESP32Config::ClearNamespace(const char * ns)
{
    ScopedNvsHandle handle;

    ReturnErrorOnFailure(handle.Open(ns, NVS_READWRITE, GetPartitionLabelByNamespace(ns)));
    ReturnMappedErrorOnFailure(nvs_erase_all(handle));
    ReturnMappedErrorOnFailure(nvs_commit(handle));
    return CHIP_NO_ERROR;
}

void ESP32Config::RunConfigUnitTest() {}

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