#pragma once
#include <guecs/ui.hpp>
#include "gui/event_router.hpp"
#include "gui/guecstra.hpp"
#include "events.hpp"
#include <filesystem>

namespace animator {

  enum class State {
    START=__LINE__,
    ANIMATE=__LINE__,
    END=__LINE__,
  };

  enum class Event {
    TICK=__LINE__,
    PLAY_STOP=__LINE__,
    NEXT_FORM=__LINE__,
    PREV_FORM=__LINE__,
    TEST_SHADER=__LINE__,
    RELOAD=__LINE__,
  };

  struct FSM;

  struct UI {
    guecs::UI $ui;
    guecs::UI $overlay;
    std::shared_ptr<sf::Sprite> sprite = nullptr;
    std::shared_ptr<sf::Shader> effect = nullptr;
    bool $initialized_this_sucks_ass = false;

    void button(const std::string& name, std::function<void(guecs::Modifiers mods)> cb);
    void init(const std::string& sprite_name, const std::string& background, int width, int height);
    void render(sf::RenderWindow& window, bool debug=false);
    bool mouse(float x, float y, guecs::Modifiers mods);
    void update_status(animation::Animation& anim);
    std::shared_ptr<sf::Sprite> get_sprite();
    void show_error(const std::string& message);
    void clear_error();
  };

  struct FSM : public DeadSimpleFSM<State, Event> {
    UI $ui;
    gui::routing::Router $router;
    sf::RenderWindow $window;
    sf::Vector2f $pos{0,0};
    sf::Vector2f $scale{0,0};
    animation::Animation $anim;
    std::string $sprite_name="";
    std::string $anim_name="";
    std::string $background="";
    std::filesystem::file_time_type $last_mod_time;
    sf::Clock $timer;
    std::string $cur_form = "idle";
    int $cur_form_i = 0;
    bool $mute = true;

    void init(const std::string &sprite_name, const std::string& background, const std::string &anim_name);
    void event(Event ev, std::any data={});
    void START(Event ev);
    void ANIMATE(Event ev);
    void END(Event ev);

    void handle_keyboard_mouse();
    void render();
    bool active();
    void update();
    void reload();
    void check_changed();
    void change_form(int direction);
  };

}
