#include "gui/debug_ui.hpp"
#include "constants.hpp"
#include "events.hpp"
#include <optional>
#include <fmt/core.h>
#include <fmt/xchar.h>
#include "components.hpp"

namespace gui {
  using namespace guecs;

  DebugUI::DebugUI(LevelManager& level_mgr) :
    $level_mgr(level_mgr)
  {
  }

  void DebugUI::init(lel::Cell cell) {
    $gui.position(cell.x, cell.y, cell.w, cell.h);
    $gui.layout(
        "[*%(100,400)debug_text]"
        "[_]"
        "[_]"
        "[_]"
        "[spawn1|spawn2|spawn3]"
        "[spawn4|spawn5|spawn6]");

    add_spawn_button("AXE_RANGER", "axe_ranger", "spawn1");
    add_spawn_button("KNIGHT","armored_knight", "spawn2");
    add_spawn_button("SPIDER_GIANT_HAIRY", "hairy_spider", "spawn3");
    add_spawn_button("RAT_GIANT", "rat_with_sword", "spawn4");
    add_spawn_button("GOLD_SAVIOR", "gold_savior", "spawn5");

    $gui.init();
  }

  void DebugUI::add_spawn_button(std::string enemy_key, std::string sprite_name, std::string region) {
    auto button = $gui.entity(region);
    $gui.set<guecs::Clickable>(button, { [this, enemy_key](auto, auto){ spawn(enemy_key); } });
    $gui.set<guecs::Sprite>(button, { sprite_name});
  }

  void DebugUI::spawn(const std::string& enemy_key) {
    (void)enemy_key;
    dbc::log("THIS FUNCTION NEEDS A REWRITE");
    // auto ent = $level_mgr.spawn_enemy(enemy_key);
    // auto& level = $level_mgr.current();
    // level.world->send<Events::GUI>(Events::GUI::ENTITY_SPAWN, ent, {});
  }

  void DebugUI::render(sf::RenderWindow& window) {
    if(active) {
      auto& level = $level_mgr.current();
      auto player = level.world->get_the<components::Player>();
      auto player_combat = level.world->get<components::Combat>(player.entity);
      auto map = level.map;

      std::wstring stats = fmt::format(L"STATS\n"
          L"HP: {}\n"
          L"mean:{:>8.5}\n"
          L"sdev: {:>8.5}\n"
          L"min: {:>8.5}\n"
          L"max: {:>8.5}\n"
          L"count:{:<10}\n"
          L"level: {} size: {}x{}\n\n"
          L"VSync? {}\n"
          L"FR Limit: {}\n"
          L"Debug? {}\n\n",
          player_combat.hp, $stats.mean(), $stats.stddev(), $stats.min,
          $stats.max, $stats.n, level.index, map->width(), map->height(),
          VSYNC, FRAME_LIMIT, DEBUG_BUILD);

      $gui.show_text("debug_text", stats);
      $gui.render(window);
      // $gui.debug_layout(window);
    }
  }

  void DebugUI::debug() {
    active = !active;

    if(active) {
      auto& level = $level_mgr.current();
      // it's on now, enable things
      auto player = level.world->get_the<components::Player>();
      auto& player_combat = level.world->get<components::Combat>(player.entity);
      player_combat.hp = player_combat.max_hp;
      $gui.show_text("debug_text", L"STATS");
    } else {
      // it's off now, close it
      $gui.close<Text>("debug_text");
    }
  }

  bool DebugUI::mouse(float x, float y, bool hover) {
    return $gui.mouse(x, y, hover);
  }

  Stats::TimeBullshit DebugUI::time_start() {
    return $stats.time_start();
  }

  void DebugUI::sample_time(Stats::TimeBullshit start) {
    $stats.sample_time(start);
  }

  void DebugUI::reset_stats() {
    $stats.reset();
  }
}
