import React, { useState, useEffect, useRef } from 'react'
import { Item } from './components/Item'
import { AnimationController } from './components/animation'

interface AnimationType {
  mode?: 'fade' | 'slideLeft' | 'slideRight'
  duration?: number
  speed?: number
}

const stages = {
  idle: 'idle',
  prepared: 'prepared',
  animating: 'animating'
}

interface Props {
  items: React.ReactElement[],
  animation: AnimationType,
  animate: boolean
  containerRows: number
  containerColumns: number
  containerRowsGap: number
  containerColumnsGap: number
}

export const ItemsContainer: React.FunctionComponent<Props> = ({ items, animation, animate, containerRows, containerColumns, containerRowsGap, containerColumnsGap }) => {
  const container = useRef<HTMLDivElement>(null)
  const [animations] = useState(() => new AnimationController)
  const [birthdayItems, setBirthdayItems] = useState<React.ReactElement[]>([])
  const [lastIndex, setLastIndex] = useState(0)
  const [show, setShow] = useState(false)
  const [stage, setStage] = useState(stages.idle)

  useEffect(() => {
    configure()
  }, [animation])

  useEffect(() => {
    if (null !== container.current && stage === stages.animating) {
      animations.animate(container.current.childNodes, () => createItems())
    }
  }, [stage])

  useEffect(() => {
    if (animate && stage === stages.prepared) setStage(stages.animating)
  }, [birthdayItems, animate])

  const configure = () => {
    animations.configure({
      mode: animation.mode,
      duration: animation.duration,
      speed: animation.speed
    })
    if (animate && stage === stages.idle) createItems()
  }

  const updateIndex = (newIndex: number) => {
    if (newIndex >= items.length) {
      setLastIndex(0)
    } else {
      setLastIndex(newIndex)
    }
  }

  const createItems = () => {

    const remainingItems = items.length - lastIndex
    const itemsToShow = Math.min(containerRows * containerColumns, remainingItems)

    const newItems = items.slice(lastIndex, lastIndex + itemsToShow).map(
      (item: React.ReactElement, index: number, arr: React.ReactElement[]) => (
        <Item
          key={lastIndex + index + 1}
          containerData={{
            ic_index: index,
            ic_rowIndex: index / containerColumns,
            ic_columnIndex: index % containerColumns,
            ic_firstChild: index === 0,
            ic_lastChild: index === (arr.length - 1)
          }}
          style={animations.getInitialStyle()}
          width={`${(100 - ((containerColumnsGap * (containerColumns - 1)))) / containerColumns}%`}
          height={`${(100 - ((containerRowsGap * (containerRows - 1)))) / containerRows}%`}
          horizontalGap={containerColumnsGap}
          verticalGap={containerRowsGap}>
          {item}
        </Item>
      ))

    if (newItems.length > 0) {
      setShow(true)
      setStage(stages.prepared)
      setBirthdayItems(newItems)
    } else {
      setShow(false)
      setStage(stages.idle)
    }

    updateIndex(lastIndex + newItems.length)
  }

  return (
    <div
      ref={container}
      style={{
        opacity: show ? 1 : 0,
        position: 'relative',
        height: '100%',
        width: '100%',
        display: 'flex',
        flexWrap: 'wrap',
        alignContent: 'flex-start'
      }}
    >
      {birthdayItems}
    </div>
  )
}
