import React, { useEffect, useState } from "react";
import PropTypes from "prop-types";
import styled from "styled-components";
import variant from "@styled-system/variant";

import * as CONSTANTS from "./constants";

const defaultStyles = () => {
  return {
    ...CONSTANTS.DEFAULT_TRANSITION,
  };
};

const EntryVariants = variant({
  prop: "entry",
  scale: "entryStyles",
  variants: {},
});

const ExitVariants = variant({
  prop: "exit",
  scale: "exitStyles",
  variants: {},
});

const ActiveVariant = variant({
  prop: "active",
  scale: "activeStyle",
});

const AnimateWrapper = styled.div`
  ${defaultStyles}
  ${props => {
    const { active, triggerExit } = props;
    if (active) return ActiveVariant(props);
    if (triggerExit) return ExitVariants(props);
    return EntryVariants(props);
  }}
`;

const Animate = props => {
  const { active } = props;
  const [wrapperActive, setWrapperActive] = useState(false);
  const [wrapperUnmount, setWrapperUnmount] = useState(false);

  useEffect(() => {
    if (props.active) setWrapperUnmount(false);
    setTimeout(() => {
      setWrapperActive(props.active);
    }, CONSTANTS.TIMEOUTS.TRANSITION);
  }, [props]);

  const transitionEnd = () => {
    if (!wrapperActive) {
      setTimeout(() => {
        setWrapperUnmount(true);
      }, CONSTANTS.TIMEOUTS.UNMOUNT);
    }
  };

  return !wrapperUnmount ? (
    <AnimateWrapper
      // eslint-disable-next-line react/jsx-props-no-spreading
      {...props}
      active={wrapperActive}
      onTransitionEnd={transitionEnd}
      triggerExit={!active}
    />
  ) : null;
};

Animate.defaultProps = {
  active: true,
  entry: "fade",
  exit: "fade",
  style: {},
};

Animate.propTypes = {
  /** Determines if element is visible */
  active: PropTypes.bool,

  /** Name of entry animation */
  entry: PropTypes.string,

  /** Name of exit animation */
  exit: PropTypes.string,

  /** Pass custom styles (if applicable) */
  style: PropTypes.shape({}),
};

export default Animate;
