#include <flecs.h>
#include <iostream>
#include <typeindex>
#include <typeinfo>
#include <unordered_map>

struct Position {
    double x, y;
};

struct Velocity {
    double x, y;
};

int main() {
    flecs::world ecs;

    flecs::system fight = ecs.system<const Position>()
      .each([&](flecs::entity e, const Position &other) {
          flecs::entity player = ecs.lookup("player");
          if(e == player) return; // don't process the player

          const Position *player_p = player.get<Position>();
          if(player_p->x == other.x && player_p->y == other.y) {
            std::cerr << "HIT\n";
          }
      });

    // Create a system for Position, Velocity. Systems are like queries (see
    // queries) with a function that can be ran or scheduled (see pipeline).
    flecs::system move = ecs.system<Position, const Velocity>()
        .each([&](flecs::entity e, Position& p, const Velocity& v) {
            p.x += v.x;
            p.y += v.y;
            std::cerr << e.name() << ": {" << p.x << ", " << p.y << "}\n";
        });

    // Create a few test entities for a Position, Velocity query
    ecs.entity("player")
        .set<Position>({10, 10})
        .set<Velocity>({1, 1});

    ecs.entity("e2")
      .set<Position>({10, 20})
      .set<Velocity>({1, 1});

    // This entity will not match as it does not have Position, Velocity
    ecs.entity("e3")
      .set<Position>({10, 20});

    std::unordered_map<std::type_index, std::string> type_names;
    type_names[std::type_index(typeid(Position))] = "Position";
    type_names[std::type_index(typeid(Velocity))] = "Velocity";

    for(const auto& [key, value] : type_names) {
      std::cout << " VAL " << value << std::endl;
    }
    // Run the system
    move.run();
    fight.run();
}
