import React, { useState } from 'react';
import { useEffect } from 'react';
import { useSpring, animated } from 'react-spring';

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 = {},
  width,
  left,
  height,
  top
}: {
  children: React.ReactElement;
  config?: {
    type?: TransitionType;
    direction?: Direction;
    duration?: number;
    delay?: number;
    timingFunction?: string;
    opacityOpen?: boolean;
  };
  width: number;
  height: number;
  left: number;
  top: number;
}) {
  const { type = 'none', direction = 'left', duration = 300, delay = 0, timingFunction = 'linear', opacityOpen = false } = config;
  const [mounted, setMounted] = useState(false);
  const [screenWidth, setScreenWidth] = useState(1920);
  const [screenHeight, setScreenHeight] = useState(1080);

  useEffect(() => {
    let screenDom = document.getElementById('bigscreen-container');
    if (screenDom) {
      setScreenWidth(parseInt(screenDom.style.width));
      setScreenHeight(parseInt(screenDom.style.height));
    }
  }, []);
  const options: any = getTransitionOptions({
    type,
    direction,
    width,
    height,
    left,
    top,
    screenWidth,
    screenHeight
  });

  if (opacityOpen) {
    options.from.opacity = 0;
    options.to.opacity = 1;
  }

  const styles = useSpring({
    ...options,
    delay,
    config: {
      duration
    },
    onRest: () => {
      setMounted(true);
    }
  });

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

  return <animated.div style={mounted ? {} : styles}>{children}</animated.div>;
}

type Direction = 'left' | 'right' | 'up' | 'down' | 'leftUp' | 'leftDown' | 'rightUp' | 'rightDown';
type TransitionType = 'none' | 'slide' | 'slideSmall' | 'wipe';

function getTransitionOptions({
  type,
  direction,
  width,
  height,
  top,
  left,
  screenWidth,
  screenHeight
}: {
  type: TransitionType;
  direction: Direction;
  width: number;
  height: number;
  top: number;
  left: number;
  screenWidth: number;
  screenHeight: number;
}) {
  switch (type) {
    case 'slide':
    case 'slideSmall': {
      let result = {
        from: {
          x: 0,
          y: 0
        },
        to: {
          y: 0,
          x: 0
        }
      };

      switch (direction) {
        case 'left':
          result.from.x = -(left + width);
          break;
        case 'right': {
          result.from.x = screenWidth - left;
          break;
        }
        case 'up': {
          result.from.y = screenHeight - top;
          break;
        }
        case 'down': {
          result.from.y = -(top + height);
          break;
        }
        case 'leftDown': {
          result.from.x = -(left + width);
          result.from.y = -(top + height);
          break;
        }
        case 'leftUp': {
          result.from.x = -(left + width);
          result.from.y = screenHeight - top;
          break;
        }
        case 'rightDown': {
          result.from.x = screenWidth - left;
          result.from.y = -(top + height);
          break;
        }
        case 'rightUp': {
          result.from.x = screenWidth - left;
          result.from.y = screenHeight - top;
          break;
        }
        default:
          break;
      }
      return result;
    }
    case 'wipe': {
      let result = {
        from: {
          clipPath: `polygon(0 0, ${width}px 0, ${width}px ${height}px, 0 ${height}px)`
        },
        to: {
          clipPath: `polygon(0 0, ${width}px 0, ${width}px ${height}px, 0 ${height}px)`
        }
      };

      switch (direction) {
        case 'left':
          result.from.clipPath = `polygon(0 0, 0 0, 0 ${height}px, 0 ${height}px)`;
          break;
        default:
          break;
      }

      return result;
    }
    case 'none': {
      return {};
    }
    default:
      break;
  }
}
