#pragma once

#include <string>
#include <vector>
#include <memory>
#include <iostream>
#include "utils.h"

// 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
{
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 Asset *get();								  // Obtiene el puntero al objeto Asset

	// --- 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
	std::string get(const std::string &text) const;													// Obtiene la ruta completa de un recurso a partir de su nombre
	bool check() const;																				// Verifica la existencia de todos los recursos requeridos
	std::vector<std::string> getListByType(AssetType type) const;									// Devuelve una lista de archivos de un tipo concreto

private:
	// --- Estructura interna para almacenar información de cada recurso ---
	struct AssetItem
	{
		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(const std::string &filePath, AssetType assetType, bool isRequired)
			: file(filePath), type(assetType), required(isRequired) {}
	};

	// --- 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 ---
	bool checkFile(const std::string &path) const; // Verifica si un archivo existe
	std::string getTypeName(AssetType type) const; // Devuelve el nombre textual del tipo de recurso

	// --- Patrón Singleton ---
	explicit Asset(const std::string &executable_path)
		: executable_path_(executable_path) {}
	~Asset() = default;
	Asset(const Asset &) = delete;
	Asset &operator=(const Asset &) = delete;

	// --- Singleton ---
	static Asset *instance_;
};