#pragma once

#include "constants.hpp"
#include "levelmanager.hpp"
#include "simplefsm.hpp"
#include "gui/debug_ui.hpp"
#include "gui/main_ui.hpp"
#include "gui/combat_ui.hpp"
#include "gui/status_ui.hpp"
#include "gui/loot_ui.hpp"
#include "gui/boss_fight_ui.hpp"
#include "gui/map_view.hpp"
#include "gui/mini_map.hpp"
#include "events.hpp"
#include "gui/event_router.hpp"
#include "gui/dnd_loot.hpp"

namespace gui {
  enum class State {
    START=0,
    MOVING=1,
    IN_COMBAT=2,
    COMBAT_ROTATE=3,
    ATTACKING=4,
    ROTATING=5,
    NEXT_LEVEL=6,
    LOOTING=7,
    IDLE=8,
    END=9
  };

  class FSM : public DeadSimpleFSM<State, Event> {
    public:
      sf::RenderWindow $window;
      bool $draw_stats = false;
      bool autowalking = false;
      bool $map_open = false;
      int $temp_attack_id = 0;
      LevelManager $levels;
      DebugUI $debug_ui;
      MainUI $main_ui;
      GameLevel $level;
      shared_ptr<BossFightUI> $boss_fight_ui = nullptr;
      CombatUI $combat_ui;
      StatusUI $status_ui;
      MapViewUI $map_ui;
      MiniMapUI $mini_map;
      LootUI $loot_ui;
      sf::Font $font;
      gui::routing::Router $router;
      DNDLoot $dnd_loot;

      FSM();

      void event(Event ev, std::any data={});
      void autowalk();
      void start_autowalk(double rot_speed);

      void START(Event );
      void MOVING(Event );
      void ATTACKING(Event );
      void MAPPING(Event);
      void ROTATING(Event );
      void IDLE(Event ev, std::any data);
      void IN_COMBAT(Event ev);
      void COMBAT_ROTATE(Event ev);
      void NEXT_LEVEL(Event ev);
      void LOOTING(Event ev, std::any data);
      void END(Event ev);

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