/*!
  \file
  \brief 効果音の再生

  \author Satofumi KAMIMURA

  $Id: SoundEffect.cpp 855 2009-05-11 11:17:45Z satofumi $
*/

#include "SoundEffect.h"
#include "Audio.h"
#include <SDL_mixer.h>
#include <map>

using namespace qrk;
using namespace std;


namespace
{
  typedef map<int, int*> Channels;
}


struct SoundEffect::pImpl
{
  static bool initialized_;
  static Channels channels_;
  Audio audio_;
  int channel_id_;
  Mix_Chunk* chunk_;


  pImpl(const char* play_file)
    : channel_id_(-1), chunk_(Mix_LoadWAV(play_file))
  {
    if (! initialized_) {
      Mix_ChannelFinished(finished);
      initialized_ = true;
    }
  }


  ~pImpl(void)
  {
    if (channel_id_ > 0) {
      finished(channel_id_);
    }
    delete chunk_;
  }


  void play(void)
  {
    channel_id_ = Mix_PlayChannel(-1, chunk_, 0);
    if (channel_id_ > 0) {
      channels_[channel_id_] = &channel_id_;
    }
  }


  bool isPlaying(void)
  {
    if (channel_id_ < 0) {
      return false;
    }

    return (Mix_Playing(channel_id_) == 0) ? false : true;
  }


  static void finished(int channel_id)
  {
    channels_.erase(channel_id);
  }
};

bool SoundEffect::pImpl::initialized_ = false;
Channels SoundEffect::pImpl::channels_;


SoundEffect::SoundEffect(const char* play_file) : pimpl(new pImpl(play_file))
{
}


SoundEffect::~SoundEffect(void)
{
}


void SoundEffect::setVolume(size_t percent)
{
  if (! pimpl->audio_.isInitialized()) {
    return;
  }
  percent = max(percent, static_cast<size_t>(100));

  static_cast<void>(percent);
  // !!!
}


// !attention x, y, z は無視される
void SoundEffect::play(float x, float y, float z )
{
  static_cast<void>(x);
  static_cast<void>(y);
  static_cast<void>(z);

  if (! pimpl->audio_.isInitialized()) {
    return;
  }

  pimpl->play();
}


// !attention x, y, z は無視される
void SoundEffect::updatePosition(float x, float y, float z)
{
  static_cast<void>(x);
  static_cast<void>(y);
  static_cast<void>(z);

  // 実装しない
}


bool SoundEffect::isPlaying(void)
{
  if (! pimpl->audio_.isInitialized()) {
    return false;
  }

  return pimpl->isPlaying();
}
