#pragma once

#include <string>   // Para string
#include <utility>  // Para move
#include <vector>   // Para vector

// Tipos de recursos gestionados por Asset
enum class AssetType : int {
    BITMAP,
    MUSIC,
    SOUND,
    FONT,
    LANG,
    DATA,
    DEMODATA,
    ANIMATION,
    PALETTE,
    COUNT,
};

// Clase Asset: gestor de recursos (singleton)
class Asset {  // Gestor de recursos (singleton)
    public:
        // --- Métodos de singleton ---
        static void init(const std::string &executable_path);  // Inicializa el objeto Asset
        static void destroy();                                 // Libera el objeto Asset
        static auto get() -> Asset *;                          // Obtiene el puntero al objeto Asset
        Asset(const Asset &) = delete;                         // No se permite copiar
        auto operator=(const Asset &) -> Asset & = delete;     // No se permite asignar

        // --- Métodos para la gestión de recursos ---
        void add(const std::string &file, AssetType type, bool required = true, bool absolute = false);  // Añade un recurso a la lista
        [[nodiscard]] auto get(const std::string &text) const -> std::string;                            // Obtiene la ruta completa de un recurso a partir de su nombre
        [[nodiscard]] auto check() const -> bool;                                                        // Verifica la existencia de todos los recursos requeridos
        [[nodiscard]] auto getListByType(AssetType type) const -> std::vector<std::string>;              // Devuelve una lista de archivos de un tipo concreto

    private:
        // --- Estructura interna para almacenar información de cada recurso ---
        struct AssetItem {         // Estructura para cada recurso
                std::string file;  // Ruta del fichero desde la raíz del directorio
                AssetType type;    // Tipo de recurso
                bool required;     // Indica si el fichero es obligatorio

                AssetItem(std::string file_path, AssetType asset_type, bool is_required)
                    : file(std::move(file_path)), type(asset_type), required(is_required) {}  // Constructor
        };

        // --- Variables internas ---
        int longest_name_ = 0;              // Longitud del nombre más largo
        std::vector<AssetItem> file_list_;  // Lista con todas las rutas de recursos
        std::string executable_path_;       // Ruta del ejecutable

        // --- Métodos internos ---
        [[nodiscard]] static auto checkFile(const std::string &path) -> bool;  // Verifica si un archivo existe (interno)
        [[nodiscard]] static auto getTypeName(AssetType type) -> std::string;  // Devuelve el nombre textual del tipo de recurso (interno)

        // --- Patrón Singleton ---
        explicit Asset(std::string executable_path)
            : executable_path_(std::move(executable_path)) {}  // Constructor privado
        ~Asset() = default;                                    // Destructor

        // --- Singleton ---
        static Asset *instance;  // Instancia singleton
};