#pragma once

#include <map>
#include <optional>
#include <utility>
#include <vector>

#include <QPoint>

#include "BuildingId.h"

class Hasher;

// The authority on which building owns which world tile.
//
// Every building and construction site claims its body cells here when it is placed
// and releases them when it is removed, so the map is the single place that knows
// whether a tile is free. It is a plain index owned by BuildingSystem, not a system:
// it has no per-tick behaviour and nothing outside BuildingSystem touches it.
//
// Keys are deliberately std::pair<int, int> rather than QPoint: the checksum folds the
// entries in map iteration order (docs/replay_design.md), so the comparator is part of
// the determinism contract and is not changed casually.
class BuildingGrid
{
public:
    // Records absolute body cells as owned by id. Re-occupying a cell overwrites its
    // previous owner, matching the placement paths that reserve cells for a site and
    // then hand them to the building it becomes.
    void occupy(QPoint cell, BuildingId id);
    void occupy(const std::vector<QPoint>& cells, BuildingId id);

    // Releases absolute body cells. Cells that are not occupied are ignored.
    void release(const std::vector<QPoint>& cells);

    bool isOccupied(QPoint tile) const;

    // The building owning the tile, or nullopt when the tile is free.
    std::optional<BuildingId> findOwner(QPoint tile) const;

    // Folds the occupancy into the hasher in deterministic order.
    void appendChecksum(Hasher& hasher) const;

private:
    std::map<std::pair<int, int>, BuildingId> m_owners;
};
