#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_t {
    int x;
    int y;
    int w;
};

struct textFile_t {
    int boxWidth;          // Anchura de la caja de cada caracter en el png
    int boxHeight;         // Altura de la caja de cada caracter en el png
    offset_t offset[128];  // Vector con las posiciones y ancho de cada letra
};

// Llena una estructuta textFile_t desde un fichero
textFile_t LoadTextFile(const std::string &file, bool verbose = false);

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

// Clase texto. Pinta texto en pantalla a partir de un bitmap
class Text {
   private:
    // Objetos y punteros
    Sprite *sprite;    // Objeto con los graficos para el texto
    Texture *texture;  // Textura con los bitmaps del texto

    // Variables
    int boxWidth;          // Anchura de la caja de cada caracter en el png
    int boxHeight;         // Altura de la caja de cada caracter en el png
    bool fixedWidth;       // Indica si el texto se ha de escribir con longitud fija en todas las letras
    offset_t offset[128];  // Vector con las posiciones y ancho de cada letra

   public:
    // Constructor
    Text(const std::string &bitmapFile, const std::string &textFile, SDL_Renderer *renderer);
    Text(const std::string &textFile, Texture *texture, SDL_Renderer *renderer);
    Text(textFile_t *textFile, Texture *texture, SDL_Renderer *renderer);

    // Constructor desde bytes en memoria: comparte ownership del texture (no lo libera)
    Text(const std::vector<uint8_t> &pngBytes, const std::vector<uint8_t> &txtBytes, SDL_Renderer *renderer);

    // Destructor
    ~Text();

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

    // Escribe el texto en pantalla
    void write(int x, int y, const std::string &text, int kerning = 1, int lenght = -1);

    // Escribe el texto con colores
    void writeColored(int x, int y, const std::string &text, color_t color, int kerning = 1, int lenght = -1);

    // Escribe el texto con sombra
    void writeShadowed(int x, int y, const std::string &text, color_t color, Uint8 shadowDistance = 1, int kerning = 1, int lenght = -1);

    // Escribe el texto centrado en un punto x
    void writeCentered(int x, int y, const std::string &text, int kerning = 1, int lenght = -1);

    // Escribe texto con extras
    void writeDX(Uint8 flags, int x, int y, const std::string &text, int kerning = 1, color_t textColor = color_t(255, 255, 255), Uint8 shadowDistance = 1, color_t shadowColor = color_t(0, 0, 0), int lenght = -1);

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

    // Devuelve el valor de la variable
    int getCharacterSize();

    // Recarga la textura
    void reLoadTexture();

    // Establece si se usa un tamaño fijo de letra
    void setFixedWidth(bool value);
};
