#include <maps/wikimap/mapspro/tools/ymapsdf-conversion/tnc2ymapsdf/names.h>

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

#include <boost/algorithm/string/trim.hpp>
#include <boost/lexical_cast.hpp>

namespace maps {
namespace wiki {
namespace tnc2ymapsdf {

namespace {

const std::string NAME_PREFIX = "name_";
const std::string STREET_PREFIX = "street_";
const std::string LABEL_PREFIX = "label_";

std::string trim(std::string str)
{
    boost::algorithm::trim(str);
    return str;
}

bool isNumber(const std::string& str)
{
    try {
        if (!str.empty()) {
            boost::lexical_cast<int64_t>(str);
            return true;
        }
    } catch (...) {
        // suppress
    }
    return false;
}

} // namespace


void NamesBase::check(Id id) const
{
    REQUIRE(!empty(), "empty names for id: " << id);
}

void NamesBase::parse(const pqxx::row& row, const std::string& nmPrefix)
{
    auto add = [&](auto code, auto lang, const auto& nonEqual) {
        auto nm = row[nmPrefix + code].c_str();
        return addName(nm, lang, nonEqual);
    };

    auto name = add("nat", LOCAL_LANG, EMPTY);
    bool isNum = isNumber(name);
    add("rus", "ru", isNum ? name : EMPTY);
    add("eng", "en", isNum ? name : EMPTY);
    add("arb", "ar", isNum ? name : EMPTY);
}

std::string NamesBase::addName(std::string nm, std::string_view lang, const std::string& nonEqual)
{
    auto name = trim(std::move(nm));
    if (!name.empty() && name != nonEqual) {
        langToName_.emplace(lang, name);
    }
    return name;
}


Names::Names(const pqxx::row& row)
{
    parse(row, NAME_PREFIX);
}

void Names::addLocal(std::string name)
{
    addName(std::move(name), LOCAL_LANG, EMPTY);
}


StreetNames::StreetNames(const pqxx::row& row)
{
    parse(row, STREET_PREFIX);
}


LabelNames::LabelNames(const pqxx::row& row)
{
    parse(row, LABEL_PREFIX);
}

} // namespace tnc2ymapsdf
} // namespace wiki
} // namespace maps
