#pragma once

#include "../../../entity.hpp"

#include <imgui.h>
#include <string>
#include <vector>

namespace game::state::play::menu
{
  class Gather
  {
  public:
    Entity player{};
    std::vector<Entity> collectibles{};
    std::vector<Entity> nextCollectibles{};
    std::vector<Entity> staminaPickups{};
    std::vector<Entity> nextStaminaPickups{};
    glm::vec2 targetPosition{};
    float stamina{};
    float boostTime{};
    float magnetRadiusTime{};
    float timeTicks{};
    float timeGainTicks{};
    float timeGainAlpha{};
    int score{};
    int wave{};
    bool isStarted{};
    bool isPaused{};
    bool isMenuFullscreenKnown{};
    bool isMenuFullscreenLast{};
    bool isWaveResetPending{};
    float waveResetAlpha{};

    void update(bool isMenuFullscreen, bool isMenuResizeSettled);

  private:
    enum class Structure
    {
      SINGLE,
      LINE_HORIZONTAL,
      LINE_VERTICAL,
      POLYGON
    };

    static float random_range_get(float, float);
    static glm::vec2 random_position_get(float, float, float, float);
    static Entity collectible_make(glm::vec2);
    static Structure structure_get(int);
    static int structure_count_get(int);
    static int wave_collectible_count_get(int);
    static void collectible_add(std::vector<Entity>&, glm::vec2, int);
    static void single_spawn(std::vector<Entity>&, ImVec2, float, int);
    static void line_spawn(std::vector<Entity>&, ImVec2, float, bool, int, int);
    static float polygon_radius_get(int);
    static void polygon_spawn(std::vector<Entity>&, ImVec2, float, int, int);
    static void wave_spawn(std::vector<Entity>&, ImVec2, int);
    static int stamina_pickup_count_get(int);
    static void stamina_pickups_spawn(std::vector<Entity>&, ImVec2, int);
    static float wave_time_gain_ticks_get();
    static bool collectible_hit_get(const Entity&, const Entity&);
    static float magnet_radius_get(float, bool isMenuFullscreen);
    static int collectibles_collect(std::vector<Entity>&, const Entity&);
    static void collectibles_magnet_update(std::vector<Entity>&, const Entity&, ImVec2, float, float);
    static bool wave_complete_get(const std::vector<Entity>&);
    static void collectibles_draw(const std::vector<Entity>&, ImDrawList*, ImVec2, float, ImU32);
    static void magnet_radius_draw(ImDrawList*, ImVec2, const Entity&, float);
    static int alpha_get(int, float);
    static void progress_bar_draw(ImDrawList*, ImVec2, ImVec2, float, ImU32, ImU32, const std::string& = {});
    static void score_draw(ImDrawList*, ImVec2, int, int);
    static void time_draw(ImDrawList*, ImVec2, ImVec2, float, float, float);
    void reset();
    void start(ImVec2);
    void wave_reset(ImVec2);
    void wave_reset_request();
  };
}
