/*
 * GDevelop C++ Platform
 * Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
 * reserved. This project is released under the MIT License.
 */
#include "AudioTools.h"
#include <string>
#include "GDCpp/Runtime/RuntimeGame.h"
#include "GDCpp/Runtime/RuntimeScene.h"
#include "GDCpp/Runtime/SoundManager.h"
#undef PlaySound  // Avoid a nasty macro from polluting everything

/**
 * Test if a music is played
 */
bool GD_API MusicPlaying(RuntimeScene& scene, unsigned int channel) {
  if (scene.game->GetSoundManager().GetMusicOnChannel(channel) ==
      std::shared_ptr<Music>())
    return false;

  return (
      scene.game->GetSoundManager().GetMusicOnChannel(channel)->GetStatus() ==
      sf::Music::Playing);
}

/**
 * Test if a music is paused
 */
bool GD_API MusicPaused(RuntimeScene& scene, unsigned int channel) {
  if (scene.game->GetSoundManager().GetMusicOnChannel(channel) ==
      std::shared_ptr<Music>())
    return false;

  return (
      scene.game->GetSoundManager().GetMusicOnChannel(channel)->GetStatus() ==
      sf::Music::Paused);
}

/**
 * Test if a music is stopped
 */
bool GD_API MusicStopped(RuntimeScene& scene, unsigned int channel) {
  if (scene.game->GetSoundManager().GetMusicOnChannel(channel) ==
      std::shared_ptr<Music>())
    return false;

  return (
      scene.game->GetSoundManager().GetMusicOnChannel(channel)->GetStatus() ==
      sf::Music::Stopped);
}

/**
 * Test if a sound is stopped
 */
bool GD_API SoundPlaying(RuntimeScene& scene, unsigned int channel) {
  if (scene.game->GetSoundManager().GetSoundOnChannel(channel) ==
      std::shared_ptr<Sound>())
    return false;

  return (
      scene.game->GetSoundManager().GetSoundOnChannel(channel)->GetStatus() ==
      sf::Sound::Playing);
}

/**
 * Test if a sound is stopped
 */
bool GD_API SoundPaused(RuntimeScene& scene, unsigned int channel) {
  if (scene.game->GetSoundManager().GetSoundOnChannel(channel) ==
      std::shared_ptr<Sound>())
    return false;

  return (
      scene.game->GetSoundManager().GetSoundOnChannel(channel)->GetStatus() ==
      sf::Sound::Paused);
}

/**
 * Test if a sound is stopped
 */
bool GD_API SoundStopped(RuntimeScene& scene, unsigned int channel) {
  if (scene.game->GetSoundManager().GetSoundOnChannel(channel) ==
      std::shared_ptr<Sound>())
    return false;

  return (
      scene.game->GetSoundManager().GetSoundOnChannel(channel)->GetStatus() ==
      sf::Sound::Stopped);
}

void GD_API PlaySoundOnChannel(RuntimeScene& scene,
                               const gd::String& file,
                               unsigned int channel,
                               bool repeat,
                               float volume,
                               float pitch) {
  sf::Clock latency;

  scene.game->GetSoundManager().PlaySoundOnChannel(
      file, channel, repeat, volume, pitch);

  scene.GetTimeManager().NotifyPauseWasMade(
      latency.getElapsedTime().asMicroseconds());
}

void GD_API PlaySound(RuntimeScene& scene,
                      const gd::String& file,
                      bool repeat,
                      float volume,
                      float pitch) {
  sf::Clock latency;

  scene.game->GetSoundManager().PlaySound(file, repeat, volume, pitch);

  scene.GetTimeManager().NotifyPauseWasMade(
      latency.getElapsedTime().asMicroseconds());
}

void GD_API StopSoundOnChannel(RuntimeScene& scene, unsigned int channel) {
  if (scene.game->GetSoundManager().GetSoundOnChannel(channel) ==
      std::shared_ptr<Sound>())
    return;

  scene.game->GetSoundManager().GetSoundOnChannel(channel)->sound.stop();
}

void GD_API PauseSoundOnChannel(RuntimeScene& scene, unsigned int channel) {
  if (scene.game->GetSoundManager().GetSoundOnChannel(channel) ==
      std::shared_ptr<Sound>())
    return;

  scene.game->GetSoundManager().GetSoundOnChannel(channel)->sound.pause();
}

void GD_API RePlaySoundOnChannel(RuntimeScene& scene, unsigned int channel) {
  if (scene.game->GetSoundManager().GetSoundOnChannel(channel) ==
      std::shared_ptr<Sound>())
    return;

  scene.game->GetSoundManager().GetSoundOnChannel(channel)->sound.play();
}

void GD_API PlayMusic(RuntimeScene& scene,
                      const gd::String& file,
                      bool repeat,
                      float volume,
                      float pitch) {
  scene.game->GetSoundManager().PlayMusic(file, repeat, volume, pitch);
}

void GD_API PlayMusicOnChannel(RuntimeScene& scene,
                               const gd::String& file,
                               unsigned int channel,
                               bool repeat,
                               float volume,
                               float pitch) {
  scene.game->GetSoundManager().PlayMusicOnChannel(
      file, channel, repeat, volume, pitch);
}

void GD_API StopMusicOnChannel(RuntimeScene& scene, unsigned int channel) {
  if (scene.game->GetSoundManager().GetMusicOnChannel(channel) ==
      std::shared_ptr<Music>())
    return;

  scene.game->GetSoundManager().GetMusicOnChannel(channel)->Stop();
}

void GD_API PauseMusicOnChannel(RuntimeScene& scene, unsigned int channel) {
  if (scene.game->GetSoundManager().GetMusicOnChannel(channel) ==
      std::shared_ptr<Music>())
    return;

  scene.game->GetSoundManager().GetMusicOnChannel(channel)->Pause();
}

void GD_API RePlayMusicOnChannel(RuntimeScene& scene, unsigned int channel) {
  if (scene.game->GetSoundManager().GetMusicOnChannel(channel) ==
      std::shared_ptr<Music>())
    return;

  scene.game->GetSoundManager().GetMusicOnChannel(channel)->Play();
}

void GD_API SetSoundVolumeOnChannel(RuntimeScene& scene,
                                    unsigned int channel,
                                    float volume) {
  if (scene.game->GetSoundManager().GetSoundOnChannel(channel) ==
      std::shared_ptr<Sound>())
    return;

  scene.game->GetSoundManager().GetSoundOnChannel(channel)->SetVolume(
      volume, scene.game->GetSoundManager().GetGlobalVolume());
}

void GD_API SetMusicVolumeOnChannel(RuntimeScene& scene,
                                    unsigned int channel,
                                    float volume) {
  if (scene.game->GetSoundManager().GetMusicOnChannel(channel) ==
      std::shared_ptr<Music>())
    return;

  scene.game->GetSoundManager().GetMusicOnChannel(channel)->SetVolume(
      volume, scene.game->GetSoundManager().GetGlobalVolume());
}

double GD_API GetSoundVolumeOnChannel(RuntimeScene& scene,
                                      unsigned int channel) {
  if (scene.game->GetSoundManager().GetSoundOnChannel(channel) ==
      std::shared_ptr<Sound>())
    return 0;

  return scene.game->GetSoundManager().GetSoundOnChannel(channel)->GetVolume();
}

double GD_API GetMusicVolumeOnChannel(RuntimeScene& scene,
                                      unsigned int channel) {
  if (scene.game->GetSoundManager().GetMusicOnChannel(channel) ==
      std::shared_ptr<Music>())
    return 0;

  return scene.game->GetSoundManager().GetMusicOnChannel(channel)->GetVolume();
}

void GD_API SetGlobalVolume(RuntimeScene& scene, float volume) {
  scene.game->GetSoundManager().SetGlobalVolume(volume);
}

double GD_API GetGlobalVolume(RuntimeScene& scene) {
  return scene.game->GetSoundManager().GetGlobalVolume();
}

void GD_API SetSoundPitchOnChannel(RuntimeScene& scene,
                                   unsigned int channel,
                                   float pitch) {
  if (scene.game->GetSoundManager().GetSoundOnChannel(channel) ==
      std::shared_ptr<Sound>())
    return;

  scene.game->GetSoundManager().GetSoundOnChannel(channel)->SetPitch(pitch);
}

void GD_API SetMusicPitchOnChannel(RuntimeScene& scene,
                                   unsigned int channel,
                                   float pitch) {
  if (scene.game->GetSoundManager().GetMusicOnChannel(channel) ==
      std::shared_ptr<Music>())
    return;

  scene.game->GetSoundManager().GetMusicOnChannel(channel)->SetPitch(pitch);
}

double GD_API GetSoundPitchOnChannel(RuntimeScene& scene,
                                     unsigned int channel) {
  if (scene.game->GetSoundManager().GetSoundOnChannel(channel) ==
      std::shared_ptr<Sound>())
    return 0;

  return scene.game->GetSoundManager().GetSoundOnChannel(channel)->GetPitch();
}

double GD_API GetMusicPitchOnChannel(RuntimeScene& scene,
                                     unsigned int channel) {
  if (scene.game->GetSoundManager().GetMusicOnChannel(channel) ==
      std::shared_ptr<Music>())
    return 0;

  return scene.game->GetSoundManager().GetMusicOnChannel(channel)->GetPitch();
}

void GD_API SetSoundPlayingOffsetOnChannel(RuntimeScene& scene,
                                           unsigned int channel,
                                           float playingOffset) {
  if (scene.game->GetSoundManager().GetSoundOnChannel(channel) ==
      std::shared_ptr<Sound>())
    return;

  scene.game->GetSoundManager().GetSoundOnChannel(channel)->SetPlayingOffset(
      playingOffset);
}

void GD_API SetMusicPlayingOffsetOnChannel(RuntimeScene& scene,
                                           unsigned int channel,
                                           float playingOffset) {
  if (scene.game->GetSoundManager().GetMusicOnChannel(channel) ==
      std::shared_ptr<Music>())
    return;

  scene.game->GetSoundManager().GetMusicOnChannel(channel)->SetPlayingOffset(
      playingOffset);
}

double GD_API GetSoundPlayingOffsetOnChannel(RuntimeScene& scene,
                                             unsigned int channel) {
  if (scene.game->GetSoundManager().GetSoundOnChannel(channel) ==
      std::shared_ptr<Sound>())
    return 0;

  return static_cast<double>(scene.game->GetSoundManager()
                                 .GetSoundOnChannel(channel)
                                 ->GetPlayingOffset());
}

double GD_API GetMusicPlayingOffsetOnChannel(RuntimeScene& scene,
                                             unsigned int channel) {
  if (scene.game->GetSoundManager().GetMusicOnChannel(channel) ==
      std::shared_ptr<Music>())
    return 0;

  return static_cast<double>(scene.game->GetSoundManager()
                                 .GetMusicOnChannel(channel)
                                 ->GetPlayingOffset());
}
