#pragma once

#include <maps/wikimap/mapspro/services/mrc/libs/graph/include/common.h>

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

#include <map>
#include <vector>

namespace maps::mrc::graph {

class DirectedId {

public:
    DirectedId(TId roadElementId, Direction direction)
        : roadElementId_(roadElementId)
        , direction_(direction)
    {
        REQUIRE(direction != Direction::Both, "Impossible direction " << direction);
    }

    TId roadElementId() const { return roadElementId_; }

    Direction direction() const { return direction_; }

    DirectedId reverse() const { return {roadElementId_, ymapsdf::rd::reverse(direction_)}; }

    auto introspect() const { return std::tie(roadElementId_, direction_); }

private:
    TId roadElementId_;
    Direction direction_;
};

inline bool operator==(const DirectedId& lhs, const DirectedId& rhs)
{
    return lhs.introspect() == rhs.introspect();
}

inline bool operator!=(const DirectedId& lhs, const DirectedId& rhs)
{
    return !(lhs == rhs);
}

inline bool operator<(const DirectedId& lhs, const DirectedId& rhs)
{
    return lhs.introspect() < rhs.introspect();
}

 // Path in road graph, that doesn't violate directions of road elements.
using Trace = std::vector<DirectedId>;
using Traces = std::vector<Trace>;

using DirectedIds = std::vector<DirectedId>;

} // namespace maps::mrc::graph
