"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.default = void 0;
var THREE = _interopRequireWildcard(require("three"));
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
const FRAMERATE = 60;
const FRAME_DURATION = 1000 / FRAMERATE;

// player statut
const PLAYER_STATE = {
  // player is stopped
  STOP: 0,
  // player plays animation
  PLAY: 1,
  // player is at the end of an animation
  END: 2,
  // player is paused
  PAUSE: 3
};

// Private functions
// stop timer and re-init parameter
const resetTimer = function (player) {
  if (player.id) {
    clearInterval(player.id);
    player.id = undefined;
  }
  if (player.waitTimer) {
    clearInterval(player.waitTimer);
    player.waitTimer = undefined;
  }
  player.keyframe = 0;
};

// finish animation and re-init parameter
const finishAnimation = function (player) {
  resetTimer(player);
  if (player.isEnded()) {
    player.dispatchEvent({
      type: 'animation-ended'
    });
  }
  player.dispatchEvent({
    type: 'animation-stopped'
  });
  player.duration = 0;
};

/**
 * It can play, pause or stop Animation or AnimationExpression (See below).
 * AnimationPlayer is needed to use Animation or AnimationExpression
 * AnimationPlayer emits events :
 *       - for each animation's frame;
 *       - when Animation is stopped
 *       - when Animation is ending
 */
class AnimationPlayer extends THREE.EventDispatcher {
  constructor() {
    super();
    this.id = null;
    this.keyframe = 0;
    this.duration = 0;
    this.state = PLAYER_STATE.STOP;
    this.waitTimer = null;
    this.callback = () => {};
  }
  isPlaying() {
    return this.state === PLAYER_STATE.PLAY;
  }
  isStopped() {
    return this.state === PLAYER_STATE.STOP;
  }
  isEnded() {
    return this.state === PLAYER_STATE.END;
  }

  // Public functions

  /**
   * Set the Player `callback` property. This callback is executed at each animation frame.
   *
   * @param {function} callback - The callback to execute at each animation frame.
   */
  setCallback(callback) {
    this.callback = callback;
  }

  /**
   * Play one animation.
   * If another animation is playing, it's stopped and the new animation is played.
   *
   * @param {number} duration - The duration to play
   */
  play(duration) {
    this.duration = duration;
    this.dispatchEvent({
      type: 'animation-started'
    });
    this.state = PLAYER_STATE.PLAY;
    resetTimer(this);
    this.id = setInterval(this.frame.bind(this), FRAME_DURATION);
  }

  /**
   * Play an animation after a number of frames.
   *
   * @param      {number}  duration    The duration to play
   * @param      {number}  waitingFrame    The waiting time before start animation (time in frame)
   */
  playLater(duration, waitingFrame) {
    const timew = Math.floor(FRAME_DURATION * waitingFrame);
    window.clearInterval(this.waitTimer);
    const self = this;
    this.waitTimer = window.setTimeout(() => {
      self.play(duration);
    }, timew);
  }

  /**
   * Stop the current animation.
   *
   */
  stop() {
    this.state = PLAYER_STATE.STOP;
    finishAnimation(this);
  }

  /**
   * Executed for each frame.
   *
   * @private
   */
  frame() {
    if (this.keyframe < this.duration) {
      this.keyframe++;
      this.dispatchEvent({
        type: 'animation-frame'
      });
      this.callback();
    } else {
      this.state = PLAYER_STATE.END;
      finishAnimation(this);
    }
  }
}
var _default = AnimationPlayer;
exports.default = _default;