#include <frostbite2D/2d/text_sprite.h>
#include <frostbite2D/graphics/font_manager.h>
#include <frostbite2D/graphics/texture.h>
#include <SDL2/SDL.h>
#include <SDL2/SDL_ttf.h>

namespace frostbite2D {

TextSprite::TextSprite()
  : Sprite() {
}

TextSprite::~TextSprite() {
}

Ptr<TextSprite> TextSprite::create() {
  return MakePtr<TextSprite>();
}

Ptr<TextSprite> TextSprite::create(const std::string& text, const std::string& fontName) {
  auto textSprite = MakePtr<TextSprite>();
  textSprite->SetFont(fontName);
  textSprite->SetText(text);
  return textSprite;
}

void TextSprite::SetText(const std::string& text) {
  if (text_ != text) {
    text_ = text;
    RenderText();
  }
}

void TextSprite::SetFont(const std::string& fontName) {
  if (fontName_ != fontName) {
    fontName_ = fontName;
    RenderText();
  }
}

void TextSprite::SetTextColor(const Color& color) {
  textColor_ = color;
  RenderText();
}

void TextSprite::SetTextColor(float r, float g, float b, float a) {
  textColor_ = Color(r, g, b, a);
  RenderText();
}

void TextSprite::SetAlign(Align align) {
  if (align_ != align) {
    align_ = align;
    RenderText();
  }
}

void TextSprite::RenderText() {
  if (text_.empty() || fontName_.empty()) {
    return;
  }

  FontManager& fontMgr = FontManager::get();
  TTF_Font* font = fontMgr.getFont(fontName_);
  if (!font) {
    SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Font '%s' not found for text rendering", fontName_.c_str());
    return;
  }

  SDL_Color sdlColor;
  sdlColor.r = static_cast<Uint8>(textColor_.r * 255.0f);
  sdlColor.g = static_cast<Uint8>(textColor_.g * 255.0f);
  sdlColor.b = static_cast<Uint8>(textColor_.b * 255.0f);
  sdlColor.a = static_cast<Uint8>(textColor_.a * 255.0f);

  SDL_Surface* surface = TTF_RenderUTF8_Blended(font, text_.c_str(), sdlColor);
  if (!surface) {
    SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to render text: %s", TTF_GetError());
    return;
  }

  SDL_PixelFormat* rgbaFormat = SDL_AllocFormat(SDL_PIXELFORMAT_RGBA8888);
  SDL_Surface* converted = SDL_ConvertSurface(surface, rgbaFormat, 0);
  SDL_FreeSurface(surface);
  surface = converted;
  SDL_FreeFormat(rgbaFormat);

  if (!surface) {
    SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to convert text surface: %s", SDL_GetError());
    return;
  }

  int width = surface->w;
  int height = surface->h;

  std::vector<uint8> rgbaData(width * height * 4);
  uint8* pixels = static_cast<uint8*>(surface->pixels);
  for (int i = 0; i < width * height; i++) {
    rgbaData[i * 4 + 0] = pixels[i * 4 + 0];
    rgbaData[i * 4 + 1] = pixels[i * 4 + 1];
    rgbaData[i * 4 + 2] = pixels[i * 4 + 2];
    rgbaData[i * 4 + 3] = pixels[i * 4 + 3];
  }

  SDL_FreeSurface(surface);

  Ptr<Texture> texture = Texture::createFromMemory(
    rgbaData.data(),
    width,
    height,
    4
  );

  if (texture) {
    SetTexture(texture);
    SetSizeToTexture();
  }
}

Vec2 TextSprite::GetTextSize() const {
  if (text_.empty() || fontName_.empty()) {
    return Vec2::Zero();
  }

  FontManager& fontMgr = FontManager::get();
  TTF_Font* font = fontMgr.getFont(fontName_);
  if (!font) {
    return Vec2::Zero();
  }

  int w = 0;
  int h = 0;
  TTF_SizeUTF8(font, text_.c_str(), &w, &h);
  return Vec2(static_cast<float>(w), static_cast<float>(h));
}

void TextSprite::updateTexture() {
  RenderText();
}

}
