/*
 *   Copyright (c) 2020-2022 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.
 *
 */
#include "ExamplePersistentStorage.h"

#include <lib/core/CHIPEncoding.h>
#include <lib/support/IniEscaping.h>

#include <fstream>
#include <map>
#include <memory>
#include <string>

using String   = std::basic_string<char>;
using Section  = std::map<String, String>;
using Sections = std::map<String, Section>;

using namespace ::chip;
using namespace ::chip::Controller;
using namespace ::chip::IniEscaping;
using namespace ::chip::Logging;

constexpr char kDefaultSectionName[]       = "Default";
constexpr char kPortKey[]                  = "ListenPort";
constexpr char kLoggingKey[]               = "LoggingLevel";
constexpr char kLocalNodeIdKey[]           = "LocalNodeId";
constexpr char kCommissionerCATsKey[]      = "CommissionerCATs";
constexpr LogCategory kDefaultLoggingLevel = kLogCategory_Automation;

const char * GetUsedDirectory(const char * directory)
{
    const char * dir = directory;

    if (dir == nullptr)
    {
        dir = getenv("TMPDIR");
    }

    if (dir == nullptr)
    {
        dir = "/tmp";
    }

    return dir;
}

std::string GetFilename(const char * directory, const char * name)
{
    const char * dir = GetUsedDirectory(directory);

    if (name == nullptr)
    {
        return std::string(dir) + "/chip_tool_config.ini";
    }

    return std::string(dir) + "/chip_tool_config." + std::string(name) + ".ini";
}

CHIP_ERROR PersistentStorage::Init(const char * name, const char * directory)
{
    CHIP_ERROR err = CHIP_NO_ERROR;

    std::ifstream ifs;
    ifs.open(GetFilename(directory, name), std::ifstream::in);
    if (!ifs.good())
    {
        CommitConfig(directory, name);
        ifs.open(GetFilename(directory, name), std::ifstream::in);
    }
    VerifyOrExit(ifs.is_open(), err = CHIP_ERROR_OPEN_FAILED);

    mName      = name;
    mDirectory = directory;
    mConfig.clear();
    mConfig.parse(ifs);
    ifs.close();

    // To audit the contents at init, uncomment the following:
#if 0
    DumpKeys();
#endif

exit:
    return err;
}

CHIP_ERROR PersistentStorage::SyncGetKeyValue(const char * key, void * value, uint16_t & size)
{
    std::string iniValue;

    VerifyOrReturnError((value != nullptr) || (size == 0), CHIP_ERROR_INVALID_ARGUMENT);

    auto section = mConfig.sections[kDefaultSectionName];

    VerifyOrReturnError(SyncDoesKeyExist(key), CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND);

    std::string escapedKey = EscapeKey(key);
    VerifyOrReturnError(inipp::extract(section[escapedKey], iniValue), CHIP_ERROR_INVALID_ARGUMENT);

    iniValue = Base64ToString(iniValue);

    uint16_t dataSize = static_cast<uint16_t>(iniValue.size());
    VerifyOrReturnError(size != 0 || dataSize != 0, CHIP_NO_ERROR);
    VerifyOrReturnError(value != nullptr, CHIP_ERROR_BUFFER_TOO_SMALL);

    uint16_t sizeToCopy = std::min(size, dataSize);

    memcpy(value, iniValue.data(), sizeToCopy);
    size = sizeToCopy;
    return size < dataSize ? CHIP_ERROR_BUFFER_TOO_SMALL : CHIP_NO_ERROR;
}

CHIP_ERROR PersistentStorage::SyncSetKeyValue(const char * key, const void * value, uint16_t size)
{
    VerifyOrReturnError((value != nullptr) || (size == 0), CHIP_ERROR_INVALID_ARGUMENT);

    auto section = mConfig.sections[kDefaultSectionName];

    std::string escapedKey = EscapeKey(key);
    if (value == nullptr)
    {
        section[escapedKey] = "";
    }
    else
    {
        section[escapedKey] = StringToBase64(std::string(static_cast<const char *>(value), size));
    }

    mConfig.sections[kDefaultSectionName] = section;
    return CommitConfig(mDirectory, mName);
}

CHIP_ERROR PersistentStorage::SyncDeleteKeyValue(const char * key)
{
    auto section = mConfig.sections[kDefaultSectionName];

    VerifyOrReturnError(SyncDoesKeyExist(key), CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND);

    std::string escapedKey = EscapeKey(key);
    section.erase(escapedKey);

    mConfig.sections[kDefaultSectionName] = section;
    return CommitConfig(mDirectory, mName);
}

bool PersistentStorage::SyncDoesKeyExist(const char * key)
{
    std::string escapedKey = EscapeKey(key);
    auto section           = mConfig.sections[kDefaultSectionName];
    auto it                = section.find(escapedKey);
    return (it != section.end());
}

void PersistentStorage::DumpKeys() const
{
#if CHIP_PROGRESS_LOGGING
    for (const auto & section : mConfig.sections)
    {
        const std::string & sectionName = section.first;
        const auto & sectionContent     = section.second;

        ChipLogProgress(chipTool, "[%s]", sectionName.c_str());
        for (const auto & entry : sectionContent)
        {
            const std::string & keyName = entry.first;
            ChipLogProgress(chipTool, "  => %s", UnescapeKey(keyName).c_str());
        }
    }
#endif // CHIP_PROGRESS_LOGGING
}

CHIP_ERROR PersistentStorage::SyncClearAll()
{
    ChipLogProgress(chipTool, "Clearing %s storage", kDefaultSectionName);
    auto section = mConfig.sections[kDefaultSectionName];
    section.clear();
    mConfig.sections[kDefaultSectionName] = section;
    return CommitConfig(mDirectory, mName);
}

const char * PersistentStorage::GetDirectory() const
{
    return GetUsedDirectory(mDirectory);
}

CHIP_ERROR PersistentStorage::CommitConfig(const char * directory, const char * name)
{
    CHIP_ERROR err = CHIP_NO_ERROR;

    std::ofstream ofs;
    std::string tmpPath = GetFilename(directory, name) + ".tmp";
    ofs.open(tmpPath, std::ofstream::out | std::ofstream::trunc);
    VerifyOrExit(ofs.good(), err = CHIP_ERROR_WRITE_FAILED);

    mConfig.generate(ofs);
    ofs.close();
    VerifyOrExit(ofs.good(), err = CHIP_ERROR_WRITE_FAILED);

    VerifyOrExit(rename(tmpPath.c_str(), GetFilename(directory, name).c_str()) == 0, err = CHIP_ERROR_WRITE_FAILED);

exit:
    return err;
}

uint16_t PersistentStorage::GetListenPort()
{
    CHIP_ERROR err = CHIP_NO_ERROR;

    // By default chip-tool listens on an ephemeral port.
    uint16_t chipListenPort = 0;

    char value[6];
    uint16_t size = static_cast<uint16_t>(sizeof(value));
    err           = SyncGetKeyValue(kPortKey, value, size);
    if (CHIP_NO_ERROR == err)
    {
        uint16_t tmpValue;
        std::stringstream ss(value);
        ss >> tmpValue;
        if (!ss.fail() && ss.eof())
        {
            chipListenPort = tmpValue;
        }
    }

    return chipListenPort;
}

LogCategory PersistentStorage::GetLoggingLevel()
{
    CHIP_ERROR err           = CHIP_NO_ERROR;
    LogCategory chipLogLevel = kDefaultLoggingLevel;

    char value[9];
    uint16_t size = static_cast<uint16_t>(sizeof(value));
    err           = SyncGetKeyValue(kLoggingKey, value, size);
    if (CHIP_NO_ERROR == err)
    {
        if (strcasecmp(value, "none") == 0)
        {
            chipLogLevel = kLogCategory_None;
        }
        else if (strcasecmp(value, "error") == 0)
        {
            chipLogLevel = kLogCategory_Error;
        }
        else if (strcasecmp(value, "progress") == 0)
        {
            chipLogLevel = kLogCategory_Progress;
        }
        else if (strcasecmp(value, "detail") == 0)
        {
            chipLogLevel = kLogCategory_Detail;
        }
        else if (strcasecmp(value, "automation") == 0)
        {
            chipLogLevel = kLogCategory_Automation;
        }
    }

    return chipLogLevel;
}

NodeId PersistentStorage::GetLocalNodeId()
{
    CHIP_ERROR err = CHIP_NO_ERROR;

    uint64_t nodeId;
    uint16_t size = static_cast<uint16_t>(sizeof(nodeId));
    err           = SyncGetKeyValue(kLocalNodeIdKey, &nodeId, size);
    if (err == CHIP_NO_ERROR)
    {
        return static_cast<NodeId>(Encoding::LittleEndian::HostSwap64(nodeId));
    }

    return kTestControllerNodeId;
}

CHIP_ERROR PersistentStorage::SetLocalNodeId(NodeId value)
{
    uint64_t nodeId = Encoding::LittleEndian::HostSwap64(value);
    return SyncSetKeyValue(kLocalNodeIdKey, &nodeId, sizeof(nodeId));
}

CATValues PersistentStorage::GetCommissionerCATs()
{
    CHIP_ERROR err = CHIP_NO_ERROR;
    CATValues cats;
    chip::CATValues::Serialized serializedCATs;
    uint16_t size = chip::CATValues::kSerializedLength;
    err           = SyncGetKeyValue(kCommissionerCATsKey, serializedCATs, size);
    if (err == CHIP_NO_ERROR && size == chip::CATValues::kSerializedLength)
    {
        err = cats.Deserialize(serializedCATs);
        if (err == CHIP_NO_ERROR)
        {
            return cats;
        }
    }
    return chip::kUndefinedCATs;
}

CHIP_ERROR PersistentStorage::SetCommissionerCATs(const CATValues & cats)
{
    chip::CATValues::Serialized serializedCATs;
    ReturnErrorOnFailure(cats.Serialize(serializedCATs));

    return SyncSetKeyValue(kCommissionerCATsKey, serializedCATs, sizeof(serializedCATs));
}
