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

const aligments: { [alignment: string]: any } = {
  start: 'flex-start',
  center: 'center',
  end: 'flex-end',
  stretch: 'stretch'
}

type GridItemProps = {
  style: React.CSSProperties,
  alignment?: {
    h: 'start' | 'center' | 'end',
    v: 'start' | 'center' | 'end'
  }
  border?: {
    style: 'none' | 'horizontal' | 'vertical' | 'both'
    width: number
    color: string
  }
  width: number,
  height: number,
  horizontalGap: number,
  verticalGap: number,
  containerData: ContainerDataProps
  fontSize?: string
  children?: React.ReactNode
}

export type ContainerDataProps = {
  ic_index: number
  ic_rowIndex: number,
  ic_rows: number
  ic_columnIndex: number,
  ic_columns: number,
  ic_firstChild: boolean,
  ic_lastChild: boolean
}

const GridItem: React.FunctionComponent<GridItemProps> = (props) => {
  const elRef = useRef<HTMLDivElement>(null)
  const [elementHeight, setElementHeight] = useState<number>(0)

  useEffect(() => {
    if (elRef.current) {
      setElementHeight(elRef.current.offsetHeight)
    }
  }, [props])

  const getBorder = (borderClass: 'horizontal' | 'vertical'): React.CSSProperties => {
    let styles: React.CSSProperties = {
      position: 'absolute'
    }
    if (!props.border) return { ...styles, display: 'none' }

    const { style, width, color } = props.border
    const { ic_columnIndex, ic_columns, ic_rowIndex, ic_rows } = props.containerData
    const { verticalGap, horizontalGap } = props
    if (!style || style === 'none') return { ...styles, display: 'none' }

    styles = {
      ...styles,
      backgroundColor: color || 'black'
    }

    let lastColumn: boolean = ic_columnIndex + 1 === ic_columns
    if (borderClass === 'vertical' && style !== 'horizontal' && !lastColumn) {
      styles = {
        ...styles,
        width: (width || 1) + 'px',
        right: 0,
        top: 0,
        bottom: 0,
        marginTop: ic_rowIndex > 0 ? `${verticalGap / 2}%` : undefined,
        marginBottom: ic_rowIndex + 1 < ic_rows ? `${verticalGap / 2}%` : undefined
      }
    }

    let lastRow: boolean = ic_rowIndex + 1 === ic_rows
    if (borderClass === 'horizontal' && style !== 'vertical' && !lastRow) {
      styles = {
        ...styles,
        height: (width || 1) + 'px',
        bottom: 0,
        left: 0,
        right: 0,
        marginLeft: ic_columnIndex > 0 ? `${horizontalGap / 2}%` : undefined,
        marginRight: ic_columnIndex + 1 < ic_columns ? `${horizontalGap / 2}%` : undefined
      }
    }
    return styles
  }

  const getOffset = (): React.CSSProperties => {
    let styles: React.CSSProperties = {}
    const { ic_columnIndex, ic_columns, ic_rowIndex, ic_rows } = props.containerData
    const { horizontalGap, verticalGap } = props
    if (ic_columnIndex !== 0) {
      styles = {
        ...styles,
        paddingLeft: `${horizontalGap / 2}%`
      }
    }
    if (ic_columnIndex + 1 < ic_columns) {
      styles = {
        ...styles,
        paddingRight: `${horizontalGap / 2}%`
      }
    }
    if (ic_rowIndex !== 0) {
      styles = {
        ...styles,
        paddingTop: `${verticalGap / 2}%`
      }
    }
    if (ic_rowIndex + 1 < ic_rows) {
      styles = {
        ...styles,
        paddingBottom: `${verticalGap / 2}%`
      }
    }
    return styles
  }

  let style: React.CSSProperties = {
    overflow: 'hidden',
    display: 'flex',
    position: 'relative',
    width: `${props.width}%`,
    height: `${props.height}%`,
    fontSize: props.fontSize || elementHeight && `${elementHeight}px`,
    ...props.style
  }

  return (
    <div style={style} ref={elRef}>
      <div style={{ ...getBorder('horizontal') }} />
      <div style={{ ...getBorder('vertical') }} />
      <div style={{
        ...getOffset(),
        display: 'flex',
        flex: 1,
        alignItems: aligments[props?.alignment?.v || 'stretch'],
        justifyContent: aligments[props?.alignment?.h || 'flex-start']
      }}>
        {
          props.children && React.isValidElement(props.children)
            ? React.cloneElement(props.children, props.containerData)
            : props.children
        }
      </div>
    </div>
  )
}

export default GridItem
