import { useCallback, useEffect, useMemo } from 'react'
import type {
  LassoToolsData,
  LassoToolsControlProps,
  LassoToolsState,
} from './types'
import { useLassoToolsState } from './provider/provider'

export function LassoToolsControls({
  mapId,
  children,
}: LassoToolsControlProps) {
  const enabled = useLassoToolsState((state) => state.data[mapId]?.enabled)!
  const setEnabled = useLassoToolsState((state) => state.setEnabled)
  const values = useLassoToolsState((state) => state.data[mapId]?.values)!
  const setValue = useLassoToolsState((state) => state.setValue)
  const setVisibility = useLassoToolsState((state) => state.setVisibility)
  const modeSelected = useLassoToolsState(
    (state) => state.data[mapId]?.modeSelected,
  )!
  const setModeSelected = useLassoToolsState((state) => state.setModeSelected)
  const modes = useLassoToolsState((state) => state.data[mapId]?.modes)!
  const setModeInstance = useLassoToolsState((state) => state.setModeInstance)

  useEffect(() => {
    const data = modes[modeSelected]

    if (data && enabled) {
      const Mode = data.mode
      setModeInstance(mapId, new Mode() as LassoToolsState['modeInstance'])
    }
  }, [enabled, mapId, modeSelected, modes, setModeInstance])

  const [mask, draw] = useMemo(() => {
    const serialize = (value: LassoToolsData) => ({
      id: value.id,
      ...value.properties,
      visible: value.properties.visible,
      label: value.properties.label,
    })
    const _values = Object.values(values)
    const mask = _values.filter((value) => value.type === 'mask').map(serialize)
    const draw = _values.filter((value) => value.type === 'draw').map(serialize)
    return [mask, draw]
  }, [values])

  const handleModeSelected = useCallback(
    (mode: LassoToolsState['modeSelected']) => {
      setEnabled(mapId, !!mode)
      setModeSelected(mapId, mode)
    },
    [mapId, setEnabled, setModeSelected],
  )

  return children({
    mapId,
    enabled,
    modes,
    modeSelected,
    values: {
      mask,
      draw,
    },
    setValue: useCallback(
      (id, data) => setValue(mapId, id, data),
      [mapId, setValue],
    ),
    setEnabled: useCallback(
      (enabled) => setEnabled(mapId, enabled),
      [mapId, setEnabled],
    ),
    setVisibility: useCallback(
      (valueId, visible) => setVisibility(mapId, valueId, visible),
      [mapId, setVisibility],
    ),
    setModeSelected: handleModeSelected,
  })
}
