#pragma once

#include <cstdint>        // Para uint8_t
#include <string>         // Para string
#include <unordered_map>  // Para unordered_map
#include <utility>        // Para move
#include <vector>         // Para vector

namespace Resource {

    // --- Clase List: gestor optimizado de recursos (singleton) ---
    class List {
       public:
        // --- Enums ---
        enum class Type : std::uint8_t {
            DATA,       // Datos
            BITMAP,     // Imágenes
            ANIMATION,  // Animaciones
            MUSIC,      // Música
            SOUND,      // Sonidos
            FONT,       // Fuentes
            ROOM,       // Datos de habitación (.yaml - formato unificado con tilemap)
            PALETTE,    // Paletas
            SIZE,       // Tamaño (para iteración)
        };

        // --- Métodos de singleton ---
        static void init(const std::string& executable_path);
        static void destroy();
        static auto get() -> List*;
        List(const List&) = delete;
        auto operator=(const List&) -> List& = delete;

        // --- Métodos para la gestión de recursos ---
        void add(const std::string& file_path, Type type, bool required = true, bool absolute = false);
        void addAsset(const std::string& path, Type type);                                                                              // Añade al mapa y persiste en assets.yaml
        void removeAsset(const std::string& filename);                                                                                  // Quita del mapa y persiste en assets.yaml
        void loadFromFile(const std::string& config_file_path, const std::string& prefix = "", const std::string& system_folder = "");  // Con soporte para variables
        void loadFromString(const std::string& config_content, const std::string& prefix = "", const std::string& system_folder = "");  // Para cargar desde pack (release)
        [[nodiscard]] auto get(const std::string& filename) const -> std::string;                                                       // Obtiene la ruta completa
        [[nodiscard]] auto loadData(const std::string& filename) const -> std::vector<uint8_t>;                                         // Carga datos del archivo
        [[nodiscard]] auto getListByType(Type type) const -> std::vector<std::string>;
        [[nodiscard]] auto exists(const std::string& filename) const -> bool;  // Verifica si un asset existe

        // --- Helpers static (públics perquè els fan servir parsers externs del .cpp) ---
        [[nodiscard]] static auto parseAssetType(const std::string& type_str) -> Type;                                                                    // Convierte string a tipo
        [[nodiscard]] static auto replaceVariables(const std::string& path, const std::string& prefix, const std::string& system_folder) -> std::string;  // Reemplaza variables en la ruta

       private:
        // --- Estructuras privadas ---
        struct Item {
            std::string file;  // Ruta completa del archivo
            Type type;         // Tipo de recurso
            bool required;     // Indica si el archivo es obligatorio

            Item(std::string path, Type asset_type, bool is_required)
                : file(std::move(path)),
                  type(asset_type),
                  required(is_required) {}
        };

        // --- Variables internas ---
        std::unordered_map<std::string, Item> file_list_;  // Mapa para búsqueda O(1)
        std::string executable_path_;                      // Ruta del ejecutable
        std::string config_file_path_;                     // Ruta del fichero assets.yaml
        std::string prefix_;                               // Prefijo para rutas (${PREFIX})

        // --- Métodos internos ---
        [[nodiscard]] static auto getTypeName(Type type) -> std::string;                               // Obtiene el nombre del tipo
        void addToMap(const std::string& file_path, Type type, bool required, bool absolute);          // Añade archivo al mapa
        static auto parseOptions(const std::string& options, bool& required, bool& absolute) -> void;  // Parsea opciones

        // --- Constructores y destructor privados (singleton) ---
        explicit List(std::string executable_path)  // Constructor privado
            : executable_path_(std::move(executable_path)) {}
        ~List() = default;  // Destructor privado

        // --- Instancia singleton ---
        static List* instance;  // Instancia única de List
    };

}  // namespace Resource
