#include <iostream>
#include <vector>
#include <string>
#include <filesystem>

#include "quill/LogMacros.h"

#include "resourceManager.h"
#include "resourceManagerTypes.h"
#include "debug.h"

#include "config.h"

#define STRINGIFY(x) #x
#define TOSTRING(x) STRINGIFY(x)

ResourceManager::ResourceManager() {
    std::string defaultDataDir = TOSTRING(DATA_DIR);
    m_dataDir = m_config.get<std::string>("Data:Dir", defaultDataDir);
    // -- Get the index file path using filesytem to make it a system safe path
    std::string indexFilePath = m_dataDir + "/index.yaml";
    std::filesystem::path indexFile(indexFilePath);

    m_resourceConfig.loadConfig(indexFile.string());
    std::vector<std::string> assets = m_resourceConfig.keys();
    for (auto key : assets ) {
        load(key);
    }
}


std::vector<std::string> ResourceManager::getAvaliableResources() {
    std::vector<std::string> resources;
    resources = m_resourceConfig.keys();
    return resources;
}

const Resource& ResourceManager::getResource(const std::string &name) const {
    auto it = m_resources.find(name);
    if (it != m_resources.end()) {
        return it->second;
    }
    throw std::runtime_error("Resource " + name + " not found");
}


bool ResourceManager::loadResource(std::string& name) {
    return load(name);
}

bool ResourceManager::load(const std::string& name) {
    const std::string resourcePath = m_dataDir + "/" + m_resourceConfig.get<std::string>(name);
    std::filesystem::path resourceFile(resourcePath);
    if (!std::filesystem::exists(resourceFile)) {
        LOG_ERROR(m_logger, "Resource file not found: {}", resourceFile.string());
        return false;
    }
    LOG_INFO(m_logger, "Loading resource: {}", resourceFile.string());
    if (m_resources.find(name) != m_resources.end()) {
        LOG_INFO(m_logger, "Resource already loaded: {}", name);
        return true;
    }
    Resource resource = createResource(name, resourcePath);
    m_resources[name] = std::move(resource);
    // -- Check if the resource is already in the map
    return true;
}

