//
// Created by sebastian on 30.07.26.
//

#include "AssetManager.h"

#include <iostream>
#include <ostream>

std::shared_ptr<engine::Model> engine::AssetManager::getModel(const std::string &name) const {
    auto it = m_models.find(name);
    if (it == m_models.end()) {
        throw std::runtime_error("Model not found: " + name);
    }
    return it->second;
}

bool engine::AssetManager::hasModel(const std::string &name) const {
    return m_models.contains(name);
}

void engine::AssetManager::insertAsset(LoadedAsset loadedAsset) {
    std::cout << "Inserting asset: " << std::endl;
    std::visit([this](const auto& loaded) {
        using T = std::decay_t<decltype(loaded)>;

        if constexpr (std::is_same_v<T, LoadedModel>) {
            insertModel(loaded.name, loaded.model);
        } else if constexpr (std::is_same_v<T, LoadedTexture>) {
            insertTexture(loaded.name, loaded.texture);
        } else if constexpr (std::is_same_v<T, LoadedSound>) {
            insertSound(loaded.name, loaded.sound);
        }
    }, loadedAsset);
}

void engine::AssetManager::insertModel(const std::string &name, std::shared_ptr<Model> model) {
    std::cout << "Inserting model " << name << std::endl;
    m_models[name] = std::move(model);
}

void engine::AssetManager::unloadModel(const std::string &name) {
    m_models.erase(name);
}

std::shared_ptr<engine::Texture2D> engine::AssetManager::getTexture(const std::string &name) const {
    auto it = m_textures.find(name);
    if (it == m_textures.end()) {
        throw std::runtime_error("Texture not found: " + name);
    }
    return it->second;
}

bool engine::AssetManager::hasTexture(const std::string &name) const {
    return m_textures.contains(name);
}

void engine::AssetManager::insertTexture(const std::string &name, std::shared_ptr<Texture2D> texture) {
    std::cout << "Inserting texture " << name << std::endl;
    m_textures[name] = std::move(texture);
}

void engine::AssetManager::unloadTexture(const std::string &name) {
    m_textures.erase(name);
}

std::shared_ptr<engine::audio::SoundBuffer> engine::AssetManager::getSound(const std::string &name) const {
    auto it = m_loadedAssets.find(name);
    if (it == m_loadedAssets.end()) {
        throw std::runtime_error("Sound not found: " + name);
    }
    return it->second;
}

bool engine::AssetManager::hasSound(const std::string &name) const {
    return m_loadedAssets.contains(name);
}

void engine::AssetManager::insertSound(const std::string &name, std::shared_ptr<audio::SoundBuffer> sound) {
    std::cout << "Inserting sound " << name << std::endl;
    m_loadedAssets[name] = std::move(sound);
}

void engine::AssetManager::unloadSound(const std::string &name) {
    m_loadedAssets.erase(name);
}
