import { createSlice, PayloadAction } from '@reduxjs/toolkit'
import { RootState } from '../../app/store'
import { ChatMessageModel, ChatMessageType, ChatModel } from './models'
import { PUBLIC_CHAT_RECIPIENT } from './constants'
import { ChatMessageAction } from './actionModels'

const initialState: ChatModel = {
  publicChatMessages: [],
  privateChatMessages: {},
  messageRecipient: PUBLIC_CHAT_RECIPIENT,
  newMessagesFrom: [],
}

export const chatSlice = createSlice({
  name: 'chat',
  initialState,
  reducers: {
    publicChatMessageReceived: (state, action: PayloadAction<ChatMessageAction>) => {
      const chatMessage = action.payload
      state.publicChatMessages.push({
        type: ChatMessageType.PUBLIC,
        ...chatMessage,
      })
      saveNewMessageSender(state, PUBLIC_CHAT_RECIPIENT)
    },
    publicChatMessageSent: (state, action: PayloadAction<ChatMessageAction>) => {
      const chatMessage = action.payload
      state.publicChatMessages.push({
        type: ChatMessageType.PUBLIC,
        ...chatMessage,
      })
    },
    privateChatMessageReceived: (state, action: PayloadAction<ChatMessageAction>) => {
      const chatMessage = action.payload
      const {
        from: { id: senderId },
      } = chatMessage
      if (senderId) {
        addPrivateMessageForParticipant(state.privateChatMessages, chatMessage, senderId)
        saveNewMessageSender(state, senderId)
      }
    },
    privateChatMessageSent: (state, action: PayloadAction<ChatMessageAction>) => {
      const chatMessage = action.payload
      const { privateChatMessages } = state
      const { to: { id: recipientId } = {} } = chatMessage
      if (recipientId) {
        addPrivateMessageForParticipant(privateChatMessages, chatMessage, recipientId)
      }
    },
    clearChatMessages: (state) => {
      state.publicChatMessages = []
      state.privateChatMessages = {}
      state.messageRecipient = PUBLIC_CHAT_RECIPIENT
      state.newMessagesFrom = []
    },
    setMessageRecipient: (state, action: PayloadAction<string>) => {
      state.messageRecipient = action.payload
    },
    clearNewMessageFrom: (state, action: PayloadAction<string>) => {
      const messageFrom = action.payload
      state.newMessagesFrom = state.newMessagesFrom.filter((s) => s !== messageFrom)
    },
  },
})

const addPrivateMessageForParticipant = (
  privateChatMessages: { [participantId: string]: ChatMessageModel[] },
  chatMessage: ChatMessageAction,
  remoteParticipantId: string
) => {
  if (!Object.keys(privateChatMessages).includes(remoteParticipantId)) {
    privateChatMessages[remoteParticipantId] = []
  }
  privateChatMessages[remoteParticipantId].push({
    type: ChatMessageType.PRIVATE,
    ...chatMessage,
  })
}

const saveNewMessageSender = (state: ChatModel, senderId: string) => {
  state.newMessagesFrom.push(senderId)
  state.newMessagesFrom = [...new Set(state.newMessagesFrom)]
}

export const {
  clearChatMessages,
  clearNewMessageFrom,
  publicChatMessageReceived,
  publicChatMessageSent,
  privateChatMessageReceived,
  privateChatMessageSent,
  setMessageRecipient,
} = chatSlice.actions

export const selectPublicChatMessages = (state: RootState) => state.chat.publicChatMessages

export const selectPrivateChatMessages = (state: RootState) => state.chat.privateChatMessages

export const selectMessageRecipient = (state: RootState) => state.chat.messageRecipient

export const selectNewMessagesFrom = (state: RootState) => state.chat.newMessagesFrom

export default chatSlice.reducer
