#pragma once

#include <SDL3/SDL.h>

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

#include "core/rendering/surface_sprite.hpp"  // Para SSprite
class Surface;                                // lines 8-8

constexpr int TEXT_COLOR = 1;
constexpr int TEXT_SHADOW = 2;
constexpr int TEXT_CENTER = 4;
constexpr int TEXT_STROKE = 8;

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
        TextOffset offset[128];  // Vector con las posiciones y ancho de cada letra
};

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

// Clase texto. Pinta texto en pantalla a partir de un bitmap
class Text {
    private:
        // Objetos y punteros
        std::unique_ptr<SurfaceSprite> sprite_ = nullptr;  // Objeto con los graficos 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
        TextOffset offset_[128] = {};  // Vector con las posiciones y ancho de cada letra

    public:
        // Constructor
        Text(const std::shared_ptr<Surface>& surface, const std::string& text_file);
        Text(const std::shared_ptr<Surface>& surface, const std::shared_ptr<TextFile>& text_file);

        // Destructor
        ~Text() = default;

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

        // Escribe el texto en una textura
        auto writeToSurface(const std::string& text, int zoom = 1, int kerning = 1) -> std::shared_ptr<Surface>;

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

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

        // Escribe el texto con sombra
        void writeShadowed(int x, int y, const std::string& text, Uint8 color, Uint8 shadow_distance = 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, Uint8 text_color = Uint8(), Uint8 shadow_distance = 1, Uint8 shadow_color = Uint8(), int lenght = -1);

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

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

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