// resource_loader.cpp - Implementació del carregador de recursos
// © 2025 Port a C++20 amb SDL3

#include "resource_loader.hpp"

#include <filesystem>
#include <fstream>
#include <iostream>

namespace Resource {

// Singleton
Loader& Loader::get() {
    static Loader instance;
    return instance;
}

// Inicialitzar el sistema de recursos
bool Loader::initialize(const std::string& pack_file, bool enable_fallback) {
    fallback_enabled_ = enable_fallback;

    // Intentar carregar el paquet
    pack_ = std::make_unique<Pack>();

    if (!pack_->loadPack(pack_file)) {
        if (!fallback_enabled_) {
            std::cerr << "[ResourceLoader] ERROR FATAL: No es pot carregar " << pack_file
                      << " i el fallback està desactivat\n";
            return false;
        }

        std::cout << "[ResourceLoader] Paquet no trobat, usant fallback al sistema de fitxers\n";
        pack_.reset();  // No hi ha paquet
        return true;
    }

    std::cout << "[ResourceLoader] Paquet carregat: " << pack_file << "\n";
    return true;
}

// Carregar un recurs
std::vector<uint8_t> Loader::loadResource(const std::string& filename) {
    // Intentar carregar del paquet primer
    if (pack_) {
        if (pack_->hasResource(filename)) {
            auto data = pack_->getResource(filename);
            if (!data.empty()) {
                return data;
            }
            std::cerr << "[ResourceLoader] Advertència: recurs buit al paquet: " << filename
                      << "\n";
        }

        // Si no està al paquet i no hi ha fallback, falla
        if (!fallback_enabled_) {
            std::cerr << "[ResourceLoader] ERROR: Recurs no trobat al paquet i fallback desactivat: "
                      << filename << "\n";
            return {};
        }
    }

    // Fallback al sistema de fitxers
    if (fallback_enabled_) {
        return loadFromFilesystem(filename);
    }

    return {};
}

// Comprovar si existeix un recurs
bool Loader::resourceExists(const std::string& filename) {
    // Comprovar al paquet
    if (pack_ && pack_->hasResource(filename)) {
        return true;
    }

    // Comprovar al sistema de fitxers si està activat el fallback
    if (fallback_enabled_) {
        std::string fullpath = base_path_.empty() ? "data/" + filename : base_path_ + "/data/" + filename;
        return std::filesystem::exists(fullpath);
    }

    return false;
}

// Validar el paquet
bool Loader::validatePack() {
    if (!pack_) {
        std::cerr << "[ResourceLoader] Advertència: no hi ha paquet carregat per validar\n";
        return false;
    }

    return pack_->validatePack();
}

// Comprovar si hi ha paquet carregat
bool Loader::isPackLoaded() const {
    return pack_ != nullptr;
}

// Establir la ruta base
void Loader::setBasePath(const std::string& path) {
    base_path_ = path;
    std::cout << "[ResourceLoader] Ruta base establerta: " << base_path_ << "\n";
}

// Obtenir la ruta base
std::string Loader::getBasePath() const {
    return base_path_;
}

// Carregar des del sistema de fitxers (fallback)
std::vector<uint8_t> Loader::loadFromFilesystem(const std::string& filename) {
    // The filename is already normalized (e.g., "shapes/logo/letra_j.shp")
    // We need to prepend base_path + "data/"
    std::string fullpath;

    if (base_path_.empty()) {
        fullpath = "data/" + filename;
    } else {
        fullpath = base_path_ + "/data/" + filename;
    }

    std::ifstream file(fullpath, std::ios::binary | std::ios::ate);
    if (!file) {
        std::cerr << "[ResourceLoader] Error: no es pot obrir " << fullpath << "\n";
        return {};
    }

    std::streamsize file_size = file.tellg();
    file.seekg(0, std::ios::beg);

    std::vector<uint8_t> data(file_size);
    if (!file.read(reinterpret_cast<char*>(data.data()), file_size)) {
        std::cerr << "[ResourceLoader] Error: no es pot llegir " << fullpath << "\n";
        return {};
    }

    std::cout << "[ResourceLoader] Carregat des del sistema de fitxers: " << fullpath << "\n";
    return data;
}

}  // namespace Resource
