#include "assetManager.h"

#include <SDL2/SDL_image.h>
#include <SDL2/SDL_rwops.h>
#include <iostream>

using namespace std;
using namespace quokka_gfx;
//------------------------------------------------------------
AssetManager::AssetManager(SDL_Renderer *renderer)
{
  // Initialization
  m_renderer = renderer;
}
//------------------------------------------------------------
void AssetManager::clear()
{
  m_textures.clear();
  m_fonts.clear();
}
//------------------------------------------------------------
bool AssetManager::loadTexture(const HashID &id, const std::filesystem::path &filePath)
{
  // Check if the texture is already loaded
  if (m_textures.contains(id))
    return false;

  // Load the texture from the file path
  SDL_Texture *texture = IMG_LoadTexture(m_renderer, filePath.string().c_str());
  if (!texture)
  {
    cerr << format("Failed to load texture: {}, Error: {}",
                   filePath.string(),
                   SDL_GetError());
    return false;
  }

  // Store the texture in the map and return it
  m_textures.emplace(id, Texture(texture, SDL_DestroyTexture));
  return true;
}
//------------------------------------------------------------
/* Load a texture from a memory buffer */
bool AssetManager::loadTexture(const HashID &id, const std::span<const uint8_t> &buffer)
{
  // Check if the texture is already loaded
  if (m_textures.contains(id))
    return false;

  // Load the texture from the memory buffer
  const auto rw = SDL_RWFromConstMem(buffer.data(), static_cast<int>(buffer.size()));
  if (!rw)
  {
    cerr << format("Failed to create RWops from memory buffer, Error: {}",
                   SDL_GetError());
    return false;
  }

  SDL_Texture *texture = IMG_LoadTexture_RW(m_renderer, rw, 1);
  if (!texture)
  {
    cerr << format("Failed to load texture from memory buffer, Error: {}",
                   SDL_GetError());
    return false;
  }

  // Store the texture in the map and return it
  m_textures.emplace(id, Texture(texture, SDL_DestroyTexture));
  return true;
}
//------------------------------------------------------------
SDL_Texture *AssetManager::getTexture(const HashID &id) const
{
  if (m_textures.contains(id))
    return m_textures.at(id).get();

  cerr << format("Texture with ID '{}' not found.", id);
  return nullptr;
}
//------------------------------------------------------------
void AssetManager::unloadTexture(const HashID &id)
{
  m_textures.erase(id);
}
//------------------------------------------------------------
/* Load a font from a file path with a specific size */
TTF_Font *AssetManager::loadFont(const HashID &id, const std::filesystem::path &filePath, int fontSize)
{
  // Check if the font is already loaded
  if (m_fonts.contains(id))
    return m_fonts.at(id).get();

  // Load the font from the file path
  TTF_Font *font = TTF_OpenFont(filePath.string().c_str(), fontSize);
  if (!font)
  {
    cerr << format("Failed to load font: {}, Error: {}", filePath.string(), TTF_GetError());
    return nullptr;
  }

  // Store the font in the map and return it
  m_fonts.emplace(id, Font(font, TTF_CloseFont));
  return font;
}
//------------------------------------------------------------
/* Get a font by its ID */
TTF_Font *AssetManager::getFont(const HashID &id) const
{
  if (m_fonts.contains(id))
    return m_fonts.at(id).get();

  cerr << format("Font with ID '{}' not found.", id);
  return nullptr;
}
//------------------------------------------------------------
/* Unload a font by its ID */
void AssetManager::unloadFont(const HashID &id)
{
  m_fonts.erase(id);
}
//------------------------------------------------------------
