/* KMKeyFile.cpp
 *
 * Copyright (C) 2023 OpenKylin, Inc
 */

#include "KMKeyFile.h"

#include <iostream>

#include "KMLogger.h"
#include "KMUtil.h"

KMKeyFile::KMKeyFile()
{
    m_ini = std::make_shared<CSimpleIniCaseA>();
}

KMKeyFile::~KMKeyFile() { }

bool KMKeyFile::loadFile(const std::string &metafile)
{
    if (!fs::exists(metafile))
    {
        KMInfo(metafile + " not exists");
        return false;
    }

    SI_Error rc = m_ini->LoadFile(metafile.c_str());
    if (rc != SI_OK)
    {
        KMError(metafile + " load failed");
        return false;
    }

    m_path = metafile;
    m_loaded = true;

    return true;
}

bool KMKeyFile::saveFile(const std::string &metafile)
{
    SI_Error rc = m_ini->SaveFile(metafile.c_str());
    if (rc != SI_OK)
    {
        KMError(metafile + " save failed");
        return false;
    }

    return true;
}

std::string KMKeyFile::getStringValue(const std::string &group, const std::string &key, const std::string &defaultValue)
{
    const char *pszValue = m_ini->GetValue(group.c_str(), key.c_str(), nullptr);
    if (!pszValue || !*pszValue)
    {
        return defaultValue;
    }

    return pszValue;
}

std::vector<std::string> KMKeyFile::getStringListValue(const std::string &group, const std::string &key)
{
    std::string value = getStringValue(group, key);

    return KMUtil::splitString(value, ";");
}

std::vector<std::string> KMKeyFile::getStringListValueWithQMarks(const std::string &group, const std::string &key)
{
    std::string value = getStringValue(group, key);

    if (value.length() > 2)
    {
        if (value.at(0) == '\"')
        {
            value.replace(0, 1, "");
        }

        if (value.at(value.length() - 1) == '\"')
        {
            value.replace(value.length() - 1, 1, "");
        }
    }

    return KMUtil::splitString(value, ";");
}

bool KMKeyFile::getBoolValue(const std::string &group, const std::string &key, bool defaultValue)
{
    return m_ini->GetBoolValue(group.c_str(), key.c_str(), defaultValue);
}

long KMKeyFile::getLongValue(const std::string &group, const std::string &key, long defaultValue)
{
    return m_ini->GetLongValue(group.c_str(), key.c_str(), defaultValue);
}

double KMKeyFile::getDoubleValue(const std::string &group, const std::string &key, double defaultValue)
{
    return m_ini->GetDoubleValue(group.c_str(), key.c_str(), defaultValue);
}

std::map<std::string, std::string> KMKeyFile::getGroupData(const std::string &group)
{
    std::map<std::string, std::string> groupValues;

    const CSimpleIniCaseA::TKeyVal *keyVals = m_ini->GetSection(group.c_str());
    if (!keyVals)
    {
        return groupValues;
    }

    for (auto &pair : *keyVals)
    {
        const CSimpleIniCaseA::Entry &entry = pair.first;
        const char *pvalue = pair.second;
        if (!pvalue)
        {
            continue;
        }

        std::string key(entry.pItem);
        if (key.empty())
        {
            continue;
        }

        std::string value(pvalue);
        groupValues.insert({ key, value });
    }

    return groupValues;
}

std::vector<std::string> KMKeyFile::getAllGroups() const
{
    std::vector<std::string> groups;

    CSimpleIniCaseA::TNamesDepend sections;
    m_ini->GetAllSections(sections);
    for (auto &section : sections)
    {
        groups.push_back(section.pItem);
    }

    return groups;
}

void KMKeyFile::setStringValue(const std::string &group, const std::string &key, const std::string &value)
{
    m_ini->SetValue(group.c_str(), key.c_str(), value.c_str(), nullptr, true);
}

void KMKeyFile::setStringListValue(const std::string &group, const std::string &key, const std::vector<std::string> &vector)
{
    setStringValue(group, key, KMUtil::join(vector, ";"));
}

void KMKeyFile::setBoolValue(const std::string &group, const std::string &key, bool value)
{
    m_ini->SetBoolValue(group.c_str(), key.c_str(), value, nullptr, true);
}

void KMKeyFile::setLongValue(const std::string &group, const std::string &key, long value)
{
    m_ini->SetLongValue(group.c_str(), key.c_str(), value, nullptr, true);
}

void KMKeyFile::setDoubleValue(const std::string &group, const std::string &key, double value)
{
    m_ini->SetDoubleValue(group.c_str(), key.c_str(), value, nullptr, true);
}

void KMKeyFile::deleteKey(const std::string &group, const std::string &key)
{
    m_ini->Delete(group.c_str(), key.c_str());
}

void KMKeyFile::deleteGroup(const std::string &group)
{
    m_ini->Delete(group.c_str(), nullptr);
}

bool KMKeyFile::groupExists(const std::string &group)
{
    return m_ini->SectionExists(group.c_str());
}

bool KMKeyFile::keyExists(const std::string &group, const std::string &key)
{
    return m_ini->KeyExists(group.c_str(), key.c_str());
}
