import React, { useCallback, useEffect, useState } from 'react'
import { MediaDeviceManager } from '@zocks-communications/client-sdk-js'
import { MenuItem, SelectButton } from '../common'
import { useSelectMediaDevice } from './hooks'
import { DeviceSelectButtonProps } from './models'

export const DeviceSelectButton: React.FC<DeviceSelectButtonProps> = ({
  deviceKind,
  onDeviceSelected,
  disabled,
  label,
  components,
  styles,
}) => {
  const { selectedMediaDeviceId, selectMediaDevice } = useSelectMediaDevice(deviceKind)
  const [sources, setSources] = useState<MediaDeviceInfo[]>()
  const [menuItems, setMenuItems] = useState<MenuItem[]>([])

  const SelectMenuElement = components?.SelectMenu

  const listDevices = useCallback(async () => {
    const devices = await MediaDeviceManager.getDevices(deviceKind)
    setSources(devices)
    setMenuItems(
      devices.map((item) => {
        return {
          label: item.label,
          value: item.deviceId,
          selected: item.deviceId === selectedMediaDeviceId,
        }
      })
    )
  }, [selectedMediaDeviceId, deviceKind])

  useEffect(() => {
    if (!sources) {
      return
    }
    if (!sources.length) {
      selectMediaDevice(null)
    } else if (!selectedMediaDeviceId) {
      const defaultDevice = sources[0]
      selectMediaDevice(defaultDevice.deviceId)
    } else if (!sources.some((d) => d.deviceId === selectedMediaDeviceId)) {
      const defaultDevice = sources[0]
      selectMediaDevice(defaultDevice.deviceId)
      onDeviceSelected(defaultDevice)
    }
  }, [selectMediaDevice, selectedMediaDeviceId, sources, deviceKind, onDeviceSelected])

  useEffect(() => {
    listDevices()
    navigator.mediaDevices.addEventListener('devicechange', listDevices)

    return () => {
      navigator.mediaDevices.removeEventListener('devicechange', listDevices)
    }
  }, [listDevices])

  if (!sources || (sources.length <= 1 && !SelectMenuElement)) {
    return <></>
  }

  const onMenuItemSelected = (item: MenuItem) => {
    const device = sources.find((d) => d.label === item.label)
    if (device) {
      selectMediaDevice(device.deviceId)
      onDeviceSelected(device)
    }
  }

  return (
    <SelectButton
      disabled={disabled}
      styles={styles}
      buttonLabel={label}
      menuItems={menuItems}
      onMenuItemSelected={onMenuItemSelected}
      SelectMenu={SelectMenuElement}
    />
  )
}
