import EventEmitter from '../core/eventemitter';

/**
 * Animator.
 */
export default class Animator extends EventEmitter {
  from: any;
  to: any;
  value: any;
  duration: number;
  interval: any;
  easing: Function;

  constructor(from, to) {
    super();
    this.from = from || 0;
    this.to = to || 1;
    this.duration = 1000;
    this.interval = null;
    this.value = this.from;
    this.easing = null;
  }

  setEasing(easing : Function) {
    this.easing = easing;
    return this;
  }

  set(from, to) {
    if (this.interval)
      this.cancel();
    this.from = from;
    this.to = to;
    this.value = this.from;
    return this;
  }

  /**
   * Start animator
   */
  start() {
    let self = this;
    if (self.interval)
      self.cancel();
    let startTs = new Date().getTime();
    let value, spend;
    self.interval = setInterval(function() {
      spend = new Date().getTime() - startTs;
      if (spend > self.duration) {
        self.value = self.to;
        self.cancel();
      } else {
        self.updateValues(spend / self.duration);
      }
      self.trigger('animationUpdate', self.value);
    }, 1000 / 60); // 60 frames per second.
    return self;
  }

  updateValues(progress) {
    // progress = Easing.easeOutBounce(progress);
    // progress = Easing.easeInOutQuad(progress);
    // progress = Easing.easeInOutQuadBack(progress);
    // progress = Easing.easeInOutQuadBack2(progress);
    // progress = Easing.overshoot(progress);
    // progress = Easing.easeInQuad(progress);
    // progress = Easing.easeInCubic(progress);
    // progress = Easing.easeInQuart(progress);

    if (this.easing) {
      progress = this.easing.call(null, progress);
    }

    let self = this;
    //console.log('self.from:', self.from, 'self.to:', self.to);

    if (self.from.length) {
      self.value = [];
      for (var i = 0; i < self.from.length; i++) {
        self.value[i] = self.from[i] + (self.to[i] - self.from[i]) * progress;
      }
    } else {
      self.value = self.from + (self.to - self.from) * progress;
    }
  }

  /**
   * Cancel the animator
   */
  cancel() {
    if (this.interval) {
      clearInterval(this.interval);
      this.interval = null;
    }
    return self;
  }

  /**
   * Set animation duration
   */
  setDuration(duration) {
    this.duration = duration;
    return this;
  }

  getValue() { return this.value; }

  /**
   * Check animator is running or not
   */
  isRunning() { return this.interval != null; }
}
