import React, { useContext, useRef, useState } from 'react';
import { LoadingContext } from './Context';

const animateName = {
  slide: {
    left: 'slideInLeft',
    right: 'slideInRight',
    down: 'slideInDown',
    up: 'slideInUp',
    leftUp: 'slideInLeftUp',
    leftDown: 'slideInLeftDown',
    rightUp: 'slideInRightUp',
    rightDown: 'slideInRightDown'
  },
  slideSmall: {
    left: 'slideInLeftSmall',
    right: 'slideInRightSmall',
    down: 'slideInDownSmall',
    up: 'slideInUpSmall',
    leftUp: 'slideInLeftUpSmall',
    leftDown: 'slideInLeftDownSmall',
    rightUp: 'slideInRightUpSmall',
    rightDown: 'slideInRightDownSmall'
  },
  wipe: {
    left: 'wipeInLeft',
    right: 'wipeInRight',
    down: 'wipeInDown',
    up: 'wipeInUp',
    leftUp: 'wipeInLeftUp',
    leftDown: 'wipeInLeftDown',
    rightUp: 'wipeInRightUp',
    rightDown: 'wipeInRightDown'
  }
};

export default function Transition({
  children,
  config = {}
}: {
  children: React.ReactElement;
  config?: {
    type?: string;
    direction?: string;
    duration?: number;
    delay?: number;
    timingFunction?: string;
    opacityOpen?: boolean;
  };
}) {
  const { type = 'none', direction = 'left', duration = 300, delay = 0, timingFunction = 'linear', opacityOpen = false } = config;

  const finish = useContext(LoadingContext);
  const [animationEnd, setAnimationEnd] = useState(false);
  const containerRef = useRef(null);

  if (finish == null || type === 'none') {
    return children;
  }

  const handleAnimationEnd = (e) => {
    if (e.target === containerRef.current) {
      // 延迟设置动画结束，存在渲染误差，立即设置会出现动画结束的生硬
      setTimeout(() => {
        setAnimationEnd(true);
      }, 1500);
    }
  };

  const animateClassName = finish
    ? animationEnd
      ? ''
      : `animated ${animateName[type][direction]} ${opacityOpen ? 'opacityIn' : ''}`
    : 'hidden';

  return (
    <div
      ref={containerRef}
      className={animateClassName}
      style={{ animationDuration: `${duration}ms`, animationDelay: `${delay}ms`, animationTimingFunction: timingFunction }}
      onAnimationEnd={handleAnimationEnd}
    >
      {children}
    </div>
  );
}
