import React from 'react'
import { VirtualBackgroundConfig, VirtualBackgroundType } from '@zocks-communications/client-sdk-js'
import { AudioControlButton, VideoControlButton, VirtualBackgroundVideoControlMenu } from '../../ControlButtons'
import { getClassName, getMergedClassNames, StyledComponent } from '../../common'
import { Video } from '../../Media'
import { JoinPageLocalStreamsProps } from './models'
import zocksStyle from './JoinPageLocalStreams.module.scss'

export const JoinPageLocalStreams: React.FC<JoinPageLocalStreamsProps> = ({ styles, localMedia, components }) => {
  const {
    localAudioStream,
    localVideoStream,
    virtualBackgroundStream,
    currentVirtualBackground,
    availableVirtualBackgrounds,
    currentVideoDeviceId,
    toggleLocalAudioStream,
    toggleLocalVideoStream,
    changeVirtualBackground,
    stopLocalVirtualBackground,
    selectAudioDevice,
    selectVideoDevice,
  } = localMedia

  const audioEnabled = !!localAudioStream
  const videoEnabled = !!localVideoStream || !!virtualBackgroundStream

  const AudioControlButtonElement = components?.AudioControlButton ?? AudioControlButton
  const VideoControlButtonElement = components?.VideoControlButton ?? VideoControlButton
  const DisabledVideoComponentElement = components?.DisabledVideoComponent ?? DisabledVideoComponent
  const ExtraComponentElement = components?.ExtraComponent || null

  const changeVideoDevice = async (videoDevice: MediaDeviceInfo) => {
    if (currentVirtualBackground) {
      await stopLocalVirtualBackground()
      await changeVirtualBackground(currentVirtualBackground.type, videoDevice.deviceId, {
        backgroundImageUrl: currentVirtualBackground.url,
      })
    } else {
      selectVideoDevice(videoDevice)
    }
  }

  const toggleVideoStream = async () => {
    if (currentVirtualBackground) {
      if (videoEnabled) {
        await stopLocalVirtualBackground()
      } else {
        await changeVirtualBackground(currentVirtualBackground.type, currentVideoDeviceId || undefined, {
          backgroundImageUrl: currentVirtualBackground.url,
        })
      }
    } else {
      toggleLocalVideoStream()
    }
  }

  const toggleVirtualBackground = async (
    virtualBackgroundType: VirtualBackgroundType | null,
    config?: VirtualBackgroundConfig
  ) => {
    if (
      currentVirtualBackground &&
      currentVirtualBackground.type === virtualBackgroundType &&
      currentVirtualBackground.url === config?.backgroundImageUrl
    ) {
      await changeVirtualBackground(null)
    } else {
      await changeVirtualBackground(virtualBackgroundType, currentVideoDeviceId || undefined, config)
    }
    toggleLocalVideoStream()
  }

  const videoStream = currentVirtualBackground ? virtualBackgroundStream : localVideoStream

  const mergedStyles = getMergedClassNames(zocksStyle, styles)

  return (
    <div className={getClassName('join-page__local-streams', mergedStyles)}>
      {videoStream ? (
        <div className={getClassName('join-page__video-container', mergedStyles)}>
          <div className={getClassName('join-page__video-preview', mergedStyles)}>
            <Video videoStream={videoStream} />
          </div>
        </div>
      ) : (
        <DisabledVideoComponentElement styles={mergedStyles} />
      )}
      <div className={getClassName('join-page__local-stream-buttons', mergedStyles)}>
        <AudioControlButtonElement
          audioIsOn={audioEnabled}
          toggleAudio={toggleLocalAudioStream}
          onAudioDeviceSelected={selectAudioDevice}
          styles={mergedStyles}
        />
        <VideoControlButtonElement
          videoIsOn={videoEnabled}
          toggleVideo={toggleVideoStream}
          onVideoDeviceSelected={changeVideoDevice}
          components={{
            VideoControlMenu: VirtualBackgroundVideoControlMenu(
              availableVirtualBackgrounds,
              currentVirtualBackground,
              toggleVirtualBackground
            ),
          }}
          styles={mergedStyles}
        />
        {ExtraComponentElement && <ExtraComponentElement styles={mergedStyles} />}
      </div>
    </div>
  )
}

const DisabledVideoComponent: React.FC<StyledComponent> = ({ styles }) => {
  return <div className={getClassName('join-page__no-video-icon', styles)} />
}
