#include <AssetManager/AssetManager.hpp>
#include <Log/Log.hpp>
#include <Utilities/Utilities.hpp>
#include <filesystem>
#include <fstream>

AssetManager assets;

void AssetManager::loadFromIndex(const std::string &casDir, const std::string &indexPath)
{
    std::ifstream ifs(indexPath);

    std::string line;
    while (std::getline(ifs, line))
    {
        std::string hash = line.substr(0, 64);  // SHA256 is 64 chars.
        std::string relPath = line.substr(65);  // Skip hash and space.
        std::string ext = relPath.substr(relPath.find_last_of(".") + 1);

        assetsIndex[relPath] = formatString(
            "$+/$+/$+.$+",
            casDir,
            hash.substr(0, 2),
            hash,
            ext
        );
    }

    ifs.close();
    Log::info(formatString(
        "Loaded $+ asset mappings\n  CAS Directory: $+\n  Index file: $+",
        assetsIndex.size(),
        casDir,
        indexPath
    ));
}

void AssetManager::init()
{
    char *envAssetsDir = getenv("VOXELVERSE_ASSETS_DIR");
    if (envAssetsDir != nullptr)
    {
        assetsDir = envAssetsDir;
    }

    Log::info(formatString("Assets directory: $+", assetsDir));

    char *envCasDir = getenv("VOXELVERSE_ASSETS_CAS");
    char *envCasIndex = getenv("VOXELVERSE_ASSETS_INDEX");

    if (envCasDir != NULL && envCasIndex != NULL)
    {
        loadFromIndex(envCasDir, envCasIndex);
    }
}

std::string AssetManager::resolve(const std::string &assetPath)
{
    auto it = assetsIndex.find(assetPath);
    if (it != assetsIndex.end())
    {
        return it->second;
    }

    return formatString("$+/$+", assetsDir, assetPath);
}

bool AssetManager::exists(const std::string &assetPath)
{
    return std::filesystem::exists(resolve(assetPath));
}