import Service from './service';
import EventsMixin from './mixin/events';

export default class SoundsService extends EventsMixin(Service) {
  constructor() {
    super();
    this.events = ['state'];

    this.sounds = {};
  }

  load(id, url) {
    if (this.sounds[id]) return;
    this._initSound(id, url);
  }

  getState(id) {
    return this.sounds[id] ? this.sounds[id].state : 'uninitialized';
  }

  togglePlay(id) {
    this._isPlaying(id) ? this.stop(id) : this.play(id);
  }

  play(id) {
    if (!this.sounds[id]) throw new Error('Sound must be loaded first');
    const sound = this.sounds[id].sound;

    window.soundManager.stopAll();
    this.sounds[id].state = 'loading';
    sound.setPosition(0).play();
  }

  stop(id) {
    if (!this.sounds[id]) throw new Error('Sound must be loaded first');
    const sound = this.sounds[id].sound;

    sound.stop();
  }

  _initSound(id, url) {
    const handler = this._onStatusChange.bind(this, id);
    const options = {
      url: url,
      volume: 100,
      onpause: handler,
      onstop: handler,
      onresume: handler,
      onfinish: handler,
      onload: handler,
      onplay: handler,
    };
    return this.sounds[id] = {
      sound: window.soundManager.createSound(options),
      state: 'paused',
    };
  }

  _onStatusChange(id) {
    const sound = this.sounds[id];

    sound.state = this._isPlaying(id)
      ? 'playing'
      : this._isLoading(id) ? 'loading' : 'paused';
    this._broadcast.state(id);
  }

  _isPlaying(id) {
    const sound = this.sounds[id].sound;

    if (!sound) return false;
    return !sound.paused && sound.playState === 1 && sound.readyState === 3;
  }

  _isLoading(id) {
    const sound = this.sounds[id].sound;

    if (!sound) return false;
    return sound.readyState === 1;
  }
}
