#include "object_helpers.h"

#include <yandex/maps/wiki/common/pg_utils.h>
#include <yandex/maps/wiki/common/string_utils.h>
#include <maps/libs/geolib/include/serialization.h>
#include <maps/libs/locale/include/convert.h>

namespace maps::wiki::masstransit {

namespace {

const std::string STR_EMPTY_ARRAY = "{}";

Ids
parseIdsArray(const std::string& values)
{
    Ids ids;
    for (const auto& value : common::parseSqlArray(values)) {
        ids.push_back(to<DBID>(value));
    }
    return ids;
}

} // namespace

std::string
toString(const std::vector<DBID>& ids)
{
    ASSERT(!ids.empty());
    return "(" + common::join(ids, ',') + ")";
}

std::string
toString(const std::vector<FtType>& ids)
{
    ASSERT(!ids.empty());
    return "("
        + common::join(ids, [](FtType ftType) { return static_cast<DBID>(ftType); }, ',')
        + ")";
}

template<>
bool
getAttr(const pqxx::row& tuple, const std::string& attrName)
{
    const auto attr = tuple.at(attrName);
    if (attr.is_null()) {
        return false;
    }

    const auto strAttr = attr.as<std::string>();
    if (strAttr == "t" || strAttr == "true" || strAttr == "1") {
        return true;
    } else if (strAttr.empty() || strAttr == "f" || strAttr == "false" || strAttr == "0") {
        return false;
    }

    throw RuntimeError() << "Unable to convert boolean attribute "
            << attrName << " from '" << strAttr << "'";
}

template<>
std::string
getAttr(const pqxx::row& tuple, const std::string& attrName)
{
    const auto attr = tuple.at(attrName);
    if (attr.is_null()) {
        throw PqxxNullValueError() << "Attribute '" << attrName << "' is NULL";
    }
    return attr.as<std::string>();
}

template<>
Point
getAttr(const pqxx::row& tuple, const std::string& attrName)
{
    const auto shapeStr = getAttr<std::string>(tuple, attrName);
    return geolib3::WKT::read<Point>(shapeStr);
}

template<>
FtType getAttr(const pqxx::row& tuple, const std::string& attrName)
{
    return static_cast<FtType>(getAttr<DBID>(tuple, attrName));
}

template<>
Ids getAttr(const pqxx::row& tuple, const std::string& attrName)
{
    auto idsStr = getAttr<std::string>(tuple, attrName, STR_EMPTY_ARRAY);
    return parseIdsArray(idsStr);
}

} // namespace maps::wiki::masstransit
