#include <frostbite2D/audio/audio_system.h>
#include <SDL2/SDL.h>
#include <SDL2/SDL_mixer.h>
#include <algorithm>

namespace frostbite2D {

AudioSystem& AudioSystem::get() {
  static AudioSystem instance;
  return instance;
}

// 移除析构函数中的自动销毁，改为在 Application::shutdown() 中手动调用

bool AudioSystem::init(const AudioConfig& config) {
  if (initialized_) {
    return true;
  }

  if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) {
    SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to initialize SDL audio: %s", SDL_GetError());
    return false;
  }

  int frequency = config.frequency;
  uint16_t format = config.format;
  int channels = config.channels;

  if (Mix_OpenAudio(frequency, format, channels, config.chunksize) < 0) {
    if (Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, config.chunksize) < 0) {
      SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to open audio: %s", Mix_GetError());
      SDL_QuitSubSystem(SDL_INIT_AUDIO);
      return false;
    }
  }

  maxChannels_ = config.maxSoundChannels;
  Mix_AllocateChannels(maxChannels_);

  initialized_ = true;
  updateVolumes();

  return true;
}

void AudioSystem::shutdown() {
  if (!initialized_) {
    return;
  }

  Mix_HaltMusic();
  Mix_HaltChannel(-1);
  Mix_CloseAudio();
  SDL_QuitSubSystem(SDL_INIT_AUDIO);

  initialized_ = false;
}

void AudioSystem::setMasterVolume(float volume) {
  masterVolume_ = std::clamp(volume, 0.0f, 1.0f);
  updateVolumes();
}

float AudioSystem::getMasterVolume() const {
  return masterVolume_;
}

void AudioSystem::setSoundVolume(float volume) {
  soundVolume_ = std::clamp(volume, 0.0f, 1.0f);
  updateVolumes();
}

float AudioSystem::getSoundVolume() const {
  return soundVolume_;
}

void AudioSystem::setMusicVolume(float volume) {
  musicVolume_ = std::clamp(volume, 0.0f, 1.0f);
  updateVolumes();
}

float AudioSystem::getMusicVolume() const {
  return musicVolume_;
}

void AudioSystem::updateVolumes() {
  if (!initialized_) {
    return;
  }

  int musicVol = static_cast<int>(musicVolume_ * masterVolume_ * MIX_MAX_VOLUME);
  Mix_VolumeMusic(musicVol);
}

void AudioSystem::pauseAllSounds() {
  if (!initialized_) {
    return;
  }
  Mix_Pause(-1);
}

void AudioSystem::resumeAllSounds() {
  if (!initialized_) {
    return;
  }
  Mix_Resume(-1);
}

void AudioSystem::stopAllSounds() {
  if (!initialized_) {
    return;
  }
  Mix_HaltChannel(-1);
}

}
