#pragma once
#include "constants.hpp"
#include "stats.hpp"
#include "levelmanager.hpp"
#include "fsm.hpp"
#include "map_view.hpp"
#include "main_ui.hpp"
#include "combat_ui.hpp"
#include "status_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=0,
    TICK=1,
    MOVE_FORWARD = 2,
    MOVE_BACK = 3,
    MOVE_LEFT = 4,
    MOVE_RIGHT = 5,
    MAP_OPEN = 6,
    CLOSE = 7,
    ROTATE_LEFT = 8,
    ROTATE_RIGHT = 9,
    ATTACK = 10,
    START_COMBAT = 11,
    STOP_COMBAT = 12,
    STAIRS_DOWN = 13,
    QUIT = 14
  };

  class FSM : public DeadSimpleFSM<State, Event> {
    public:
      sf::RenderWindow $window;
      bool $draw_stats = false;
      bool autowalking = false;
      LevelManager $levels;
      MainUI $main_ui;
      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();
  };
}