import { StoreAction } from 'store/utils/actions';
import produce from 'immer';
import {
  handleRequest,
  handleResponse,
  handleUpdateResponse,
  handleAddResponse,
  handleDeleteResponse,
  handleReset,
} from 'store/utils/reducers';
import findIndex from 'lodash/findIndex';
import auth from 'store/auth';
import actions from './actions';

interface MessagerieState {
  currentRoom: {};
  roomsList: [];
  currentRoomMessages: [];
  messagesNumber: string;
}

export const initialState: MessagerieState = {
  currentRoom: null,
  roomsList: null,
  currentRoomMessages: null,
  messagesNumber: 0,
};

const treatMessages = (messages, state) => {
  if (!messages || !state) return [];

  let currentRoomMessages = state.currentRoomMessages;

  if (!currentRoomMessages) currentRoomMessages = [];

  messages.forEach(message => {
    currentRoomMessages.push(message);
  });

  return currentRoomMessages;
};

const refreshRoomsList = (room, state) => {
  if (!room || !state || !state.roomsList || state.roomsList.length === 0) return [];

  const roomsList = state.roomsList;

  const roomToRefresh = findIndex(roomsList, { _id: room._id });

  if (roomToRefresh >= 0) roomsList[roomToRefresh] = room;

  return roomsList;
};

const reducer = (state: MessagerieState = initialState, action: StoreAction): MessagerieState => {
  return produce(
    state,
    (draft): MessagerieState => {
      switch (action.type) {
        case actions.getOneRoom.result.constant:
          handleResponse(draft, action, 'currentRoom');
          draft.currentRoomMessages = {
            data: treatMessages(action.payload.getMessages, state),
            loaded: true,
            loading: false,
          };
          draft.messagesNumber = draft.currentRoomMessages.data.length;
          break;
        case actions.getRoomsList.result.constant:
          handleResponse(draft, action, 'roomsList', true);
          break;
        case actions.createRoom.result.constant:
          // add is also working as a get one
          if (draft.roomsList) {
            const found = findIndex(draft.roomsList.data, rooms => {
              return rooms._id === action.payload._id;
            });

            if (found < 0) {
              draft.roomsList.data.unshift(action.payload);
            }
          } else {
            draft.roomsList = draft.roomsList || {};
            draft.roomsList.data = [action.payload];
          }
          break;
        case actions.getRoomMessages.request.constant:
          handleRequest(draft, action, 'currentRoomMessages', true);
          draft.messagesNumber = 0;
          break;
        case actions.getRoomMessages.result.constant:
          handleResponse(draft, action, 'currentRoomMessages');
          if (draft.currentRoomMessages && draft.currentRoomMessages.data)
            draft.messagesNumber = draft.currentRoomMessages.data.length;
          break;
        case actions.addMessageToRoom.result.constant: {
          draft.currentRoomMessages = draft.currentRoomMessages || {};
          draft.currentRoomMessages.data = draft.currentRoomMessages.data || [];

          handleAddResponse(draft, action, 'currentRoomMessages', undefined, true);
          if (draft.currentRoomMessages && draft.currentRoomMessages.data)
            draft.messagesNumber = draft.currentRoomMessages.data.length;
          break;
        }
        case actions.resetMessageList.constant:
          handleReset(draft, action, 'currentRoomMessages');
          break;
        case actions.markMessagesAsRead.result.constant:
          if (draft.roomsList) draft.roomsList = refreshRoomsList(action.payload, state);
          break;
        case actions.leaveRoom.constant:
          draft.currentRoom = null;
          draft.currentRoomMessages = null;
          break;
        case auth.actions.logout.result.constant:
          draft.currentRoom = null;
          draft.roomsList = null;
          break;
        default:
      }
    },
  );
};

export default reducer;
