#pragma once

#include <SDL3/SDL.h>

#include <cstdint>
#include <string>  // for string
#include <vector>
class Sprite;
class Texture;
#include "utils/utils.h"

// Opciones de texto
constexpr int TXT_COLOR = 1;
constexpr int TXT_SHADOW = 2;
constexpr int TXT_CENTER = 4;
constexpr int TXT_STROKE = 8;

struct Offset {
    int x;
    int y;
    int w;
};

struct TextFile {
    int box_width;       // Anchura de la caja de cada caracter en el png
    int box_height;      // Altura de la caja de cada caracter en el png
    Offset offset[128];  // Vector con las posiciones y ancho de cada letra
};

// Llena una estructuta TextFile desde un fichero
auto loadTextFile(const std::string &file, bool verbose = false) -> TextFile;

// Llena una estructura TextFile desde bytes en memoria
auto loadTextFileFromMemory(const std::vector<uint8_t> &bytes, bool verbose = false) -> TextFile;

// Clase texto. Pinta texto en pantalla a partir de un bitmap
class Text {
   public:
    Text(const std::string &bitmap_file, const std::string &text_file, SDL_Renderer *renderer);  // Constructor
    Text(const std::string &text_file, Texture *texture, SDL_Renderer *renderer);
    Text(TextFile *text_file, Texture *texture, SDL_Renderer *renderer);
    Text(const std::vector<uint8_t> &png_bytes, const std::vector<uint8_t> &txt_bytes, SDL_Renderer *renderer);  // Constructor desde bytes en memoria: comparte ownership del texture (no lo libera)

    ~Text();  // Destructor

    // No copiable (gestiona memoria dinámica)
    Text(const Text &) = delete;
    auto operator=(const Text &) -> Text & = delete;

    void write(int x, int y, const std::string &text, int kerning = 1, int lenght = -1);                                                                                                                          // Escribe el texto en pantalla
    void writeColored(int x, int y, const std::string &text, Color color, int kerning = 1, int lenght = -1);                                                                                                      // Escribe el texto con colores
    void writeShadowed(int x, int y, const std::string &text, Color color, Uint8 shadow_distance = 1, int kerning = 1, int lenght = -1);                                                                          // Escribe el texto con sombra
    void writeCentered(int x, int y, const std::string &text, int kerning = 1, int lenght = -1);                                                                                                                  // Escribe el texto centrado en un punto x
    void writeDX(Uint8 flags, int x, int y, const std::string &text, int kerning = 1, Color text_color = Color(255, 255, 255), Uint8 shadow_distance = 1, Color shadow_color = Color(0, 0, 0), int lenght = -1);  // Escribe texto con extras

    auto lenght(const std::string &text, int kerning = 1) -> int;  // Obtiene la longitud en pixels de una cadena

    [[nodiscard]] auto getCharacterSize() const -> int;  // Devuelve el valor de la variable

    void reLoadTexture();            // Recarga la textura
    void setFixedWidth(bool value);  // Establece si se usa un tamaño fijo de letra

   private:
    // Objetos y punteros
    Sprite *sprite_;    // Objeto con los graficos para el texto
    Texture *texture_;  // Textura con los bitmaps del texto

    // Variables
    int box_width_;       // Anchura de la caja de cada caracter en el png
    int box_height_;      // Altura de la caja de cada caracter en el png
    bool fixed_width_;    // Indica si el texto se ha de escribir con longitud fija en todas las letras
    Offset offset_[128];  // Vector con las posiciones y ancho de cada letra
};
