/*
 * Copyright (C) 2006-2026 Metallizer, Solarus - http://www.solarus-games.org
 *
 * Solarus is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Solarus is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program. If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef SOLARUS_AUDIO_CONTEXT_H
#define SOLARUS_AUDIO_CONTEXT_H

#include "solarus/core/Common.h"
#include "solarus/audio/AudioEffect.h"
#include "solarus/audio/AudioFilter.h"
#include "solarus/audio/effects/ChorusAudioEffect.h"
#include "solarus/audio/effects/EchoAudioEffect.h"
#include "solarus/audio/effects/FlangerAudioEffect.h"
#include "solarus/audio/effects/ReverbAudioEffect.h"
#include "solarus/audio/filters/HighPassAudioFilter.h"
#include "solarus/audio/filters/LowPassAudioFilter.h"
#include "solarus/audio/MusicPtr.h"
#include "solarus/audio/SoundPtr.h"
#include <list>
#include <map>

namespace Solarus {

class SOLARUS_API AudioContext {
  public:
    /**
     * \brief Types of audio contexts
     */
    enum Identifier {
      MAIN,
      GAME,
      MAP,
    };

    AudioContext();
    AudioContext(Identifier identifier);
    ~AudioContext();

    static void initialize();
    static void quit();
    static bool is_initialized();
    static void update_all();
    static std::shared_ptr<AudioContext> get_context(const Identifier& identifier);

    static void notify_map_finished();
    static void notify_game_finished();
    static void notify_suspended(bool is_suspended);
    static void notify_device_disconnected_to_all_contexts();
    static void notify_device_reconnected_to_all_contexts();

    void update();

    const Identifier& get_identifier() const;

    // Sounds
    void play_sound(SoundPtr sound);
    void stop_sound(SoundPtr sound);
    void stop_all_sounds();

    // Musics
    MusicPtr get_common_music() const;
    void play_common_music(MusicPtr music);
    void play_music(MusicPtr music);
    void stop_common_music();
    void stop_music(MusicPtr music);
    void stop_all_musics();
    void set_pause_to_all_musics(bool is_paused);

    // Effects
    bool is_effect_enabled(AudioEffectId id) const;
    void add_reverb_effect(ReverbPreset preset);
    void add_chorus_effect(ChorusPreset preset);
    void add_echo_effect(EchoPreset preset);
    void add_flanger_effect(FlangerPreset preset);
    void set_reverb_preset(ReverbPreset preset);
    void set_chorus_preset(ChorusPreset preset);
    void set_echo_preset(EchoPreset preset);
    void set_flanger_preset(FlangerPreset preset);
    void add_low_pass_filter(float gain, float gainhf);
    void set_low_pass_params(float gain, float gainhf);
    void add_high_pass_filter(float gain, float gainlf);
    void set_high_pass_params(float gain, float gainlf);
    void remove_effect(AudioEffectId id);
    void remove_all_effects();

    // Events
    void notify_music_global_volume_changed();
    void notify_sound_global_volume_changed();
    void notify_device_disconnected();
    void notify_device_reconnected();

  private:
    void update_sounds();
    void update_musics();

    static std::map<AudioContext::Identifier, std::shared_ptr<AudioContext>> audio_contexts;

    Identifier identifier;                          /**< Identifier for this context. */
    std::list<SoundPtr> current_sounds;             /**< The sounds currently playing. */

    MusicPtr current_common_music;                  /**< Music currently playing from sol.audio api */
    std::list<MusicPtr> current_musics;             /**< The musics currently playing from sol.music.api */

    std::map<AudioEffectId, std::shared_ptr<AudioEffect>> effects;  /**< Effects currently bound to the context. */
    std::map<AudioEffectId, std::shared_ptr<AudioFilter>> filters;  /**< Filters currently bound to the context. */
};

} // namespace Solarus

#endif
