#pragma once

#include <SDL3/SDL.h>

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

#include "utils/defines.hpp"

class Surface;
class Sprite;

class TilemapRenderer {
   public:
    TilemapRenderer(std::vector<int> tile_map, int tile_set_width, std::shared_ptr<Surface> tileset_surface, Uint8 bg_color, int conveyor_belt_direction);
    ~TilemapRenderer() = default;

    TilemapRenderer(const TilemapRenderer&) = delete;
    auto operator=(const TilemapRenderer&) -> TilemapRenderer& = delete;
    TilemapRenderer(TilemapRenderer&&) = delete;
    auto operator=(TilemapRenderer&&) -> TilemapRenderer& = delete;

    void initialize(const std::vector<int>& collision_tile_map);
    void update(float delta_time);
    void render();

#ifdef _DEBUG
    void redrawMap(const std::vector<int>& collision_tile_map);
    void setTile(int index, int tile_value);
#endif

    void setPaused(bool paused) { is_paused_ = paused; }
    [[nodiscard]] auto getMapSurface() const -> std::shared_ptr<Surface> { return map_surface_; }

   private:
    struct AnimatedTile {
        std::shared_ptr<Sprite> sprite{nullptr};
        int x_orig{0};
    };

    static constexpr int TILE_SIZE = Tile::SIZE;
    static constexpr int MAP_WIDTH = Map::WIDTH;
    static constexpr int MAP_HEIGHT = Map::HEIGHT;
    static constexpr int PLAY_AREA_WIDTH = PlayArea::WIDTH;
    static constexpr int PLAY_AREA_HEIGHT = PlayArea::HEIGHT;
    static constexpr float CONVEYOR_FRAME_DURATION = 0.05F;
    static constexpr int COLLISION_ANIMATED = 6;  // Valor del tile de conveyor en el collision tilemap
    static constexpr int ANIMATED_TILE_ROW = 18;  // Fila del tileset que contiene los tiles animados

    [[nodiscard]] auto isAnimatedTile(int tile_value) const -> bool;

    std::vector<int> tile_map_;
    int tile_set_width_;
    std::shared_ptr<Surface> tileset_surface_;
    Uint8 bg_color_{0};
    int conveyor_belt_direction_;

    std::shared_ptr<Surface> map_surface_;
    std::vector<AnimatedTile> animated_tiles_;
    float time_accumulator_{0.0F};
    bool is_paused_{false};

    void fillMapTexture(const std::vector<int>& collision_tile_map);
    void setAnimatedTiles(const std::vector<int>& collision_tile_map);
    void updateAnimatedTiles();
    void renderAnimatedTiles();
};
