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._url);

  // TODO: Remove load method from SoundEffect
  Future load() async {
    UrlResponse response = await fetchUrl(_url);
    _data = response.body;
  }

  String _url;
  Object _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(String url) async {
    // Create media player
    SoundTrack soundTrack = new SoundTrack();
    soundTrack._player = new MediaPlayerProxy.unbound();
    _mediaService.ptr.createPlayer(soundTrack._player);

    // Load and prepare
    UrlResponse response = await fetchUrl(url);
    await soundTrack._player.ptr.prepare(response.body);

    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();
    }
  }
}
