import { NavigationActions } from 'react-navigation';
import { createLogic, Done } from 'redux-logic';
import { AuthActions, ChatActions } from '../actions';
import { BasicUserInfo, Conversation, Dispatch, RootState, UserRole } from '../models';
import { Routes } from '../navigation';
import { getOwnRole } from '../utils/RoleManager';
import { Firestore, LogicDeps } from './';

const registerChatCallbacks = createLogic({
  type: AuthActions.ActionKey.INITIALIZE_USER_FLOW,
  warnTimeout: 0,
  processOptions: {
    dispatchMultiple: true,
  },
  process({ getState, action }: LogicDeps & {
    getState: () => RootState,
    action: AuthActions.InitializeUserFlow,
  },
    dispatch: Dispatch) {

    if (!getState().user.body) {
      return;
    }

    const currentUserId = action.uid;
    const userField = getOwnRole(action.userRole);

    Firestore
      .collection('conversations')
      .where(`${userField}.id`, '==', currentUserId)
      .onSnapshot((conversationsSnaphot) => {
        conversationsSnaphot.docChanges.forEach((change) => {
          if (change.type === 'added') {
            const conversationDoc = change.doc;
            const conversation = {
              ...conversationDoc.data(),
              id: conversationDoc.id,
            } as Conversation;
            dispatch(ChatActions.conversationAdded(conversation));
            conversationDoc.ref.collection('messages')
              .onSnapshot((messagesSnaphot) => {
                messagesSnaphot.docChanges.forEach((messageDocChange) => {
                  if (messageDocChange.type === 'added') {
                    dispatch(ChatActions.newMessageReceived(conversationDoc.id,
                      {
                        ...messageDocChange.doc.data(),
                        id: messageDocChange.doc.id,
                      },
                    ));
                  }
                });
              },
            );
          } else if (change.type === 'modified') {
            dispatch(ChatActions.conversationUpdated(change.doc.data() as Conversation));
          }
        });
      });
  },
});

const createConversationLogic = createLogic({
  type: ChatActions.ActionKey.OPEN_CHATROOM_REQUEST,
  process({ getState, action }: LogicDeps & {
    getState: () => RootState,
    action: ChatActions.OpenChatRoomRequest,
  },
    dispatch: Dispatch, done: Done) {

    let employeeId;
    let employerId;
    let employer: BasicUserInfo;
    let employee: BasicUserInfo;

    const currentUserId = getState().user.body.id;
    if (getState().user.role === UserRole.EMPLOYEE) {
      employeeId = currentUserId;
      employerId = action.userId;
      employee = {
        id: employeeId,
        name: getState().user.body.name,
        avatar: getState().user.body.avatar,
        lastVisit: Date.now(),
      };
      employer = {
        id: employerId,
        name: action.userName,
      };
    } else {
      employerId = currentUserId;
      employeeId = action.userId;
      employer = {
        id: employerId,
        name: getState().user.body.name,
        avatar: getState().user.body.avatar,
        lastVisit: Date.now(),
      };
      employee = {
        id: employeeId,
        name: action.userName,
      };
    }
    const conversationId = `${employerId}@${employeeId}`;
    Firestore
      .collection('conversations')
      .doc(conversationId)
      .set({ employer, employee, id: conversationId }, { merge: true })
      .then(() => done());
    dispatch(NavigationActions.navigate({
      routeName: Routes.CHATROOM,
      params: { conversationId },
    }));
  },
});

const toggleMuteConversation = createLogic({
  type: ChatActions.ActionKey.TOGGLE_MUTE_CONVERSATION_REQUESTED,
  process({ action, getState }: LogicDeps & { action: ChatActions.ToggleMuteConversationRequested },
    dispatch: Dispatch, done: Done) {

    const conversationId = action.conversationId;

    Firestore
      .collection('conversations')
      .doc(conversationId)
      .update({
        muted: {
          [getState().user.body.id]: action.isMuted,
        },
      })
      .then(() => dispatch(ChatActions.ToggleMuteConversationSuccess(action.conversationId)))
      .catch((e) => {
        dispatch(ChatActions.ToggleMuteConversationFail(action.conversationId, e));
      })
      .then(() => done());
  },
});

const sendMessage = createLogic({
  type: ChatActions.ActionKey.SEND_MESSAGE_REQUESTED,
  process({ getState, action }: LogicDeps & {
    getState: () => RootState,
    action: ChatActions.SendMessageRequested,
  },
    dispatch: Dispatch, done: Done) {

    const { id, name } = getState().user.body;
    const conversationId = action.conversationId;
    const conversation = getState().conversations.find((cv) => cv.id === action.conversationId);
    const toMuted = conversation && conversation.muted && conversation.muted[action.recipientId];
    const message = {
      body: action.message,
      authorId: id,
      recipientId: action.recipientId,
      authorName: name,
      timestamp: Date.now(),
      toMuted,
    };
    Firestore
      .collection('conversations')
      .doc(conversationId)
      .collection('messages')
      .add(message)
      .catch((e) => console.error(e))
      .then(() => done());
  },
});

export const chatLogic = [
  registerChatCallbacks,
  sendMessage,
  createConversationLogic,
  toggleMuteConversation,
];
