#pragma once
#include "dinkyecs.hpp"
#include "combat.hpp"
#include "inventory.hpp"
#include "tser.hpp"
#include "config.hpp"

namespace components {
  struct Player {
    DinkyECS::Entity entity;
    DEFINE_SERIALIZABLE(Player, entity);
  };

  struct Position {
    Point location;
    DEFINE_SERIALIZABLE(Position, location);
  };

  struct Motion {
    int dx;
    int dy;
    bool random=false;
    DEFINE_SERIALIZABLE(Motion, dx, dy);
  };

  struct Loot {
    int amount;
    DEFINE_SERIALIZABLE(Loot, amount);
  };

  struct Tile {
    std::string chr;
    DEFINE_SERIALIZABLE(Tile, chr);
  };

  struct GameConfig {
    Config game;
    Config enemies;
    Config items;
    Config tiles;
  };

  struct EnemyConfig {
    int hearing_distance = 10;
  };

  struct Debug {
    bool PATHS=false;
    bool LIGHT=false;
  };

  struct Weapon {
    int damage = 0;
  };

  struct Curative {
    int hp = 10;
  };

  inline void configure(DinkyECS::World &world, DinkyECS::Entity entity, json& entity_data) {
    for(auto &comp : entity_data["components"]) {
      json& config = comp["config"];

      if(comp["type"] == "Weapon") {
        world.set<Weapon>(entity, {config["damage"]});
      } else if(comp["type"] == "LightSource") {
        world.set<LightSource>(entity, {config["strength"], config["radius"]});
      } else if(comp["type"] == "Loot") {
        world.set<Loot>(entity, {config["amount"]});
      } else if(comp["type"] == "Tile") {
        world.set<Tile>(entity, {config["chr"]});
      } else if(comp["type"] == "EnemyConfig") {
        world.set<EnemyConfig>(entity, {config["hearing_distance"]});
      } else if(comp["type"] == "Combat") {
        world.set<Combat>(entity, {config["hp"], config["damage"]});
      } else if(comp["type"] == "Curative") {
        world.set<Curative>(entity, {config["hp"]});
      } else if(comp["type"] == "Motion") {
        world.set<Motion>(entity, {config["dx"], config["dy"], config["random"]});
      } else {
        dbc::sentinel(fmt::format("ITEM COMPONENT TYPE MISSING: {}",
              std::string(comp["type"])));
      }
    }
  }
}
