#pragma once

#include "constants.hpp"
#include "game/registry.hpp"
#include "algos/simplefsm.hpp"
#include "gui/debug_ui.hpp"
#include "gui/main_ui.hpp"
#include "gui/status_ui.hpp"
#include "gui/loot_ui.hpp"
#include "events.hpp"
#include "gui/event_router.hpp"
#include "gui/dnd_loot.hpp"
#include "events.hpp"
#include "gui/scene_ui.hpp"

namespace gui {
  enum class State {
    START=__LINE__,
    START_SCREEN=__LINE__,
    MOVING=__LINE__,
    ATTACKING=__LINE__,
    ROTATING=__LINE__,
    LOOTING=__LINE__,
    IDLE=__LINE__,
    END=__LINE__,
  };

  class FSM : public DeadSimpleFSM<State, game::Event> {
    public:
      sf::RenderWindow $window;
      bool $draw_stats = false;
      DebugUI $debug_ui;
      MainUI $main_ui;
      StatusUI $status_ui{STATUS_UI_X, STATUS_UI_Y, STATUS_UI_WIDTH, STATUS_UI_HEIGHT};
      LootUI $loot_ui;
      gui::routing::Router $router;
      DNDLoot $dnd_loot;
      System::Registry $systems;
      std::unordered_map<std::string, std::shared_ptr<gui::SceneUI>> $scenes{
        {"STARTING", std::make_shared<gui::SceneUI>("STARTING")},
        {"DEATH", std::make_shared<gui::SceneUI>("DEATH")},
        {"WIN", std::make_shared<gui::SceneUI>("WIN")},
        {"NEXT_LEVEL", std::make_shared<gui::SceneUI>("NEXT_LEVEL")},
      };

      std::shared_ptr<gui::SceneUI> $cur_scene = nullptr;

      FSM();

      void event(game::Event ev, std::any data={});

      void START(game::Event ev);
      void START_SCREEN(game::Event ev);
      void IDLE(game::Event ev, std::any data);
      void MOVING(game::Event ev);
      void ATTACKING(game::Event ev, std::any data);
      void MAPPING(game::Event ev);
      void ROTATING(game::Event ev);
      void LOOTING(game::Event ev, std::any data);
      void END(game::Event ev);

      void try_move(int dir, bool strafe);
      sf::Vector2f mouse_position();
      void mouse_action(guecs::Modifiers mods);
      void handle_keyboard_mouse();
      void draw_gui();
      void update();
      void render();
      bool active();
      void run_systems();
      void handle_world_events();
      void next_level();
      void debug_render();
      void take_screenshot();
  };
}
