/*
 * 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/>.
 */

#include "solarus/audio/ALWrapper.h"
#include "solarus/audio/effects/ReverbAudioEffect.h"
#include "solarus/core/Debug.h"
#include "solarus/core/Logger.h"

namespace Solarus
{

const std::string EnumInfoTraits<ReverbPreset>::pretty_name = "reverb_effect_preset";

const EnumInfo<ReverbPreset>::names_type EnumInfoTraits<ReverbPreset>::names = {
  { ReverbPreset::ARENA, "arena" },
  { ReverbPreset::AUDITORIUM, "auditorium" },
  { ReverbPreset::BATHROOM, "bathroom" },
  { ReverbPreset::CAVE, "cave" },
  { ReverbPreset::CHAPEL, "chapel" },
  { ReverbPreset::CITY, "city" },
  { ReverbPreset::FOREST, "forest" },
  { ReverbPreset::HALLWAY, "hallway" },
  { ReverbPreset::HANGAR, "hangar" },
  { ReverbPreset::ICEPALACE, "icepalace" },
  { ReverbPreset::MOUNTAINS, "mountains" },
  { ReverbPreset::QUARRY, "quarry" },
  { ReverbPreset::SEWERPIPE, "sewerpipe" },
  { ReverbPreset::SMALLWATERROOM, "smallwaterroom" },
}; 

/**
 * \brief Default constructor.
 */
ReverbAudioEffect::ReverbAudioEffect(): AudioEffect(AudioEffectId::REVERB) {
  
}

ReverbAudioEffect::ReverbAudioEffect(ReverbPreset preset): AudioEffect(AudioEffectId::REVERB) {
  ALWrapper::generate_effect(1, &effect, "create_reverb_effect");

  switch (preset) {
    case ReverbPreset::ARENA: init_props(EFX_REVERB_PRESET_ARENA); break;
    case ReverbPreset::AUDITORIUM: init_props(EFX_REVERB_PRESET_AUDITORIUM); break;
    case ReverbPreset::BATHROOM: init_props(EFX_REVERB_PRESET_BATHROOM); break;
    case ReverbPreset::CAVE: init_props(EFX_REVERB_PRESET_CAVE); break;
    case ReverbPreset::CHAPEL: init_props(EFX_REVERB_PRESET_CHAPEL); break;
    case ReverbPreset::CITY: init_props(EFX_REVERB_PRESET_CITY); break;
    case ReverbPreset::FOREST: init_props(EFX_REVERB_PRESET_FOREST); break;
    case ReverbPreset::HALLWAY: init_props(EFX_REVERB_PRESET_HALLWAY); break;
    case ReverbPreset::HANGAR: init_props(EFX_REVERB_PRESET_HANGAR); break;
    case ReverbPreset::ICEPALACE: init_props(EFX_REVERB_PRESET_ICEPALACE_MEDIUMROOM); break;
    case ReverbPreset::MOUNTAINS: init_props(EFX_REVERB_PRESET_MOUNTAINS); break;
    case ReverbPreset::QUARRY: init_props(EFX_REVERB_PRESET_QUARRY); break;
    case ReverbPreset::SEWERPIPE: init_props(EFX_REVERB_PRESET_SEWERPIPE); break;
    case ReverbPreset::SMALLWATERROOM: init_props(EFX_REVERB_PRESET_SMALLWATERROOM); break;
    default: init_props(EFX_REVERB_PRESET_GENERIC); break;
  }

  AudioEffect::create_slot();
}

void ReverbAudioEffect::set_preset(ReverbPreset preset) {
  switch (preset) {
    case ReverbPreset::ARENA: init_props(EFX_REVERB_PRESET_ARENA); break;
    case ReverbPreset::AUDITORIUM: init_props(EFX_REVERB_PRESET_AUDITORIUM); break;
    case ReverbPreset::BATHROOM: init_props(EFX_REVERB_PRESET_BATHROOM); break;
    case ReverbPreset::CAVE: init_props(EFX_REVERB_PRESET_CAVE); break;
    case ReverbPreset::CHAPEL: init_props(EFX_REVERB_PRESET_CHAPEL); break;
    case ReverbPreset::CITY: init_props(EFX_REVERB_PRESET_CITY); break;
    case ReverbPreset::FOREST: init_props(EFX_REVERB_PRESET_FOREST); break;
    case ReverbPreset::HALLWAY: init_props(EFX_REVERB_PRESET_HALLWAY); break;
    case ReverbPreset::HANGAR: init_props(EFX_REVERB_PRESET_HANGAR); break;
    case ReverbPreset::ICEPALACE: init_props(EFX_REVERB_PRESET_ICEPALACE_MEDIUMROOM); break;
    case ReverbPreset::MOUNTAINS: init_props(EFX_REVERB_PRESET_MOUNTAINS); break;
    case ReverbPreset::QUARRY: init_props(EFX_REVERB_PRESET_QUARRY); break;
    case ReverbPreset::SEWERPIPE: init_props(EFX_REVERB_PRESET_SEWERPIPE); break;
    case ReverbPreset::SMALLWATERROOM: init_props(EFX_REVERB_PRESET_SMALLWATERROOM); break;
    default: init_props(EFX_REVERB_PRESET_GENERIC); break;
  }
  ALWrapper::set_effect_slot_int(auxiliary_slot, AL_EFFECTSLOT_EFFECT, static_cast<ALint>(effect), "set_reverb_preset");
}

void ReverbAudioEffect::init_props(EFXEAXREVERBPROPERTIES props) {
  ALWrapper::set_effect_int(effect, AL_EFFECT_TYPE, AL_EFFECT_REVERB, "create_reverb_effect");
  ALWrapper::set_effect_float(effect, AL_REVERB_DENSITY, props.flDensity, "create_reverb_effect");
  ALWrapper::set_effect_float(effect, AL_REVERB_DIFFUSION, props.flDiffusion, "create_reverb_effect");
  ALWrapper::set_effect_float(effect, AL_REVERB_GAIN, props.flGain, "create_reverb_effect");
  ALWrapper::set_effect_float(effect, AL_REVERB_GAINHF, props.flGainHF, "create_reverb_effect");
  ALWrapper::set_effect_float(effect, AL_REVERB_DECAY_TIME, props.flDecayTime, "create_reverb_effect");
  ALWrapper::set_effect_float(effect, AL_REVERB_DECAY_HFRATIO, props.flDecayHFRatio, "create_reverb_effect");
  ALWrapper::set_effect_float(effect, AL_REVERB_REFLECTIONS_GAIN, props.flReflectionsGain, "create_reverb_effect");
  ALWrapper::set_effect_float(effect, AL_REVERB_REFLECTIONS_DELAY, props.flReflectionsDelay, "create_reverb_effect");
  ALWrapper::set_effect_float(effect, AL_REVERB_LATE_REVERB_GAIN, props.flLateReverbGain, "create_reverb_effect");
  ALWrapper::set_effect_float(effect, AL_REVERB_LATE_REVERB_DELAY, props.flLateReverbDelay, "create_reverb_effect");
  ALWrapper::set_effect_float(effect, AL_REVERB_AIR_ABSORPTION_GAINHF, props.flAirAbsorptionGainHF, "create_reverb_effect");
  ALWrapper::set_effect_float(effect, AL_REVERB_ROOM_ROLLOFF_FACTOR, props.flRoomRolloffFactor, "create_reverb_effect");
  ALWrapper::set_effect_int(effect, AL_REVERB_DECAY_HFLIMIT, props.iDecayHFLimit, "create_reverb_effect");
}

} // namespace Solarus
