#include "KMMetaData.h"

#include <iostream>

#include "KMUtil.h"
#include "common/KMLogger.h"

KMMetaData::KMMetaData(bool isApp)
    : KMKeyFile()
    , d(std::make_unique<Private>())
{
    d->m_isApp = isApp;
}

KMMetaData::~KMMetaData() { }

bool KMMetaData::load(const std::string &metafile)
{
    if (!loadFile(metafile))
    {
        return false;
    }

    initApplication();
    initExtensions();
    initEnvironment();
    initContext();
    initSessionBusPolicy();
    initSystemBusPolicy();
    initXDConf();
    initGenericPolicy();

    return true;
}

void KMMetaData::initApplication()
{
    if (groupExists(METADATA_GROUP_APPLICATION))
    {
        d->m_isApp = true;
    }
    else
    {
        d->m_isApp = false;
    }

    std::string group(METADATA_GROUP_APPLICATION);
    if (!d->m_isApp)
    {
        group = METADATA_GROUP_RUNTIME;
    }

    d->m_applicationCommand = getStringValue(group, METADATA_KEY_COMMAND);
    d->m_applicationName = getStringValue(group, METADATA_KEY_NAME);
    d->m_applicationRuntime = getStringValue(group, METADATA_KEY_RUNTIME);
    d->m_applicationSdk = getStringValue(group, METADATA_KEY_SDK);
    d->m_applicationTags = KMUtil::vectorToList(getStringListValue(group, METADATA_KEY_TAGS));
    d->m_applicationRequiredKaiming = getStringValue(group, METADATA_KEY_REQUIRED_KAIMING);
}

void KMMetaData::initExtensions()
{
    d->m_extensions.clear();

    CSimpleIniCaseA::TNamesDepend sections;
    m_ini->GetAllSections(sections);
    for (auto &section : sections)
    {
        std::string group(section.pItem);
        std::string groupPrefix(METADATA_GROUP_PREFIX_EXTENSION);
        kmlogger.info("group: %s", group.c_str());
        if (!KMUtil::startsWith(group, groupPrefix))
        {
            continue;
        }

        KMExtension ext;
        ext.name = group.substr(groupPrefix.length(), group.length() - groupPrefix.length());
        ext.directory = getStringValue(group, METADATA_KEY_DIRECTORY);
        if (ext.directory.empty())
        {
            continue;
        }
        ext.autodelete = getBoolValue(group, METADATA_KEY_AUTODELETE);
        ext.addLdPath = getStringValue(group, METADATA_KEY_ADD_LD_PATH);
        ext.downloadIf = getStringValue(group, METADATA_KEY_DOWNLOAD_IF);
        ext.enableIf = getStringValue(group, METADATA_KEY_ENABLE_IF);
        ext.version = getStringValue(group, METADATA_KEY_VERSION);
        ext.versions = KMUtil::vectorToList(getStringListValue(group, METADATA_KEY_VERSIONS));
        ext.mergeDirs = KMUtil::vectorToList(getStringListValue(group, METADATA_KEY_MERGE_DIRS));
        ext.noAutodownload = getBoolValue(group, METADATA_KEY_NO_AUTODOWNLOAD);
        ext.subdirectories = getBoolValue(group, METADATA_KEY_SUBDIRECTORIES);
        ext.localeSubset = getBoolValue(group, METADATA_KEY_LOCALE_SUBSET);
        ext.autopruneUnless = getStringValue(group, METADATA_KEY_AUTOPRUNE_UNLESS);
        ext.subdirectorySuffix = getStringValue(group, METADATA_KEY_SUBDIRECTORY_SUFFIX);

        d->m_extensions.push_back(ext);
    }
}

void KMMetaData::initGenericPolicy()
{
    d->m_genericPolicy.clear();

    CSimpleIniCaseA::TNamesDepend sections;
    m_ini->GetAllSections(sections);
    for (auto &section : sections)
    {
        std::string group(section.pItem);
        std::string groupPrefix(METADATA_GROUP_PREFIX_POLICY);
        if (!KMUtil::startsWith(group, groupPrefix))
        {
            continue;
        }

        std::string subsystem = group.substr(groupPrefix.length(), group.length() - groupPrefix.length());
        const std::map<std::string, std::string> &groupData = getGroupData(subsystem);
        for (const auto &pair : groupData)
        {
            std::string policyKey = subsystem + "." + pair.first;
            const std::vector<std::string> &values = KMUtil::splitString(pair.second, ";");
            d->m_genericPolicy.insert({ policyKey, values });
        }
    }
}

void KMMetaData::initEnvironment()
{
    d->m_environment.clear();
    d->m_environment = getGroupData(METADATA_GROUP_ENVIRONMENT);
}

void KMMetaData::initContext()
{
    d->m_contextShared = KMUtil::vectorToList(getStringListValue(METADATA_GROUP_CONTEXT, METADATA_KEY_SHARED));
    d->m_contextSockets = KMUtil::vectorToList(getStringListValue(METADATA_GROUP_CONTEXT, METADATA_KEY_SOCKETS));
    d->m_context_evices = KMUtil::vectorToList(getStringListValue(METADATA_GROUP_CONTEXT, METADATA_KEY_DEVICES));
    d->m_contextFeatures = KMUtil::vectorToList(getStringListValue(METADATA_GROUP_CONTEXT, METADATA_KEY_FEATURES));
    d->m_contextPersistent = KMUtil::vectorToList(getStringListValue(METADATA_GROUP_CONTEXT, METADATA_KEY_PERSISTENT));
    d->m_contextFilesystems = KMUtil::vectorToList(getStringListValue(METADATA_GROUP_CONTEXT, METADATA_KEY_FILESYSTEMS));
    d->m_contextUnsetEnvironment = KMUtil::vectorToList(getStringListValue(METADATA_GROUP_CONTEXT, METADATA_KEY_UNSET_ENVIRONMENT));
}

void KMMetaData::initSessionBusPolicy()
{
    d->m_sessionBusPolicy = getGroupData(METADATA_GROUP_SESSION_BUS_POLICY);
}

void KMMetaData::initSystemBusPolicy()
{
    d->m_systemBusPolicy = getGroupData(METADATA_GROUP_SYSTEM_BUS_POLICY);
}

void KMMetaData::initXDConf()
{
    d->m_XDConfPaths = KMUtil::vectorToList(getStringListValue(METADATA_GROUP_DCONF, METADATA_KEY_DCONF_PATHS));
    d->m_XDConfMigratePath = getStringValue(METADATA_GROUP_DCONF, METADATA_KEY_DCONF_MIGRATE_PATH);
}
