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

namespace maps::wiki::json2ymapsdf::tds::schema {

Relation::Relation(
    const Category& master,
    std::string role,
    const Category& slave,
    RelationsDirection direction)
        : master_(master)
        , role_(std::move(role))
        , slave_(slave)
        , direction_(direction)
        , attachedYmapsdfRelation_(nullptr)
{ }

bool
Relation::operator < (const Relation& other) const
{
    using LessTuple = std::tuple<const Category &, const std::string &, const Category &>;
    return LessTuple(master_, role_, slave_)
        < LessTuple(other.master_, other.role_, other.slave_);
}

std::string
Relation::name() const
{
    return master_.name() + "." + role_ + "." + slave_.name();
}

void
Relation::addAttribute(const std::string& attribute)
{
    REQUIRE (!attribute.empty(), "Unable to configure empty attribute");
    attributes_.insert(attribute);
}

void
Relation::addConstAttr(const std::string& attribute, const std::string& value)
{
    addAttribute(attribute);
    constAttributes_[attribute] = value;
}

std::string
Relation::info() const
{
    std::ostringstream infoStr;

    infoStr << "'" << name() << "'";

    if(attachedYmapsdfRelation_ == nullptr) {
        infoStr << ", no corresponded ymapsdf relation";
    } else {
        infoStr << ", corresponds to " << attachedYmapsdfRelation_->name();
    }

    infoStr << ", attribues: [";
    for(const auto& attribute: attributes_) {
        infoStr << attribute << ", ";
    }
    for(const auto& kv: constAttributes_) {
        infoStr << "*" << kv.first << "=" << kv.second << ", ";
    }
    infoStr << "]";

    return infoStr.str();
}

} // namespace maps::wiki::json2ymapsdf::tds::schema
