part of sprites;

// TODO: The sound effects should probably use Android's SoundPool instead of
// MediaPlayer as it is more efficient and flexible for playing back sound effects

typedef void SoundEffectStreamCallback(SoundEffectStream);

class SoundEffect {
  SoundEffect(this._pipeFuture);

  // TODO: Remove load method from SoundEffect
  Future load() async {
    _data = await _pipeFuture;
  }

  Future<MojoDataPipeConsumer> _pipeFuture;
  MojoDataPipeConsumer _data;
}

class SoundEffectStream {
  SoundEffectStream(
    this.sound,
    this.loop,
    this.volume,
    this.pitch,
    this.pan,
    this.onSoundComplete
  );

  // TODO: Make these properties work
  SoundEffect sound;
  bool playing = false;
  bool loop = false;
  double volume = 1.0;
  double pitch = 1.0;
  double pan = 0.0;

  // TODO: Implement completion callback. On completion, sounds should
  // also be removed from the list of playing sounds.
  SoundEffectStreamCallback onSoundComplete;

  MediaPlayerProxy _player;
}

SoundEffectPlayer _sharedSoundEffectPlayer;

class SoundEffectPlayer {

  static SoundEffectPlayer sharedInstance() {
    if (_sharedSoundEffectPlayer == null) {
      _sharedSoundEffectPlayer = new SoundEffectPlayer();
    }
    return _sharedSoundEffectPlayer;
  }

  SoundEffectPlayer() {
    _mediaService = new MediaServiceProxy.unbound();
    shell.requestService(null, _mediaService);
  }

  MediaServiceProxy _mediaService;
  List<SoundEffectStream> _soundEffectStreams = [];

  // TODO: This should no longer be needed when moving to SoundPool backing
  Map<SoundEffect,MediaPlayerProxy> _mediaPlayers = {};

  Future _prepare(SoundEffectStream playingSound) async {
    await playingSound._player.ptr.prepare(playingSound.sound._data);
  }

  // TODO: Move sound loading here
  // TODO: Support loading sounds from bundles
  // Future<SoundEffect> load(url) async {
  //   ...
  // }

  // TODO: Add sound unloader
  // unload(SoundEffect effect) {
  //   ...
  // }

  // TODO: Add paused property (should pause playback of all sounds)
  bool paused;

  SoundEffectStream play(
    SoundEffect sound,
    [bool loop = false,
      double volume = 1.0,
      double pitch = 1.0,
      double pan = 0.0,
      SoundEffectStreamCallback callback = null]) {

    // Create new PlayingSound object
    SoundEffectStream playingSound = new SoundEffectStream(
      sound,
      loop,
      volume,
      pitch,
      pan,
      callback
    );

    // TODO: Replace this with calls to SoundPool
    if (_mediaPlayers[sound] == null) {
      // Create player
      playingSound._player = new MediaPlayerProxy.unbound();
      _mediaService.ptr.createPlayer(playingSound._player);

      // Prepare sound, then play it
      _prepare(playingSound).then((_) {
        playingSound._player.ptr.seekTo(0);
        playingSound._player.ptr.start();
      });

      _soundEffectStreams.add(playingSound);
      _mediaPlayers[sound] = playingSound._player;
    } else {
      // Reuse player
      playingSound._player = _mediaPlayers[sound];
      playingSound._player.ptr.seekTo(0);
      playingSound._player.ptr.start();
    }

    return playingSound;
  }

  void stop(SoundEffectStream stream) {
    stream._player.ptr.pause();
    _soundEffectStreams.remove(stream);
  }

  void stopAll() {
    for (SoundEffectStream playingSound in _soundEffectStreams) {
      playingSound._player.ptr.pause();
    }
    _soundEffectStreams = [];
  }
}

typedef void SoundTrackCallback(SoundTrack);
typedef void SoundTrackBufferingCallback(SoundTrack, int);

class SoundTrack {
  MediaPlayerProxy _player;

  SoundTrackCallback onSoundComplete;
  SoundTrackCallback onSeekComplete;
  SoundTrackBufferingCallback onBufferingUpdate;
  bool loop;
  double time;
  double volume;
}

SoundTrackPlayer _sharedSoundTrackPlayer;

class SoundTrackPlayer {
  List<SoundTrack> _soundTracks = [];

  static sharedInstance() {
    if (_sharedSoundTrackPlayer == null) {
      _sharedSoundTrackPlayer = new SoundTrackPlayer();
    }
    return _sharedSoundTrackPlayer;
  }

  SoundTrackPlayer() {
    _mediaService = new MediaServiceProxy.unbound();
    shell.requestService(null, _mediaService);
  }

  MediaServiceProxy _mediaService;

  Future<SoundTrack> load(Future<MojoDataPipeConsumer> pipe) async {
    // Create media player
    SoundTrack soundTrack = new SoundTrack();
    soundTrack._player = new MediaPlayerProxy.unbound();
    _mediaService.ptr.createPlayer(soundTrack._player);

    await soundTrack._player.ptr.prepare(await pipe);
    return soundTrack;
  }

  void unload(SoundTrack soundTrack) {
    stop(soundTrack);
    _soundTracks.remove(soundTrack);
  }

  void play(
    SoundTrack soundTrack,
    [bool loop = false,
      double volume,
      double startTime = 0.0]) {
    // TODO: Implement looping & volume
    // soundTrack._player.ptr.setLooping(loop);
    // soundTrack._player.ptr.setVolume(volume);
    soundTrack._player.ptr.seekTo((startTime * 1000.0).toInt());
    soundTrack._player.ptr.start();
  }

  void stop(SoundTrack track) {
    track._player.ptr.pause();
  }

  void stopAll() {
    for (SoundTrack soundTrack in _soundTracks) {
      soundTrack._player.ptr.pause();
    }
  }
}
