#pragma once

#include <SDL3/SDL.h>  // Para Uint8

#include <array>   // Para array
#include <memory>  // Para shared_ptr, unique_ptr
#include <string>  // Para string

#include "color.h"   // Para Color
#include "sprite.h"  // Para Sprite

class Texture;

// --- Constantes para flags de texto ---
constexpr int TEXT_COLOR = 1;
constexpr int TEXT_SHADOW = 2;
constexpr int TEXT_CENTER = 4;
constexpr int TEXT_STROKE = 8;

// --- Estructuras auxiliares ---
struct TextOffset {
        int x, y, 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
        std::array<TextOffset, 128> offset = {};  // Vector con las posiciones y ancho de cada letra
};

struct TextStyle {
        Color text_color;
        Color shadow_color;
        Uint8 shadow_distance;
        int kerning;

        // Constructor con argumentos por defecto
        TextStyle(Color text = Color(),
            Color shadow = Color(),
            Uint8 distance = 1,
            int kern = 1)
            : text_color(text),
              shadow_color(shadow),
              shadow_distance(distance),
              kerning(kern) {}
};

// Llena una estructura TextFile desde un fichero
auto loadTextFile(const std::string &file_path) -> std::shared_ptr<TextFile>;

// --- Clase Text: pinta texto en pantalla a partir de un bitmap ---
class Text {
    public:
        // --- Constructores y destructor ---
        Text(std::shared_ptr<Texture> texture, const std::string &text_file);
        Text(std::shared_ptr<Texture> texture, std::shared_ptr<TextFile> text_file);
        ~Text() = default;

        // --- Métodos de escritura en pantalla ---
        void write(int x, int y, const std::string &text, int kerning = 1, int lenght = -1);  // Escribe el texto en pantalla
        void write2X(int x, int y, const std::string &text, int kerning = 1);                 // Escribe el texto al doble de tamaño

        // --- Escritura en textura ---
        auto writeToTexture(const std::string &text, int zoom = 1, int kerning = 1) -> std::shared_ptr<Texture>;                                                                                                         // Escribe el texto en una textura
        auto writeDXToTexture(Uint8 flags, const std::string &text, int kerning = 1, Color text_color = Color(), Uint8 shadow_distance = 1, Color shadow_color = Color(), int lenght = -1) -> std::shared_ptr<Texture>;  // Escribe el texto con extras en una textura

        // --- Métodos de escritura avanzada ---
        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(), Uint8 shadow_distance = 1, Color shadow_color = Color(), int lenght = -1);  // Escribe texto con extras
        void writeDX(Uint8 flags, int x, int y, const std::string &text, const TextStyle &style, int length = -1);                                                                                // Escribe texto a partir de un TextStyle

        // --- Utilidades ---
        [[nodiscard]] auto lenght(const std::string &text, int kerning = 1) const -> int;  // Obtiene la longitud en pixels de una cadena
        [[nodiscard]] auto getCharacterSize() const -> int;                                // Devuelve el tamaño de caracter actual

        // --- Configuración ---
        void setFixedWidth(bool value);  // Establece si se usa un tamaño fijo de letra
        void setPalette(int number);     // Establece una paleta

    private:
        // --- Objetos y punteros ---
        std::unique_ptr<Sprite> sprite_ = nullptr;  // Objeto con los gráficos para el texto

        // --- Variables ---
        int box_width_ = 0;         // Anchura de la caja de cada caracter en el png
        int box_height_ = 0;        // Altura de la caja de cada caracter en el png
        bool fixed_width_ = false;  // Indica si el texto se ha de escribir con longitud fija en todas las letras
        std::array<TextOffset, 128> offset_ = {};
        ;  // Vector con las posiciones y ancho de cada letra
};