#pragma once
#include <luna/HashTable.h>

template <typename K, typename V> struct HashPair
{
    K key;
    Option<V> value;

    bool operator==(const HashPair<K, V>& other) const
    {
        return key == other.key;
    }
};

template <typename K, typename V> u64 hash(const HashPair<K, V>& value, u64 salt)
{
    return hash(value.key, salt);
}

template <typename K, typename V> struct HashMap
{
  public:
    Result<bool> try_set(const K& key, V&& value)
    {
        return m_table.try_set(HashPair<K, V> { key, move(value) });
    }

    Result<bool> try_set(const K& key, const V& value)
    {
        return m_table.try_set(HashPair<K, V> { key, value });
    }

    Option<V> try_get(const K& key)
    {
        auto* p = m_table.try_find(HashPair<K, V> { key, {} });
        if (!p) return {};
        return p->value;
    }

    V* try_get_ref(const K& key)
    {
        auto* p = m_table.try_find(HashPair<K, V> { key, {} });
        if (!p) return nullptr;
        return p->value.value_ptr();
    }

    bool try_remove(const K& key)
    {
        return m_table.try_remove(HashPair<K, V> { key, {} });
    }

  private:
    HashTable<HashPair<K, V>> m_table;
};