#pragma once
#include "simplefsm.hpp"
#include <guecs/ui.hpp>
#include "gui/status_ui.hpp"
#include "gui/loot_ui.hpp"
#include "gui/event_router.hpp"

namespace gui {
  enum class DNDState {
    START=100,
    LOOTING=101,
    LOOT_GRAB=102,
    INV_GRAB=103,
    ITEM_PICKUP=104,
    INV_PICKUP=105,
    END=106
  };

  class DNDLoot : public DeadSimpleFSM<DNDState, Event> {
    public:
      std::optional<guecs::Entity> $grab_source = std::nullopt;
      std::shared_ptr<sf::Sprite> $grab_sprite = nullptr;
      StatusUI& $status_ui;
      LootUI& $loot_ui;
      sf::RenderWindow& $window;
      routing::Router& $router;

      DNDLoot(StatusUI& status_ui,
          LootUI& loot_ui, sf::RenderWindow& window,
          routing::Router& router);

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

      void START(Event ev);
      void LOOTING(Event ev, std::any data);
      void LOOT_GRAB(Event ev, std::any data);
      void INV_GRAB(Event ev, std::any data);
      void END(Event ev, std::any data={});
      void ITEM_PICKUP(Event ev, std::any data);
      void INV_PICKUP(Event ev, std::any data);

      void handle_mouse(Event ev, guecs::UI& gui);
      void render();
      void open();
      void close();

      std::optional<guecs::Entity> start_grab(guecs::UI& gui, std::any data);

      bool commit_drop(guecs::UI& source, guecs::UI& target,
          std::optional<guecs::Entity> source_id, std::any data);

      bool commit_move(guecs::UI& gui,
          std::optional<guecs::Entity> source_id, guecs::Entity drop_id);

      bool hold_item(guecs::UI& gui, guecs::Entity gui_id);
      bool throw_on_floor(guecs::UI& gui, bool from_status);

      void clear_grab();

      bool move_or_swap(StatusUI& status_ui, guecs::Entity drop_id);
      bool move_or_swap(LootUI& ui, guecs::Entity drop_id);

      sf::Vector2f mouse_position();
  };
}
