#include "global.h"

#include <maps/libs/log8/include/log8.h>
#include <maps/libs/common/include/exception.h>

#include <filesystem>
#include <memory>

namespace fs = std::filesystem;

namespace maps {
namespace wiki {
namespace renderer {

namespace {

const std::string DEFAULT_CONFIG_PATH = "/etc/yandex/maps/wiki/renderer/config.xml";

std::unique_ptr<Global> s_global;


std::string
getModuleConfigPath(const std::string& modulePath)
{
    size_t delimPos = modulePath.rfind('-');
    const std::string postfix = delimPos != std::string::npos
        ? ("." + modulePath.substr(delimPos + 1))
        : "";

    std::string cfgPath(DEFAULT_CONFIG_PATH);
    cfgPath.insert(cfgPath.rfind('.'), postfix);
    return cfgPath;
}

}


Global::Global(const std::string& configFilename)
    : config_(configFilename)
{
    for (const auto& [_, layer] : config_.layers()) {
        try {
            auto renderers =
                Renderer::create(layer.name, layer.path);
            renderers_.insert(renderers.begin(), renderers.end());
        } catch(const std::exception& ex) {
            WARN() << "Renderer for layer " << layer.name
                   << " failed: " << ex.what();
        }
        try {
            auto renderers = Style2Renderer::create(layer.name, config_.layersPath());
            style2renderers_.insert(renderers.begin(), renderers.end());
        } catch(const std::exception& ex) {
            WARN() << "Style2 renderer for layer " << layer.name
                   << " failed: " << ex.what();
        }
    }
}

Global::~Global()
{
    renderers_.clear();
}

GlobalScope::GlobalScope(
    const std::string& modulePath,
    const std::string& priorityConfigFilename)
{
    std::vector<std::string> configs;
    configs.push_back(priorityConfigFilename);
    configs.push_back(getModuleConfigPath(modulePath));
    configs.push_back(DEFAULT_CONFIG_PATH);

    for (const auto& filename : configs) {
        if (filename.empty()) {
            continue;
        }
        DEBUG() << "Try load config filename : " << filename;
        if (fs::is_regular_file(fs::path(filename))) {
            s_global = std::unique_ptr<Global>(new Global(filename));
            break;
        }
    }
}

GlobalScope::~GlobalScope()
{
    s_global.reset();
}

Global& GlobalScope::instance()
{
    ASSERT(s_global);
    return *s_global;
}

} // namespace renderer
} // namespace wiki
} // namespace maps
