// @flow weak

import { now as timeNow } from 'd3-timer';
import once from 'lodash/once';
import tween from './tween';
import schedule from './schedule';
import { newId, easeCubicInOut } from './helpers';

const preset = {
  time: null,
  delay: 0,
  duration: 250,
  ease: easeCubicInOut,
};

export default function transition(config) {
  const transitions = { ...config };

  if (!this || !this.isReactComponent) {
    throw new Error('transitions must be run against a React Component');
  }

  const events = transitions.events || {};
  delete transitions.events;

  // each event handler should be called only once
  Object.keys(events).forEach((d) => {
    events[d] = once(events[d]);
  });

  const timing = transitions.timing || {};
  delete transitions.timing;

  Object.keys(transitions).forEach((stateKey) => {
    const tweens = [];

    Object.keys(transitions[stateKey]).forEach((attr) => {
      const val = transitions[stateKey][attr];

      if (Array.isArray(val)) {
        if (val.length === 1) {
          tweens.push(tween.call(this, stateKey, attr, val[0]));
        } else {
          this.setState((state) => {
            return { [stateKey]: { ...state[stateKey], [attr]: val[0] } };
          });

          tweens.push(tween.call(this, stateKey, attr, val[1]));
        }
      } else {
        this.setState((state) => {
          return { [stateKey]: { ...state[stateKey], [attr]: val } };
        });
        // This assures any existing transitions are stopped
        tweens.push(tween.call(this, stateKey, attr, val));
      }
    });

    const timingConfig = { ...preset, ...timing, time: timeNow() };
    schedule(this, stateKey, newId(), timingConfig, tweens, events);
  });
}

@@ -1292,24 +1292,279 @@
 ;%0A        %7D%0A
+      %7D else if (typeof val === 'function') %7B%0A        const customTween = (t) =%3E %7B%0A          this.setState((state) =%3E %7B%0A            return %7B %5BstateKey%5D: %7B ...state%5BstateKey%5D, %5Battr%5D: val(t) %7D %7D;%0A          %7D);%0A        %7D;%0A%0A        tweens.push(customTween);%0A
       %7D else

allow using custom tween functions