#pragma once

#include <SDL3/SDL.h>  // Para SDL_FRect, SDL_Renderer

#include <memory>  // Para shared_ptr
#include <string>  // Para basic_string, string
#include <vector>  // Para vector

#include "color.h"  // Para stringInVector, Color
#include "utils.h"

class Sprite;
class Text;
class Texture;

// --- Clase Notifier: gestiona las notificaciones en pantalla (singleton) ---
class Notifier {
    public:
        // --- Métodos de singleton ---
        static void init(const std::string &icon_file, std::shared_ptr<Text> text);  // Inicializa el singleton
        static void destroy();                                                       // Libera el singleton
        static auto get() -> Notifier *;                                             // Obtiene la instancia

        // --- Métodos principales ---
        void render();  // Dibuja las notificaciones por pantalla
        void update();  // Actualiza el estado de las notificaciones

        // --- Gestión de notificaciones ---
        void show(std::vector<std::string> texts, int icon = -1, const std::string &code = std::string());  // Muestra una notificación de texto por pantalla
        [[nodiscard]] auto isActive() const -> bool { return !notifications_.empty(); }                     // Indica si hay notificaciones activas
        auto getCodes() -> std::vector<std::string>;                                                        // Obtiene los códigos de las notificaciones activas
        auto checkCode(const std::string &code) -> bool { return stringInVector(getCodes(), code); }        // Comprueba si hay alguna notificación con un código concreto

    private:
        // --- Tipos internos ---
        enum class NotificationStatus {
            RISING,
            STAY,
            VANISHING,
            FINISHED,
        };

        enum class NotificationShape {
            ROUNDED,
            SQUARED,
        };

        // --- Estructura Notification ---
        struct Notification {
                std::shared_ptr<Texture> texture;                      // Textura de la notificación
                std::shared_ptr<Sprite> sprite;                        // Sprite asociado
                std::vector<std::string> texts;                        // Textos a mostrar
                int counter{0};                                        // Contador de tiempo
                NotificationStatus state{NotificationStatus::RISING};  // Estado de la notificación
                NotificationShape shape{NotificationShape::SQUARED};   // Forma de la notificación
                SDL_FRect rect;                                        // Rectángulo de la notificación
                int y{0};                                              // Posición vertical
                int travel_dist{0};                                    // Distancia a recorrer
                std::string code;                                      // Código identificador de la notificación

                // Constructor
                explicit Notification()
                    : texture(nullptr), sprite(nullptr), rect{0, 0, 0, 0} {}
        };

        // --- Objetos y punteros ---
        SDL_Renderer *renderer_;                 // El renderizador de la ventana
        std::shared_ptr<Texture> icon_texture_;  // Textura para los iconos de las notificaciones
        std::shared_ptr<Text> text_;             // Objeto para dibujar texto

        // --- Variables de estado ---
        Color bg_color_;                           // Color de fondo de las notificaciones
        int wait_time_;                            // Tiempo que se ve la notificación
        std::vector<Notification> notifications_;  // Lista de notificaciones activas
        bool stack_;                               // Indica si las notificaciones se apilan
        bool has_icons_;                           // Indica si el notificador tiene textura para iconos

        // --- Métodos internos ---
        void clearFinishedNotifications();                                                  // Elimina las notificaciones cuyo estado es FINISHED
        void clearAllNotifications();                                                       // Elimina todas las notificaciones activas, sin importar el estado
        [[nodiscard]] auto shouldProcessNotification(int index) const -> bool;              // Determina si una notificación debe ser procesada (según su estado y posición)
        void processNotification(int index);                                                // Procesa una notificación en la posición dada: actualiza su estado y comportamiento visual
        static void playNotificationSoundIfNeeded(const Notification &notification);        // Reproduce sonido asociado si es necesario (dependiendo del estado o contenido)
        void updateNotificationState(int index);                                            // Actualiza el estado interno de una notificación (ej. de RISING a STAY)
        void handleRisingState(int index);                                                  // Lógica de animación para el estado RISING (apareciendo)
        void handleStayState(int index);                                                    // Lógica para mantener una notificación visible en el estado STAY
        void handleVanishingState(int index);                                               // Lógica de animación para el estado VANISHING (desapareciendo)
        static void moveNotificationVertically(Notification &notification, int direction);  // Mueve verticalmente una notificación en una dirección dada (útil para animación en apilamiento)
        void transitionToStayState(int index);                                              // Cambia el estado de una notificación de RISING a STAY cuando ha alcanzado su posición final

        // --- Constructor y destructor ---
        Notifier(std::string icon_file, std::shared_ptr<Text> text);  // Constructor privado
        ~Notifier() = default;                                        // Destructor privado

        // --- Singleton ---
        static Notifier *instance;
};