import Transition from './transition';
const EPSILON = 1e-5;

function updateSpringElement(prev, cur, dest, damping, stiffness) {
  const velocity = cur - prev;
  const delta = dest - cur;
  const spring = delta * stiffness;
  const damper = -velocity * damping;
  return spring + damper + velocity + cur;
}

function updateSpring(prev, cur, dest, damping, stiffness) {
  if (Array.isArray(dest)) {
    const next = [];

    for (let i = 0; i < dest.length; i++) {
      next[i] = updateSpringElement(prev[i], cur[i], dest[i], damping, stiffness);
    }

    return next;
  }

  return updateSpringElement(prev, cur, dest, damping, stiffness);
}

function distance(value1, value2) {
  if (Array.isArray(value1)) {
    let distanceSquare = 0;

    for (let i = 0; i < value1.length; i++) {
      const d = value1[i] - value2[i];
      distanceSquare += d * d;
    }

    return Math.sqrt(distanceSquare);
  }

  return Math.abs(value1 - value2);
}

export default class CPUSpringTransition extends Transition {
  constructor(...args) {
    super(...args);
    this._prevValue = void 0;
    this._currValue = void 0;
  }

  get value() {
    return this._currValue;
  }

  _onUpdate() {
    const {
      fromValue,
      toValue,
      damping,
      stiffness
    } = this.settings;
    const {
      _prevValue = fromValue,
      _currValue = fromValue
    } = this;
    let nextValue = updateSpring(_prevValue, _currValue, toValue, damping, stiffness);
    const delta = distance(nextValue, toValue);
    const velocity = distance(nextValue, _currValue);

    if (delta < EPSILON && velocity < EPSILON) {
      nextValue = toValue;
      this.end();
    }

    this._prevValue = _currValue;
    this._currValue = nextValue;
  }

}
//# sourceMappingURL=cpu-spring-transition.js.map