#pragma once
#include "constants.hpp"
#include "stats.hpp"
#include "levelmanager.hpp"
#include "fsm.hpp"
#include "render.hpp"
#include "map_view.hpp"
#include "main_ui.hpp"
#include "combat_ui.hpp"
#include "status_ui.hpp"
#include "overlay_ui.hpp"
#include "boss_fight_ui.hpp"

namespace gui {
  enum class State {
    START,
    MOVING,
    IN_COMBAT,
    COMBAT_ROTATE,
    ATTACKING,
    MAPPING,
    ROTATING,
    NEXT_LEVEL,
    IDLE,
    END
  };

  enum class Event {
    STARTED,
    TICK,
    MOVE_FORWARD,
    MOVE_BACK,
    MOVE_LEFT,
    MOVE_RIGHT,
    MAP_OPEN,
    CLOSE,
    ROTATE_LEFT,
    ROTATE_RIGHT,
    ATTACK,
    START_COMBAT,
    STOP_COMBAT,
    STAIRS_DOWN,
    QUIT
  };

  class FSM : public DeadSimpleFSM<State, Event> {
    public:
      sf::RenderWindow $window;
      bool $draw_stats = false;
      bool autowalking = false;
      LevelManager $levels;
      MainUI $main_ui;
      SFMLRender $renderer;
      GameLevel $level;
      shared_ptr<BossFightUI> $boss_fight_ui = nullptr;
      MapViewUI $map_ui;
      CombatUI $combat_ui;
      StatusUI $status_ui;
      sf::Font $font;

      FSM();

      void event(Event ev);
      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);
      void IN_COMBAT(Event ev);
      void COMBAT_ROTATE(Event ev);
      void NEXT_LEVEL(Event ev);
      void END(Event ev);

      void try_move(int dir, bool strafe);
      void keyboard_mouse();
      void draw_gui();
      void render();
      bool active();
      void run_systems();
      void handle_world_events();
      void next_level();
  };
}
