// Error a propósito: se cambia una clave que ya está en la tabla.
// La tabla sigue teniendo el dato, pero en una casilla que ya no le corresponde.
#include <cstddef>
#include <iostream>
#include <string>
#include <vector>

#include "../hash_functions.h"

class LeakyTable {
public:
    void set(const std::string& key, int value) {
        slots_[fnv1a(key) % slots_.size()].push_back(Entry{key, value});
    }
    const int* get(const std::string& key) const {
        for (const Entry& entry : slots_[fnv1a(key) % slots_.size()]) {
            if (entry.key == key) {
                return &entry.value;
            }
        }
        return nullptr;
    }
    // El error de diseño: entrega la clave sin const.
    std::string* key_of(const std::string& key) {
        for (Entry& entry : slots_[fnv1a(key) % slots_.size()]) {
            if (entry.key == key) {
                return &entry.key;
            }
        }
        return nullptr;
    }
    std::size_t size() const {
        std::size_t total = 0;
        for (const std::vector<Entry>& slot : slots_) {
            total += slot.size();
        }
        return total;
    }
    bool check_invariants() const {
        for (std::size_t i = 0; i < slots_.size(); i++) {
            for (const Entry& entry : slots_[i]) {
                if (fnv1a(entry.key) % slots_.size() != i) {
                    return false;
                }
            }
        }
        return true;
    }

private:
    struct Entry {
        std::string key;
        int value;
    };
    std::vector<std::vector<Entry>> slots_ = std::vector<std::vector<Entry>>(8);
};

int main() {
    LeakyTable table;
    table.set("lima", 10);
    std::cout << "invariantes: " << table.check_invariants() << "\n";
    *table.key_of("lima") = "cusco";
    std::cout << "size: " << table.size() << "\n";
    std::cout << "get(\"lima\"): " << (table.get("lima") == nullptr ? "no está" : "está") << "\n";
    std::cout << "get(\"cusco\"): " << (table.get("cusco") == nullptr ? "no está" : "está") << "\n";
    std::cout << "invariantes: " << table.check_invariants() << "\n";
}
