import React, { useEffect, useRef, useState } from 'react'
import { ChatInputProps } from '../models'
import { AttachmentDisplay, AttachmentUploader } from './Attachment'
import { ChatAttachmentModel, PUBLIC_CHAT_RECIPIENT } from '../../../store'
import { ChatMessageInput } from './ChatMessageInput'
import { RecipientSelector } from './RecipientSelector'
import { EmojiSelector } from './EmojiSelector'
import { SendButton } from './SendButton'
import zocksStyle from './CustomizableChatInput.module.scss'
import { getClassName, getMergedClassNames } from '../../common'

export const CustomizableChatInput: React.FC<ChatInputProps> = ({
  messageRecipient,
  onRecipientSelected,
  remoteParticipants,
  sendPublicMessage,
  sendPrivateMessage,
  uploadAttachment,
  components,
  styles,
}) => {
  const [currentMessage, setCurrentMessage] = useState('')
  const [attachment, setAttachment] = useState<ChatAttachmentModel>()
  const [isUploading, setUploading] = useState(false)
  const [hasAttachmentError, setAttachmentError] = useState(false)
  const chatMessageInputRef = useRef<HTMLElement>(null)

  const recipientParticipant = remoteParticipants?.find((p) => p.id === messageRecipient)

  const sendMessage = () => {
    const messageToSend = currentMessage.trim()
    if (!messageToSend && !attachment) {
      return
    }
    if (!messageRecipient) {
      sendPublicMessage && sendPublicMessage(messageToSend, attachment)
    }
    if (recipientParticipant) {
      sendPrivateMessage && sendPrivateMessage(messageToSend, recipientParticipant, attachment)
    }
    setCurrentMessage('')
    clearAttachment()
  }

  const recipientSelectedHandler = (recipientId: string) => {
    setAttachment(undefined)
    onRecipientSelected && onRecipientSelected(recipientId)
  }

  const emojiSelectedHandler = (emoji: string) => {
    if (!currentMessage) {
      setCurrentMessage(emoji)
    } else {
      setCurrentMessage((currentMessage) => `${currentMessage} ${emoji}`)
    }
    chatMessageInputRef.current?.focus()
  }

  const attachmentUploadStartedHandler = () => {
    setUploading(true)
    setAttachmentError(false)
  }

  const attachmentUploadFinishedHandler = (file: File, fileId: string) => {
    setAttachment({ fileId, fileName: file.name, fileSize: file.size, contentType: file.type })
    setUploading(false)
    chatMessageInputRef.current?.focus()
  }

  const attachmentUploadFailedHandler = () => {
    clearAttachment()
    setUploading(false)
    setAttachmentError(true)
  }

  const clearAttachment = () => {
    setAttachment(undefined)
  }

  useEffect(() => {
    if (messageRecipient && remoteParticipants && !remoteParticipants.some((p) => p.id === messageRecipient)) {
      onRecipientSelected && onRecipientSelected(PUBLIC_CHAT_RECIPIENT)
      setCurrentMessage('')
    }
  }, [onRecipientSelected, messageRecipient, remoteParticipants])

  const ChatMessageInputElement = components?.ChatMessageInput ?? ChatMessageInput
  const RecipientSelectorElement = components?.RecipientSelector ?? RecipientSelector
  const EmojiSelectorElement = components?.EmojiSelector ?? EmojiSelector
  const SendButtonElement = components?.SendButton ?? SendButton
  const AttachmentUploaderElement = components?.AttachmentUploader ?? AttachmentUploader
  const AttachmentDisplayElement = components?.AttachmentDisplay ?? AttachmentDisplay
  const mergedStyles = getMergedClassNames(zocksStyle, styles)

  return (
    <div className={getClassName('chat-input__input-group', mergedStyles)}>
      <div className={getClassName('chat-input__message-input-container', mergedStyles)}>
        <div className={getClassName('chat-input__top-bar', mergedStyles)}>
          <RecipientSelectorElement
            remoteParticipants={remoteParticipants}
            onRecipientSelected={recipientSelectedHandler}
            styles={mergedStyles}
          />
          <EmojiSelectorElement
            onSelectEmoji={emojiSelectedHandler}
            currentMessage={currentMessage}
            styles={mergedStyles}
          />
          {uploadAttachment && (
            <AttachmentUploaderElement
              uploadAttachment={uploadAttachment}
              attachmentRecipient={recipientParticipant}
              onAttachmentUploadStarted={attachmentUploadStartedHandler}
              onAttachmentUploadFinished={attachmentUploadFinishedHandler}
              onAttachmentUploadFailed={attachmentUploadFailedHandler}
              styles={mergedStyles}
            />
          )}
        </div>
        <ChatMessageInputElement
          ref={chatMessageInputRef}
          currentChatMessage={currentMessage}
          onChatMessageChanged={(message) => setCurrentMessage(message)}
          sendMessage={sendMessage}
          styles={mergedStyles}
        />
        <AttachmentDisplayElement
          attachment={attachment}
          onClearAttachment={clearAttachment}
          hasAttachmentError={hasAttachmentError}
          styles={mergedStyles}
        />
      </div>
      <SendButtonElement disabled={!currentMessage.trim() && !attachment} onClick={sendMessage} styles={mergedStyles} />
      {isUploading && (
        <div className={getClassName('chat-input__loader-container', mergedStyles)}>
          <div className={getClassName('chat-input__loader', mergedStyles)} />
        </div>
      )}
    </div>
  )
}
