#pragma once

#include <robin_hood.h>
#include "./core.hpp"

namespace std {
    using namespace generational;

    template<>
    struct hash<id> {
        std::size_t operator()(const id& i) const noexcept {
            return std::hash<id::type>{}(i.index());
        }
    };

    template<typename T>
    struct hash<generational::key<T>> {
        std::size_t operator()(const generational::ref<T>& r) const noexcept {
            return std::hash<id>{}(r.val);
        }
    };

    template<typename T>
    struct hash<generational::ref<T>> {
        std::size_t operator()(const generational::ref<T>& r) const noexcept {
            return std::hash<id::type>{}(r.val);
        }
    };
}

namespace generational {
    // Unordered subset of a vector
    template<typename T>
    class flag: public robin_hood::unordered_set<key<T>> { };

    /// Subset or reordering of a vector
    template<typename T>
    class map: public std::vector<ref<T>> {
    public:
        /// O(n)
        bool erase(const ref<T>& r) {
            for (auto it = this->begin(); it != this->end(); ++it) {
                if (*it == r) {
                    std::vector<ref<T>>::erase(it);
                    return true;
                }
            }
            return false;
        }
    };
}