import { useEffect, useRef, useState } from 'react';
import useDataAnimationContext from './context/useDataAnimationContext';

/**
 * A hook for animating data changes that takes a changing trigger value
 * and returns a ref and a changing display value. Attaching the ref to an element
 * will animate it in and out with a flip and fade when the trigger changes. The display value
 * is always updated to change to whatever the trigger is, and can be optionally used for a nicer
 * fade out when the element animates.
 *
 * This hook also provides a context in which you can wrap higher-level components.
 * You can turn animations off conditionally by passing a "shouldAnimate" value to the context.
 */

const useAnimateDataChange = ({
  trigger
}) => {
  const animationRef = useRef();
  const {
    shouldAnimate
  } = useDataAnimationContext();
  const [displayValue, setDisplayValue] = useState(trigger);

  // Animate out when the trigger changes, then set a new value to display
  useEffect(() => {
    if (!animationRef.current) return;
    if (!shouldAnimate) {
      // Change display val, but don't animate

      setDisplayValue(trigger);
      return;
    }
    const timing = [{
      opacity: 1,
      transform: 'rotateX(0deg)'
    }, {
      opacity: 0,
      transform: 'rotateX(90deg)'
    }];
    const fadeOut = animationRef.current.animate(timing, {
      duration: 150,
      fill: 'forwards'
    });
    fadeOut.onfinish = () => {
      if (!animationRef.current) return;
      fadeOut.commitStyles();
      setDisplayValue(trigger);
      fadeOut.cancel();
    };
  }, [trigger]);

  // Animate in when we change the display value
  useEffect(() => {
    if (!animationRef.current) return;
    if (!shouldAnimate) return;
    const timing = [{
      opacity: 0,
      transform: 'rotateX(90deg)'
    }, {
      opacity: 1,
      transform: 'rotateX(0deg)'
    }];
    const fadeIn = animationRef.current.animate(timing, {
      duration: 250,
      fill: 'forwards'
    });
    fadeIn.onfinish = () => {
      if (!animationRef.current) return;
      fadeIn.commitStyles();
      fadeIn.cancel();
    };
  }, [displayValue]);
  return [animationRef, displayValue];
};
export default useAnimateDataChange;