import React, { useContext, useState, useRef, useEffect } from 'react'
import { Item } from './Item'
import { ConfigureContext } from '../../contex/configureContext/ConfigureContext'
import { useStateWithCallbackLazy } from 'use-state-with-callback';
import { ReactElementLike } from 'prop-types';



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



interface Props {
  items: ReactElementLike[],
  animation: Animation,
  animate: boolean
}

interface Animation {
  mode: string | undefined
  duration: number | undefined,
  speed: number | undefined,
  reverse: boolean | undefined
}



export const ItemsContainer = ({ animation, items, animate }: Props) => {

  const { configureState } = useContext(ConfigureContext)
  const { containerColumns, containerRows, containerRowsGap, containerColumnsGap } = configureState.parameters
  const container = useRef<HTMLDivElement>(null)
  const [animations] = useState(new (require('./animation'))())
  let itemsCount = Number(containerColumns) * Number(containerRows)
  let columns = Number(containerColumns) || 1
  let rows = Number(containerRows) || 1
  let rowsGap = Number(containerRowsGap) || 0
  let columnsGap = Number(containerColumnsGap) || 1

  const [show, setShow] = useState(false)
  const [item, setItem] = useState([])
  const [stage, setStage] = useStateWithCallbackLazy('idle')
  const [lastIndex, setLastIndex] = useState(0)

  const configure = () => {
    animations.configure(animation)
    itemsCount = Number(containerColumns) * Number(containerRows)
    columns = Number(containerColumns) || 1
    rows = Number(containerRows) || 1
    rowsGap = Number(containerRowsGap) || 0
    columnsGap = Number(containerColumnsGap) || 1

    if (animate && stage === stages.idle) createItems(lastIndex, items)
  }

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

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


  const createItems = (lastIndex: number, items: any) => {
    let count = 0
    if (lastIndex >= (items.length - 1)) {
      setLastIndex(lastIndex = 0)
    }
    let newItems = items.filter((_item: any, index: number) => {
      return index >= lastIndex
    }).map((item: any, index: any, arr: any) => {
      if (count >= itemsCount) return null
      setLastIndex(++lastIndex)
      count++
      return <Item
        key={lastIndex} containerData={{
          ic_index: index,
          ic_rowIndex: index / columns,
          ic_columnIndex: index % columns,
          ic_firstChild: index === 0,
          ic_lastChild: index === (arr.length - 1)
        }} style={animations.getInitialStyle()}
        // Item alignment. By default is center - center.
        // alignment={alignment}
        // Setup item width based on columns count.
        width={`${(100 - ((columnsGap * (columns - 1)))) / columns}%`}
        // Setup item height based on rows count. If 0 set up on auto.
        height={`${(100 - ((rowsGap * (rows - 1)))) / rows}%`}
        // Setup horizontal gap
        horizontalGap={columnsGap}
        // Setup vertical gap
        verticalGap={rowsGap}>
        {item}
      </Item>
    })


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


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



