// SPDX-FileCopyrightText: 2024 Yury Gubich <blue@macaw.me>
// SPDX-License-Identifier: GPL-3.0-or-later

#include "config.h"

Config::Config(const std::filesystem::path& path):
    path(path),
    root(YAML::LoadFile(path))
{}

std::string Config::getBareJID() const {
    return root["jid"].as<std::string>();
}

std::string Config::getPassword() const {
    return root["password"].as<std::string>();
}

std::string Config::getResource() const {
    return root["resource"].as<std::string>("bot");
}

std::string Config::getFullJID() const {
    return getBareJID() + "/" + getResource();
}

Shared::Logger::Level Config::getLogLevel() const {
    std::string level = root["logLevel"].as<std::string>("info");

    if (level == "trace")
        return Shared::Logger::trace;
    else if (level == "debug")
        return Shared::Logger::debug;
    else if (level == "info")
        return Shared::Logger::info;
    else if (level == "warn" || level == "warning")
        return Shared::Logger::warning;
    else if (level == "error")
        return Shared::Logger::error;
    else
        return Shared::Logger::info;
}

gloox::TLSPolicy Config::getTLSPolicy() const {
    std::string level = root["tls"].as<std::string>("optional");

    if (level == "disabled")
        return gloox::TLSDisabled;
    else if (level == "required")
        return gloox::TLSRequired;
    else
        return gloox::TLSOptional;
}


std::map<std::string, std::string> Config::getActors() const {
    std::map<std::string, std::string> result;
    YAML::Node owners = root["actors"];
    if (!owners.IsMap())
        return result;

    for (const auto& node : owners)
        result.emplace(node.first.as<std::string>(), node.second.as<std::string>());

    return result;
}

bool Config::isValid() const {
    return !getBareJID().empty() && !getPassword().empty();
}

std::vector<Config::Module> Config::getModules() const {
    std::vector<Module> result;

    YAML::Node modules = root["modules"];
    if (!modules || !modules.IsSequence())
        return result;

    for (const YAML::Node& module : modules) {
        if (!module.IsMap())
            continue;

        std::string type = module["type"].as<std::string>();
        if (type.empty())
            continue;

        Module& conf = result.emplace_back(
            module["enabled"].as<bool>(true),
            type,
            module["alias"].as<std::string>(type)
        );

        YAML::Node prm = module["permissions"];
        if (prm.IsMap()) {
            for (const auto& node : prm) {
                Shared::Strings& list = conf.permissions.emplace(node.first.as<std::string>(), Shared::Strings()).first->second;
                YAML::Node lst = node.second;
                if (lst.IsSequence())
                    for (const YAML::Node& member : lst)
                        list.emplace_back(member.as<std::string>());
            }
        }
    }

    return result;
}

Shared::Responses Config::getResponses() const {
    Shared::Responses responses;

    YAML::Node replies = root["replies"];
    if (!replies || !replies.IsMap())
        return responses;

    for (const std::pair<Shared::Result, std::string_view>& entry : Shared::results) {
        YAML::Node options = replies[entry.second];
        if (!options.IsSequence())
            continue;

        Shared::Strings& out = responses.emplace(entry.first, Shared::Strings()).first->second;
        for (const YAML::Node& option : options)
            out.emplace_back(option.as<std::string>());
    }

    return responses;
}

void Config::setActors(const std::map<std::string, std::string>& actors) {
    YAML::Node cfg = root["actors"] = YAML::Node(YAML::NodeType::Map);

    for (const std::pair<const std::string, std::string>& pair : actors)
        cfg[pair.first] = pair.second;

    std::ofstream out(path);
    out << YAML::Dump(root);
    out.close();
}