#pragma once

#include <SDL3/SDL.h>

#include <string>  // for string

#include "utils.h"  // for color_t
class Asset;
class Text;

// Tipos de filtro
constexpr int FILTER_NEAREST = 0;
constexpr int FILTER_LINEAL = 1;

class Screen {
   public:
    // Constantes
    static constexpr int WINDOW_ZOOM_MIN = 1;
    static constexpr int WINDOW_ZOOM_MAX = 4;
#ifdef __EMSCRIPTEN__
    // En WASM el tamaño de ventana está fijado a 1x, así que escalamos el
    // renderizado por 3 aprovechando el modo NEAREST de la textura del juego
    // para que los píxeles salgan nítidos.
    static constexpr int WASM_RENDER_SCALE = 3;
#endif

    // Constructor y destructor
    Screen(SDL_Window *window, SDL_Renderer *renderer, Asset *asset, options_t *options);
    ~Screen();

    // Render loop
    void clean(color_t color = {0x00, 0x00, 0x00});  // Limpia la pantalla
    void start();                                     // Prepara para empezar a dibujar en la textura de juego
    void blit();                                      // Vuelca el contenido del renderizador en pantalla

    // Video y ventana
    void setVideoMode(bool fullscreen);               // Establece el modo de video
    void toggleVideoMode();                           // Cambia entre pantalla completa y ventana
    void handleCanvasResized();                       // En Emscripten, reaplica setVideoMode tras un cambio del navegador (salida de fullscreen con Esc, rotación). No-op fuera de Emscripten
    void syncFullscreenFlagFromBrowser(bool isFullscreen);  // Sincroniza el flag interno de fullscreen con el estado real del navegador. Debe llamarse antes de diferir handleCanvasResized. No-op fuera de Emscripten
    void toggleIntegerScale();                        // Alterna el escalado entero
    void setIntegerScale(bool enabled);               // Establece el escalado entero
    void toggleVSync();                               // Alterna el V-Sync
    void setVSync(bool enabled);                      // Establece el V-Sync
    auto decWindowZoom() -> bool;                     // Reduce el zoom de la ventana (devuelve true si cambió)
    auto incWindowZoom() -> bool;                     // Aumenta el zoom de la ventana (devuelve true si cambió)
    auto setWindowZoom(int zoom) -> bool;             // Establece el zoom de la ventana (devuelve true si cambió)

    // Borde
    void setBorderColor(color_t color);  // Cambia el color del borde

    // Notificaciones
    void notify(const std::string &text, color_t textColor, color_t outlineColor, Uint32 durationMs);  // Muestra una notificación en la línea superior del canvas durante durationMs. Sobrescribe cualquier notificación activa (sin apilación).
    void clearNotification();                                                                          // Limpia la notificación actual

   private:
    // Helpers internos de setVideoMode
    void applyFullscreen(bool fullscreen);    // SDL_SetWindowFullscreen + visibilidad del cursor
    void applyWindowedLayout();               // Calcula windowWidth/Height/dest + SDL_SetWindowSize + SDL_SetWindowPosition
    void applyFullscreenLayout();             // SDL_GetWindowSize + delegación a computeFullscreenGameRect
    void computeFullscreenGameRect();         // Calcula dest en fullscreen (integerScale / keepAspect / stretched)
    void applyLogicalPresentation(bool fullscreen);  // SDL_SetRenderLogicalPresentation + persistencia a options

    // Emscripten
    void registerEmscriptenEventCallbacks();  // Registra los callbacks nativos de Emscripten para fullscreenchange y orientationchange. No-op fuera de Emscripten

    // Notificaciones
    void renderNotification();  // Dibuja la notificación activa (si la hay) sobre el gameCanvas

    // Objetos y punteros
    SDL_Window *window;       // Ventana de la aplicación
    SDL_Renderer *renderer;   // El renderizador de la ventana
    Asset *asset;             // Objeto con el listado de recursos
    SDL_Texture *gameCanvas;  // Textura para completar la ventana de juego hasta la pantalla completa
    options_t *options;       // Variable con todas las opciones del programa

    // Variables
    int windowWidth;       // Ancho de la pantalla o ventana
    int windowHeight;      // Alto de la pantalla o ventana
    int gameCanvasWidth;   // Resolución interna del juego. Es el ancho de la textura donde se dibuja el juego
    int gameCanvasHeight;  // Resolución interna del juego. Es el alto de la textura donde se dibuja el juego
    int borderWidth;       // Anchura del borde
    int borderHeight;      // Altura del borde
    SDL_Rect dest;         // Coordenadas donde se va a dibujar la textura del juego sobre la pantalla o ventana
    color_t borderColor;   // Color del borde añadido a la textura de juego para rellenar la pantalla

    // Notificaciones - una sola activa, sin apilación ni animaciones
    Text *notificationText;            // Fuente 8bithud dedicada a las notificaciones
    std::string notificationMessage;   // Texto a mostrar
    color_t notificationTextColor;     // Color del texto
    color_t notificationOutlineColor;  // Color del outline
    Uint32 notificationEndTime;        // SDL_GetTicks() hasta el cual se muestra
    int notificationY;                 // Fila vertical en el canvas virtual
};
