import { useState, useEffect } from 'react'
import arrayMove from 'array-move'
import { SortableList } from '../../sortable'
import { TBlockInstance } from '../types'
import { emptyBlockInstance } from '../utils'
import BlockInstanceInputs from './BlockInstanceInputs'

const BlockList = ({
  value = [],
  name,
  onChange,
  className,
}: {
  value?: TBlockInstance[]
  name: string
  onChange: GenericEventHandler
  className?: string
}) => {
  const [state, setState] = useState(value.map((item) => item.id))

  function updateOrderProperty<T extends { id: U }, U>(values: T[], orderList: U[]) {
    const orderedValues = values.map((value) => {
      const order = orderList.findIndex((orderedId) => orderedId === value.id)
      return { ...value, order }
    })
    onChange({ target: { type: 'custom', name, value: orderedValues } })
  }

  function onSortEnd({ oldIndex, newIndex }: { oldIndex: number; newIndex: number }) {
    const newOrder = arrayMove(state, oldIndex, newIndex)
    setState(newOrder)
    updateOrderProperty(value, newOrder)
  }

  useEffect(() => {
    const missingIds = value
      .filter((item) => !state.includes(item.id))
      .filter((item) => !item.id.startsWith('--'))
      .map((item) => item.id)
    const stateWithoutRemovedItems = state.filter((stateId) =>
      value.find((item) => stateId === item.id)
    )
    setState([...stateWithoutRemovedItems, ...missingIds])
  }, [value])

  const items = state
    .map((stateId) => {
      const itemIndex = value.findIndex((item) => item.id === stateId)
      if (itemIndex < 0) return null
      const item = value[itemIndex]
      return (
        <BlockInstanceInputs
          key={item.id}
          name={`${name}.${itemIndex}`}
          value={item}
          onChange={onChange}
        />
      )
    })
    .filter((block) => block !== null)

  return (
    <fieldset className={className}>
      <h2>Blocks</h2>
      <SortableList items={items} onSortEnd={onSortEnd} useDragHandle lockAxis={'y'} />

      <button
        onClick={(event) => {
          event.preventDefault()
          onChange(addBlock(name, value))
        }}
        type='button'
      >
        Add block
      </button>
      <style jsx>
        {`
          h2 {
            margin: 0.4em 0.3em;
            padding: 0;
          }
          fieldset {
            padding: 0;
          }
        `}
      </style>
    </fieldset>
  )
}

export default BlockList

export function addBlock(name: string, blockList: TBlockInstance[]) {
  const newBlock = emptyBlockInstance({
    order: blockList ? blockList.filter((block) => !block.id.startsWith('--')).length : 0,
  })
  return {
    target: {
      type: 'custom',
      name,
      value: blockList ? [...blockList, newBlock] : [newBlock],
    },
  }
}
