import React, { FC, useEffect, useRef, useState } from 'react'

export declare interface CollapseProps extends React.HTMLProps<HTMLDivElement> {
  isOpen: boolean
}

export const Collapse: FC<CollapseProps> = ({
  isOpen,
  className,
  style,
  ...props
}) => {
  const [height, setHeight] = useState<string>(isOpen ? 'auto' : '0')
  const [overflow, setOverflow] = useState<string>(
    isOpen ? 'visible' : 'hidden'
  )
  const [visibility, setVisibility] = useState<string>(
    isOpen ? 'visible' : 'hidden'
  )
  const content = useRef<HTMLDivElement>(null)

  useEffect(() => {
    if (content.current) {
      if (isOpen && height !== 'auto') {
        setHeight(`${content.current?.scrollHeight}px`)
        setVisibility('visible')
      } else if (!isOpen && height !== '0') {
        setHeight(`${content.current?.scrollHeight}px`)
        window.requestAnimationFrame(() =>
          setTimeout(() => {
            setHeight('0')
            setOverflow('hidden')
          })
        )
      }
    }
  }, [isOpen, height])

  const onTransitionEnd = (e: React.TransitionEvent) => {
    if (e.target === content.current && e.propertyName === 'height') {
      if (!isOpen) {
        setVisibility('hidden')
      }
    }
  }

  const styles: React.CSSProperties = {
    ...style,
    willChange: 'height',
    height,
    overflow,
    visibility: visibility === 'hidden' ? 'hidden' : 'visible',
  }

  return (
    <div
      {...props}
      style={styles}
      ref={content}
      onTransitionEnd={onTransitionEnd}
      className={`collapse-transition ${className ? className : ''}`}
    />
  )
}
