#include <yandex/maps/wiki/validator/objects/road.h>

#include "object_init_helpers.h"
#include <maps/wikimap/mapspro/libs/validator/common/exception.h>
#include <maps/wikimap/mapspro/libs/validator/common/magic_strings.h>
#include <yandex/maps/wiki/validator/categories.h>

namespace maps::wiki::validator {

namespace {
const std::string MESSAGE_BAD_RD_ASSOCIATION = "bad-rd-association";
}

Road::Road(
        TId id,
        const AttrMap& attributes,
        const Relations& masters,
        const Relations& slaves)
    : id_(id)
    , type_(
            extractAttr<Type>(
                    attributes, RD_TYPE_ATTR, IsMandatory::Yes,
                    "bad-road-type", id))
    , associatedObject_{0, AssociatedObject::Type::NotSet}
    , elements_(extractRelations(slaves, PART_ROLE))
    , names_(extractNameRelations(slaves))
    , addrUnity_(extractRelation(
            masters, ASSIGNED_RD_ROLE, IsMandatory::No, "rd-shared-by-addr-unities", id))
{
    auto searchClassIt = attributes.find(RD_SEARCH_CLASS_ATTR);
    if (searchClassIt != attributes.end()) {
        searchClass_ = castAttr<int>(
                attributes, searchClassIt, IsMandatory::No,
                "bad-search-class", id);
    }

    for (const auto& masterRel : masters) {
        if (masterRel.role == RD_ASSOCIATED_WITH_ROLE ||
            masterRel.role == ASSOCIATED_WITH_ROLE)
        {
            if (associatedObject_.type != AssociatedObject::Type::NotSet) {
                throw InvalidRelationsException(
                    MESSAGE_BAD_RD_ASSOCIATION, id,
                    {associatedObject_.id, masterRel.other});
            }
            associatedObject_.id = masterRel.other;

            if (masterRel.otherCategoryId == categories::AD::id()) {
                associatedObject_.type = AssociatedObject::Type::AdmUnit;
            } else {
                associatedObject_.type = AssociatedObject::Type::Feature;
            }
        }
    }
}

} // namespace maps::wiki::validator
