#pragma once

#include <SDL3/SDL.h>

#include <algorithm>
#include <string>  // Para string, basic_string
#include <utility>

#include "core/rendering/screen.hpp"  // Para Screen::Filter
#include "game/defaults.hpp"
#include "utils/defines.hpp"  // Para WINDOW_CAPTION
#include "utils/utils.hpp"    // Para Color, Palette

// --- Namespace Options: gestión de configuración y opciones del juego ---
namespace Options {

// Estructura para las opciones de control de teclado
struct KeyboardControls {
        SDL_Scancode key_left{Defaults::Controls::KEY_LEFT};    // Tecla para mover a la izquierda
        SDL_Scancode key_right{Defaults::Controls::KEY_RIGHT};  // Tecla para mover a la derecha
        SDL_Scancode key_jump{Defaults::Controls::KEY_JUMP};    // Tecla para saltar
};

// Estructura para las opciones de control del gamepad/joystick
// Los valores pueden ser:
// - 0-20+: Botones SDL_GamepadButton (DPAD, face buttons, shoulders, etc.)
// - 100: L2 trigger
// - 101: R2 trigger
// - 200: Left stick X axis (negativo = izquierda)
// - 201: Left stick X axis (positivo = derecha)
struct GamepadControls {
        int button_left{Defaults::Controls::GAMEPAD_BUTTON_LEFT};    // Botón para mover a la izquierda (por defecto: DPAD_LEFT)
        int button_right{Defaults::Controls::GAMEPAD_BUTTON_RIGHT};  // Botón para mover a la derecha (por defecto: DPAD_RIGHT)
        int button_jump{Defaults::Controls::GAMEPAD_BUTTON_JUMP};    // Botón para saltar (por defecto: WEST/X button)
};

// Estructura para albergar trucos
struct Cheat {
        enum class State : bool {
            DISABLED = false,
            ENABLED = true
        };

        State infinite_lives{Defaults::Cheat::INFINITE_LIVES ? State::ENABLED : State::DISABLED};  // Indica si el jugador dispone de vidas infinitas
        State invincible{Defaults::Cheat::INVINCIBLE ? State::ENABLED : State::DISABLED};          // Indica si el jugador puede morir
        State jail_is_open{Defaults::Cheat::JAIL_IS_OPEN ? State::ENABLED : State::DISABLED};      // Indica si la Jail está abierta
        State alternate_skin{Defaults::Cheat::ALTERNATE_SKIN ? State::ENABLED : State::DISABLED};  // Indica si se usa una skin diferente para el jugador

        // Método para comprobar si alguno de los tres primeros trucos está activo
        [[nodiscard]] auto enabled() const -> bool {
            return infinite_lives == State::ENABLED ||
                invincible == State::ENABLED ||
                jail_is_open == State::ENABLED;
        }
};

// Estructura para almacenar estadísticas
struct Stats {
        int rooms{Defaults::Stats::ROOMS};                              // Cantidad de habitaciones visitadas
        int items{Defaults::Stats::ITEMS};                              // Cantidad de items obtenidos
        std::string worst_nightmare{Defaults::Stats::WORST_NIGHTMARE};  // Habitación con más muertes acumuladas
};

// Estructura con opciones de la ventana
struct Window {
        std::string caption{Texts::WINDOW_CAPTION};  // Texto que aparece en la barra de título de la ventana
        int zoom{Defaults::Window::ZOOM};         // Zoom de la ventana
        int max_zoom{Defaults::Window::ZOOM};     // Máximo tamaño de zoom para la ventana
};

// Estructura para gestionar el borde de la pantalla
struct Border {
        bool enabled{Defaults::Border::ENABLED};  // Indica si se ha de mostrar el borde
        float width{Defaults::Border::WIDTH};     // Ancho del borde
        float height{Defaults::Border::HEIGHT};   // Alto del borde
};

// Estructura para las opciones de video
struct Video {
        bool fullscreen{Defaults::Video::FULLSCREEN};        // Contiene el valor del modo de pantalla completa
        Screen::Filter filter{Defaults::Video::FILTER};      // Filtro usado para el escalado de la imagen
        bool vertical_sync{Defaults::Video::VERTICAL_SYNC};  // Indica si se quiere usar vsync o no
        bool shaders{Defaults::Video::SHADERS};              // Indica si se van a usar shaders o no
        bool integer_scale{Defaults::Video::INTEGER_SCALE};  // Indica si el escalado de la imagen ha de ser entero en el modo a pantalla completa
        bool keep_aspect{Defaults::Video::KEEP_ASPECT};      // Indica si se ha de mantener la relación de aspecto al poner el modo a pantalla completa
        Border border{};                                        // Borde de la pantalla
        std::string palette{Defaults::Video::PALETTE_NAME};        // Paleta de colores a usar en el juego
        std::string info;                                       // Información sobre el modo de vídeo
};

// Estructura para las opciones de musica
struct Music {
        bool enabled{Defaults::Music::ENABLED};  // Indica si la música suena o no
        float volume{Defaults::Music::VOLUME};   // Volumen al que suena la música
};

// Estructura para las opciones de sonido
struct Sound {
        bool enabled{Defaults::Sound::ENABLED};  // Indica si los sonidos suenan o no
        float volume{Defaults::Sound::VOLUME};   // Volumen al que suenan los sonidos (0 a 128 internamente)
};

// Estructura para las opciones de audio
struct Audio {
        Music music{};                              // Opciones para la música
        Sound sound{};                              // Opciones para los efectos de sonido
        bool enabled{Defaults::Audio::ENABLED};  // Indica si el audio está activo o no
        float volume{Defaults::Audio::VOLUME};   // Volumen al que suenan el audio (0-128 internamente)
};

// Estructura para las opciones de juego
struct Game {
        float width{Defaults::Canvas::WIDTH};    // Ancho de la resolucion del juego
        float height{Defaults::Canvas::HEIGHT};  // Alto de la resolucion del juego
};

// --- Variables globales (inline C++17+) ---
inline std::string version{};                 // Versión del fichero de configuración. Sirve para saber si las opciones son compatibles
inline bool console{false};                   // Indica si ha de mostrar información por la consola de texto
inline Cheat cheats{};                        // Contiene trucos y ventajas para el juego
inline Game game{};                           // Opciones de juego
inline Video video{};                         // Opciones de video
inline Stats stats{};                         // Datos con las estadisticas de juego
inline Window window{};                       // Opciones relativas a la ventana
inline Audio audio{};                         // Opciones relativas al audio
inline KeyboardControls keyboard_controls{};  // Teclas usadas para jugar
inline GamepadControls gamepad_controls{};    // Botones del gamepad usados para jugar

// Ruta completa del fichero de configuración (establecida mediante setConfigFile)
inline std::string config_file_path{};

// --- Funciones públicas ---
void init();                                  // Crea e inicializa las opciones del programa
void setConfigFile(const std::string& path);  // Establece la ruta del fichero de configuración
auto loadFromFile() -> bool;                  // Carga las opciones desde el fichero configurado
auto saveToFile() -> bool;                    // Guarda las opciones al fichero configurado

}  // namespace Options