#pragma once
#include <vector>
#include <unordered_map>
#include "map.hpp"
#include "dinkyecs.hpp"
#include "point.hpp"

struct CollisionData {
  DinkyECS::Entity entity = DinkyECS::NONE;
  bool collision = false;
};

// Point's has is in point.hpp
using EntityList = std::vector<DinkyECS::Entity>;
using PointEntityMap = std::unordered_multimap<Point, CollisionData>;
using SortedEntities = std::vector<std::pair<int, DinkyECS::Entity>>;

struct FoundEntities {
  bool found;
  EntityList nearby;
};

class SpatialMap {
  public:
    SpatialMap() {}
    PointEntityMap $collision;

    void insert(Point pos, DinkyECS::Entity obj, bool has_collision);
    void move(Point from, Point to, DinkyECS::Entity ent);
    // return value is whether the removed thing has collision
    CollisionData remove(Point pos, DinkyECS::Entity entity);
    bool occupied(Point pos) const;
    bool something_there(Point at) const;
    DinkyECS::Entity get(Point at) const;
    FoundEntities neighbors(Point position, bool diag=false) const;

    SortedEntities distance_sorted(Point from, int max_distance);
    size_t size() { return $collision.size(); }
};
