import Vue from 'vue'
import messageAPI from '@/services/api/messages'
import conversationsAPI from '@/services/api/conversations'
import { createMetaModule, withMeta, metaStatusesWithId } from '@/store/helpers'

export function isUnread (message, conversation) {
  if (!message || !conversation) return
  if (!conversation.seenUpTo) return true
  return message.id > conversation.seenUpTo
}

function initialState () {
  return {
    entries: {},
    messages: {}, // { <conversation-id> : [<message>,...] }
    cursors: {}, // { <conversation-id> : [<cursor>, ...]}
    activeConversationId: null,
  }
}

export default {
  namespaced: true,
  modules: { meta: createMetaModule() },
  state: initialState(),
  getters: {
    enrichMessage: (state, getters, rootState, rootGetters) => message => {
      if (!message) return
      return {
        ...message,
        author: rootGetters['users/get'](message.author),
        isUnread: isUnread(message, getters.activeConversation),
      }
    },
    activeMessages: (state, getters) => {
      return (state.messages[state.activeConversationId] || []).map(getters.enrichMessage)
    },
    activeConversation: state => {
      if (!state.activeConversationId) return
      return state.entries[state.activeConversationId]
    },
    active: (state, getters) => {
      const id = state.activeConversationId
      if (!id) return

      const canLoadMore = typeof state.cursors[state.activeConversationId] === 'string'
      return {
        ...getters.activeConversation,
        messages: getters.activeMessages,
        canLoadMore,
        ...metaStatusesWithId(getters, ['send', 'fetch', 'fetchMore'], id),
      }
    },
  },
  actions: {
    ...withMeta({
      async send ({ commit, state, dispatch }, { id, messageData }) {
        const message = await messageAPI.create({
          content: messageData,
          conversation: id,
        })
        commit('updateMessages', {
          messages: [message],
          conversationId: message.conversation,
        })
      },
      async fetch ({ commit }, conversationId) {
        const data = await messageAPI.list(conversationId)
        commit('updateMessages', {
          messages: data.results,
          conversationId,
          cursor: data.next,
        })
      },

      async fetchMore ({ state, commit }, conversationId) {
        const currentCursor = state.cursors[conversationId]
        const data = await messageAPI.listMore(currentCursor)
        commit('updateMessages', {
          messages: data.results,
          conversationId,
          cursor: data.next,
        })
      },

      async fetchConversation ({ commit }, conversationId) {
        commit('setConversation', { conversation: await conversationsAPI.get(conversationId) })
      },

      async mark ({ dispatch }, { id, seenUpTo }) {
        await conversationsAPI.mark(id, { seenUpTo })
      },
    }),

    async sendInActiveConversation ({ state, dispatch }, messageData) {
      dispatch('send', { id: state.activeConversationId, messageData })
    },
    async markAllReadInActiveConversation ({ state, dispatch, getters }) {
      const newestMessage = getters.activeMessages[0]
      dispatch('mark', { id: state.activeConversationId, seenUpTo: newestMessage.id })
    },

    async fetchMoreForActiveConversation ({ state, dispatch }) {
      const conversationId = state.activeConversationId
      const currentCursor = state.cursors[conversationId]
      if (!currentCursor) {
        return
      }
      await dispatch('fetchMore', conversationId)
    },

    async setActive ({ commit, dispatch }, conversation) {
      commit('setActive', { conversationId: conversation.id })
      commit('setConversation', { conversation })
      await dispatch('fetch', conversation.id)
    },

    clearActive ({ commit }) {
      commit('clearActive')
    },

    receiveMessage ({ commit, state, getters }, message) {
      commit('updateMessages', {
        messages: [message],
        conversationId: message.conversation,
      })
    },

    updateConversation ({ state, commit }, conversation) {
      const existing = state.entries[conversation.id]
      if (existing && existing.updatedAt <= conversation.updatedAt) {
        commit('setConversation', { conversation })
      }
    },
  },
  mutations: {
    setActive (state, { conversationId }) {
      state.activeConversationId = conversationId
    },
    clearActive (state) {
      state.activeConversationId = null
    },
    updateMessages (state, { conversationId, messages, cursor }) {
      if (!state.messages[conversationId]) {
        Vue.set(state.messages, conversationId, messages)
        return
      }
      // simple insertion sort for new messages
      // assumes that existing messages are sorted AND incoming messages are sorted
      let i = 0
      for (let message of messages) {
        const stateMessages = state.messages[conversationId]
        while (i < stateMessages.length && stateMessages[i].createdAt > message.createdAt) i++
        if (i >= stateMessages.length || stateMessages[i].id !== message.id) {
          stateMessages.splice(i, 0, message)
        }
      }
      if (cursor !== undefined) {
        Vue.set(state.cursors, conversationId, cursor)
      }
    },
    setConversation (state, { conversation }) {
      Vue.set(state.entries, conversation.id, conversation)
    },
  },
}

@@ -1907,37 +1907,40 @@
         
-commit('updat
+dispatch('receiv
 eMessage
 s', %7B%0A  
@@ -1935,102 +1935,18 @@
 sage
-s
 ', 
-%7B%0A          messages: %5Bmessage%5D,%0A          conversationId: message.conversation,%0A        %7D
+message
 )%0A  
@@ -2147,32 +2147,99 @@
 conversationId,%0A
+        %7D)%0A        commit('setCursor', %7B%0A          conversationId,%0A
           cursor
@@ -2481,32 +2481,32 @@
 ateMessages', %7B%0A
-
           messag
@@ -2541,32 +2541,99 @@
 conversationId,%0A
+        %7D)%0A        commit('setCursor', %7B%0A          conversationId,%0A
           cursor
@@ -4595,24 +4595,16 @@
 messages
-, cursor
  %7D) %7B%0A  
@@ -5220,40 +5220,63 @@
     
-  if (cursor !== undefined
+%7D,%0A    setCursor (state, %7B conversationId, cursor %7D
 ) %7B%0A
-  
     
@@ -5324,24 +5324,16 @@
 cursor)%0A
-      %7D%0A
     %7D,%0A 

fix message loading