#pragma once

#include <string>   // Para string
#include <utility>  // Para move

// Clase Audio: gestor de audio (singleton)
class Audio {
    public:
        enum class Group : int {
            ALL = -1,
            GAME = 0,
            INTERFACE = 1
        };

        // --- Constantes ---
        static constexpr int MAX_VOLUME = 100;
        static constexpr int MIN_VOLUME = 0;
        static constexpr int FREQUENCY = 48000;

        // --- Métodos de singleton ---
        static void init();                                 // Inicializa el objeto Audio
        static void destroy();                              // Libera el objeto Audio
        static auto get() -> Audio *;                       // Obtiene el puntero al objeto Audio
        Audio(const Audio &) = delete;                      // Evitar copia
        auto operator=(const Audio &) -> Audio & = delete;  // Evitar asignación

        // --- Control de Música ---
        void playMusic(const std::string &name, int loop = -1);  // Reproducir música en bucle
        void pauseMusic();                                       // Pausar reproducción de música
        void stopMusic();                                        // Detener completamente la música
        void fadeOutMusic(int milliseconds) const;               // Fundido de salida de la música

        // --- Control de Sonidos ---
        void playSound(const std::string &name, Group group = Group::GAME) const;  // Reproducir sonido puntual
        void stopAllSounds() const;                                                // Detener todos los sonidos

        // --- Configuración General ---
        void enable(bool value);                        // Establecer estado general
        void toggleEnabled() { enabled_ = !enabled_; }  // Alternar estado general
        void applySettings();                           // Aplica la configuración

        // --- Configuración de Sonidos ---
        void enableSound() { sound_enabled_ = true; }             // Habilitar sonidos
        void disableSound() { sound_enabled_ = false; }           // Deshabilitar sonidos
        void enableSound(bool value) { sound_enabled_ = value; }  // Establecer estado de sonidos
        void toggleSound() { sound_enabled_ = !sound_enabled_; }  // Alternar estado de sonidos

        // --- Configuración de Música ---
        void enableMusic() { music_enabled_ = true; }             // Habilitar música
        void disableMusic() { music_enabled_ = false; }           // Deshabilitar música
        void enableMusic(bool value) { music_enabled_ = value; }  // Establecer estado de música
        void toggleMusic() { music_enabled_ = !music_enabled_; }  // Alternar estado de música

        // --- Control de Volumen ---
        void setSoundVolume(int volume, Group group = Group::ALL) const;  // Ajustar volumen de efectos
        void setMusicVolume(int volume) const;                            // Ajustar volumen de música

    private:
        enum class MusicState {
            PLAYING,
            PAUSED,
            STOPPED,
        };

        struct Music {
                MusicState state;  // Estado actual de la música (reproduciendo, detenido, en pausa)
                std::string name;  // Última pista de música reproducida
                bool loop;         // Indica si la última pista de música se debe reproducir en bucle

                // Constructor para inicializar la música con valores predeterminados
                Music() : state(MusicState::STOPPED), loop(false) {}

                // Constructor para inicializar con valores específicos
                Music(MusicState init_state, std::string init_name, bool init_loop)
                    : state(init_state), name(std::move(init_name)), loop(init_loop) {}
        };

        Music music_;

        // --- Variables de Estado ---
        bool enabled_ = true;        // Estado general del audio
        bool sound_enabled_ = true;  // Estado de los efectos de sonido
        bool music_enabled_ = true;  // Estado de la música

        // --- Inicializa SDL Audio ---
        void initSDLAudio();

        // --- Patrón Singleton ---
        Audio();   // Constructor privado
        ~Audio();  // Destructor privado

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