#include <yandex/maps/wiki/routing/common.h>

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

#include <functional>
#include <map>
#include <utility>
#include <vector>

namespace maps {
namespace wiki {
namespace routing {

// The class is designed to map object to id and back.
// Object must be copyconstructible and ordered type.
// If Y not less X and X not less Y then map returns equal ids in other case different.
// Also possible get object by id.
template<typename TObject, class Compare = std::less<TObject>>
class AutoIdMap {

public:
    AutoIdMap(Compare compare = Compare()): index_(compare) {}

    ID operator()(const TObject& object)
    {
        const auto insertion = index_.insert({object, objects_.size()});
        if (insertion.second) {
            objects_.push_back(insertion.first);
        }

        return insertion.first->second;
    }

    inline ID operator()(TObject&& object) { return (*this)(static_cast<const TObject&>(object)); }

    bool has(const TObject& object) const { return index_.count(object); }

    const TObject& operator[](ID id) const {
        REQUIRE(id < objects_.size(), "There is no object with id " << id);
        return objects_[id]->first;
    }

private:
    typedef std::map<TObject, ID, Compare> Index;

    Index index_;
    std::vector<typename Index::iterator> objects_;
};

} // namespace routing
} // namespace wiki
} // namespace maps
