#pragma once

#include <SDL3/SDL.h>

#include <cstdint>
#include <memory>  // Para shared_ptr
#include <string>  // Para string
#include <vector>  // Para vector

#include "game/entities/solid_actor.hpp"  // Para SolidActor

class AnimatedSprite;

// Punto de paso en la ruta de una plataforma
struct Waypoint {
    float x{0.0F};  // Posición en pixels
    float y{0.0F};
    float wait{0.0F};  // Tiempo de parada en este punto (segundos, 0 = sin parada)
};

// Modo de recorrido de la ruta
enum class LoopMode : std::uint8_t { PINGPONG,
    CIRCULAR };

// Tipo de función de easing
using EasingFunc = float (*)(float);

class MovingPlatform : public SolidActor {
   public:
    struct Data {
        std::string animation_path;
        float speed{30.0F};  // px/s a lo largo del path
        LoopMode loop{LoopMode::PINGPONG};
        std::string easing{"linear"};  // Nombre del easing
        int frame{0};                  // Frame inicial (-1 = random)
        std::vector<Waypoint> path;    // Mínimo 2 puntos
    };

    explicit MovingPlatform(const Data& data);
    ~MovingPlatform() = default;

    void update(float delta_time);
    void render();
#ifdef _DEBUG
    void updateAnimation(float delta_time);
    void resetToInitialPosition(const Data& data);
#endif

    auto getRect() -> SDL_FRect;
    auto getCollider() -> SDL_FRect& { return aabb_; }

   private:
    void advanceSegment();
    void recalcSegmentLength();
    [[nodiscard]] auto getSegmentFrom() const -> int;
    [[nodiscard]] auto getSegmentTo() const -> int;
    static auto resolveEasing(const std::string& name) -> EasingFunc;

    std::shared_ptr<AnimatedSprite> sprite_;

    // Estado del path
    std::vector<Waypoint> path_;
    float speed_{0.0F};
    LoopMode loop_mode_{LoopMode::PINGPONG};
    EasingFunc easing_{nullptr};

    int current_segment_{0};        // Índice del segmento actual
    int direction_{1};              // +1 avanzando, -1 retrocediendo (pingpong)
    float segment_progress_{0.0F};  // Progreso dentro del segmento (0.0 a 1.0)
    float segment_length_{0.0F};    // Longitud del segmento actual en pixels
    float wait_timer_{0.0F};        // Tiempo restante de parada
    bool waiting_{false};           // Está parado en un waypoint?
};
