#pragma once

#include <SDL3/SDL_events.h>  // for SDL_Event
#include <SDL3/SDL_render.h>  // for SDL_Renderer
#include <SDL3/SDL_stdinc.h>  // for Uint64
#include <SDL3/SDL_video.h>   // for SDL_Window

#include <array>   // for array
#include <memory>  // for unique_ptr, shared_ptr
#include <string>  // for string
#include <vector>  // for vector

#include "ball.h"              // for Ball
#include "defines.h"           // for GravityDirection, ColorTheme, ShapeType
#include "external/texture.h"  // for Texture
#include "shapes/shape.h"      // for Shape (interfaz polimórfica)

// Modos de aplicación mutuamente excluyentes
enum class AppMode {
    MANUAL,      // Control manual del usuario
    DEMO,        // Modo demo completo (auto-play)
    DEMO_LITE,   // Modo demo lite (solo física/figuras)
    LOGO         // Modo logo (easter egg)
};

class Engine {
    public:
        // Interfaz pública
        bool initialize(int width = 0, int height = 0, int zoom = 0, bool fullscreen = false);
        void run();
        void shutdown();

    private:
        // Recursos SDL
        SDL_Window* window_ = nullptr;
        SDL_Renderer* renderer_ = nullptr;
        std::shared_ptr<Texture> texture_ = nullptr;      // Textura activa actual
        std::vector<std::shared_ptr<Texture>> textures_;  // Todas las texturas disponibles
        std::vector<std::string> texture_names_;          // Nombres de texturas (sin extensión)
        size_t current_texture_index_ = 0;                // Índice de textura activa
        int current_ball_size_ = 10;                      // Tamaño actual de pelotas (dinámico, se actualiza desde texture)

        // Estado del simulador
        std::vector<std::unique_ptr<Ball>> balls_;
        GravityDirection current_gravity_ = GravityDirection::DOWN;
        int scenario_ = 0;
        bool should_exit_ = false;

        // Sistema de timing
        Uint64 last_frame_time_ = 0;
        float delta_time_ = 0.0f;

        // UI y debug
        bool show_debug_ = false;
        bool show_text_ = true;

        // Sistema de zoom dinámico
        int current_window_zoom_ = DEFAULT_WINDOW_ZOOM;
        std::string text_;
        int text_pos_ = 0;
        Uint64 text_init_time_ = 0;

        // FPS y V-Sync
        Uint64 fps_last_time_ = 0;
        int fps_frame_count_ = 0;
        int fps_current_ = 0;
        std::string fps_text_ = "FPS: 0";
        bool vsync_enabled_ = true;
        std::string vsync_text_ = "VSYNC ON";
        bool fullscreen_enabled_ = false;
        bool real_fullscreen_enabled_ = false;
        ScalingMode current_scaling_mode_ = ScalingMode::INTEGER;  // Modo de escalado actual (F5)

        // Resolución base (configurada por CLI o default)
        int base_screen_width_ = DEFAULT_SCREEN_WIDTH;
        int base_screen_height_ = DEFAULT_SCREEN_HEIGHT;

        // Resolución dinámica actual (cambia en fullscreen real)
        int current_screen_width_ = DEFAULT_SCREEN_WIDTH;
        int current_screen_height_ = DEFAULT_SCREEN_HEIGHT;

        // Sistema de temas
        ColorTheme current_theme_ = ColorTheme::SUNSET;
        ColorTheme target_theme_ = ColorTheme::SUNSET;  // Tema destino para transición
        bool transitioning_ = false;                    // ¿Estamos en transición?
        float transition_progress_ = 0.0f;              // Progreso de 0.0 a 1.0
        float transition_duration_ = 0.5f;              // Duración en segundos

        // Estructura de tema de colores
        struct ThemeColors {
                const char* name_en;                           // Nombre en inglés (para debug)
                const char* name_es;                           // Nombre en español (para display)
                int text_color_r, text_color_g, text_color_b;  // Color del texto del tema
                float bg_top_r, bg_top_g, bg_top_b;
                float bg_bottom_r, bg_bottom_g, bg_bottom_b;
                std::vector<Color> ball_colors;
        };

        // Temas de colores definidos
        ThemeColors themes_[7];  // 7 temas: SUNSET, OCEAN, NEON, FOREST, RGB, MONOCHROME, LAVENDER

        // Sistema de Temas Dinámicos (animados)
        DynamicTheme dynamic_themes_[3];         // 3 temas dinámicos predefinidos
        bool dynamic_theme_active_ = false;      // ¿Tema dinámico activo?
        int current_dynamic_theme_index_ = -1;   // Índice del tema dinámico actual (-1 = ninguno)
        size_t current_keyframe_index_ = 0;      // Keyframe actual
        size_t target_keyframe_index_ = 1;       // Próximo keyframe
        float dynamic_transition_progress_ = 0.0f;  // Progreso 0.0-1.0 hacia próximo keyframe
        bool dynamic_theme_paused_ = false;      // Pausa manual con Shift+D

        // Sistema de Figuras 3D (polimórfico)
        SimulationMode current_mode_ = SimulationMode::PHYSICS;
        ShapeType current_shape_type_ = ShapeType::SPHERE;  // Tipo de figura actual
        ShapeType last_shape_type_ = ShapeType::SPHERE;     // Última figura para toggle F
        std::unique_ptr<Shape> active_shape_;               // Puntero polimórfico a figura activa
        float shape_scale_factor_ = 1.0f;                   // Factor de escala manual (Numpad +/-)
        bool depth_zoom_enabled_ = true;                    // Zoom por profundidad Z activado

        // Sistema de Modo DEMO (auto-play)
        AppMode current_app_mode_ = AppMode::MANUAL;  // Modo actual (mutuamente excluyente)
        AppMode previous_app_mode_ = AppMode::MANUAL; // Modo previo antes de entrar a LOGO
        float demo_timer_ = 0.0f;                     // Contador de tiempo para próxima acción
        float demo_next_action_time_ = 0.0f;          // Tiempo aleatorio hasta próxima acción (segundos)

        // Sistema de convergencia para LOGO MODE (escala con resolución)
        float shape_convergence_ = 0.0f;              // % de pelotas cerca del objetivo (0.0-1.0)
        float logo_convergence_threshold_ = 0.90f;    // Threshold aleatorio (75-100%)
        float logo_min_time_ = 3.0f;                  // Tiempo mínimo escalado con resolución
        float logo_max_time_ = 5.0f;                  // Tiempo máximo escalado (backup)

        // Estado previo antes de entrar a Logo Mode (para restaurar al salir)
        ColorTheme logo_previous_theme_ = ColorTheme::SUNSET;
        size_t logo_previous_texture_index_ = 0;
        float logo_previous_shape_scale_ = 1.0f;

        // Batch rendering
        std::vector<SDL_Vertex> batch_vertices_;
        std::vector<int> batch_indices_;

        // Métodos principales del loop
        void calculateDeltaTime();
        void update();
        void handleEvents();
        void render();

        // Métodos auxiliares
        void initBalls(int value);
        void setText();
        void pushBallsAwayFromGravity();
        void switchBallsGravity();
        void enableBallsGravityIfDisabled();
        void forceBallsGravityOn();
        void forceBallsGravityOff();
        void changeGravityDirection(GravityDirection direction);
        void toggleVSync();
        void toggleFullscreen();
        void toggleRealFullscreen();
        void toggleIntegerScaling();
        std::string gravityDirectionToString(GravityDirection direction) const;
        void initializeThemes();

        // Sistema de Temas Dinámicos
        void initializeDynamicThemes();                     // Inicializar 3 temas dinámicos predefinidos
        void updateDynamicTheme();                          // Actualizar animación de tema dinámico (llamado cada frame)
        void activateDynamicTheme(int index);               // Activar tema dinámico (0-2)
        void pauseDynamicTheme();                           // Toggle pausa de animación (Shift+D)

        // Sistema de gestión de estados (MANUAL/DEMO/DEMO_LITE/LOGO)
        void setState(AppMode new_mode);                // Cambiar modo de aplicación (mutuamente excluyente)

        // Sistema de Modo DEMO
        void updateDemoMode();
        void performDemoAction(bool is_lite);
        void randomizeOnDemoStart(bool is_lite);
        void toggleGravityOnOff();

        // Sistema de Modo Logo (easter egg)
        void toggleLogoMode();                     // Activar/desactivar modo logo manual (tecla K)
        void enterLogoMode(bool from_demo = false); // Entrar al modo logo (manual o automático)
        void exitLogoMode(bool return_to_demo = false); // Salir del modo logo

        // Sistema de transiciones LERP
        float lerp(float a, float b, float t) const { return a + (b - a) * t; }
        Color getInterpolatedColor(size_t ball_index) const;  // Obtener color interpolado durante transición
        void startThemeTransition(ColorTheme new_theme);

        // Sistema de cambio de sprites dinámico
        void switchTexture();                              // Cambia a siguiente textura disponible
        void updateBallSizes(int old_size, int new_size);  // Ajusta posiciones al cambiar tamaño

        // Sistema de zoom dinámico
        int calculateMaxWindowZoom() const;
        void setWindowZoom(int new_zoom);
        void zoomIn();
        void zoomOut();

        // Rendering
        void renderGradientBackground();
        void addSpriteToBatch(float x, float y, float w, float h, int r, int g, int b, float scale = 1.0f);

        // Sistema de Figuras 3D
        void toggleShapeMode(bool force_gravity_on_exit = true);  // Toggle PHYSICS ↔ última figura (tecla F)
        void activateShape(ShapeType type);                       // Activar figura específica (teclas Q/W/E/R/Y/U/I)
        void updateShape();                                       // Actualizar figura activa
        void generateShape();                                     // Generar puntos de figura activa
        void clampShapeScale();                                   // Limitar escala para evitar clipping
};
