import API from '@/api'
import { getWsUrl } from '@/util/contract.js'
import WsManager from '@/util/wsManager.js'
import {
  decryptoMsg,
  dealErrorMsg,
  noticeManager
} from '@/util/util.js'
import axios from 'axios'
import Message from '@/store/db/Message.js'

var socket = null

const actions = {
  /**
   * @des 获取群基础信息
   * @param {Object} store
   * @param {Object} params
   */
  async getGroupInfo ({ dispatch, commit, state }, params) {
    API.group.getGroupInfo2({ group_id: state.groupId }, info => {
      if (info.data.code === 0) {
        let adminList = info.data.data.adminList
        let blockList = info.data.data.blockList
        let pinMsg = info.data.data.pinMsg
        let group = info.data.data.group
        let members = info.data.data.members
        let membersNum = info.data.data.group.member_num
        let userInfo = info.data.data.userInfo
        let sessionInfo = info.data.data.sessionInfo
        let isJoin = info.data.data.members.some((item) => {
          return state.userId == item.user_id
        })
        let eosInfo = info.data.data.eosInfo
        pinMsg && (pinMsg.visible = true)
        let _members = {}
        members.forEach(n => {
          if (!n.user_id) return
          _members[n.user_id] = n
        })
        commit('setGroupInfo', {
          userCounts: members.length,
          groupName: group.group_title,
          shareName: group.group_name,
          members: _members,
          membersArray: members,
          membersNum: membersNum,
          userInfo,
          groupNotice: group.group_notice,
          url: group.url,
          inviteUrl: group.invite_url,
          sessionInfo,
          isJoin,
          coverPhoto: group.cover_photo,
          adminList: adminList,
          blockList: blockList,
          pinMsg: pinMsg,
          creator: group.creator,
          eosInfo: eosInfo
        })
      }
    })
  },
  /**
   * @des 群聊 获取最新消息【from indexeddb】
   * @param {Object} store
   * @param {Object} params
   */
  async getNewMsgFromDb (store, params = {}) {
    // 先读取indexDB的数据，来渲染
    let { state } = store
    let { groupId } = state
    const objMessage = new Message()
    let data = await objMessage.getMsg(state.groupId)
    if (groupId === state.groupId && data && data.list.length > 0) {
      params.fromdb = true
      actions._renderGroupMsg(store, data, params)
      return true
    } else {
      return false
    }
  },
  /**
   * @des 群聊 获取最新消息【不需要登录】
   * @param {Object} store
   * @param {Object} params
   */
  async getNewMsg (store, params = {}) {
    let { state } = store
    let { groupId, endHash } = state
    // 然后再请求网上的数据，来渲染
    let msg = await API.group.getNewMsg({
      group_id: groupId,
      client_hash: endHash
    }).catch(() => {})

    if (groupId === state.groupId && msg.data.code === 0 && msg.data.data.list.length > 0) {
      params.fromdb = false
      actions._renderGroupMsg(store, msg.data.data, params)
    }

    return 'done'
  },
  _renderGroupMsg ({ dispatch, commit, state }, data, params) {
    let list = []
    data.list.forEach(n => {
      let member = data.userMap[n.from]

      if (!member) return
      list.push({
        name: member.nick_name || 'unknown',
        content: n.msg,
        userId: n.from,
        timestamp: n.create_time_int,
        avatar: member.cover_photo || '',
        hash: n.hash,
        type: n.from == state.userId ? 'me' : 'you',
        msg_type: n.msg_type,
        ext: n.ext ? n.ext : null,
        ext_info: n.ext_info ? n.ext_info : null
      })
    })

    commit('updateMembers', data.userMap)

    if (state.chatList.length) {
      commit('setHash', {
        endHash: list[list.length - 1].hash
      })
    } else {
      commit('setHash', {
        endHash: list[list.length - 1].hash,
        startHash: list[0].hash
      })
    }

    let itemData = params.newMsg ? { list: list, newMsg: params.newMsg, fromdb: false } : { list: list, fromdb: params.fromdb }
    commit('addChatItem', itemData)
  },
  async getPrivateNewMsgFromDb (store, params = {}) {
    let { rootState } = store
    let { curSession } = rootState
    const objMessage = new Message()
    let data = await objMessage.getMsg(curSession)
    if (curSession === rootState.curSession && data && data.list.length > 0) {
      actions._renderPrivateMsg(store, data, params)
      return true
    } else {
      return false
    }
  },
  /**
   * @des 私聊 获取最新消息【不需要登录】
   * @param {Object} store
   * @param {Object} params
   */
  async getPrivateNewMsg (store, params = {}) {
    let { state, rootState } = store
    let { curSession } = rootState
    let msg = await API.person.getNewMsg({
      session_id: curSession,
      client_hash: state.endHash
    }).catch(() => {})

    // 有聊天记录
    // if (msg.data.code === 0 && msg.data.data.list.length > 0) {
    // 没有聊天记录也要渲染，不然没设置member
    if (curSession === rootState.curSession && msg.data.code === 0) {
      actions._renderPrivateMsg(store, msg.data.data, params)
    }
    return msg.data
  },
  _renderPrivateMsg ({ dispatch, commit, state, rootState }, data, params) {
    let list = []
    // 更新members信息
    let members = data.userMap
    commit('updateGroup', {
      key: 'members',
      data: members
    })
    for (let k in members) {
      if (k !== rootState.userId) {
        commit('updateGroup', {
          key: 'privateName',
          data: members[k]['nick_name']
        })
      }
    }

    data.list.forEach(n => {
      let member = data.userMap[n.from]
      list.push({
        name: member ? member.nick_name : 'unknown',
        content: n.msg,
        userId: n.from,
        timestamp: n.create_time_int,
        avatar: member.cover_photo || '',
        hash: n.hash,
        type: n.from == rootState.userId ? 'me' : 'you',
        msg_type: n.msg_type,
        ext: n.ext ? n.ext : null
      })
    })

    if (list.length) {
      if (state.chatList.length) {
        commit('setHash', {
          endHash: list[list.length - 1].hash
        })
      } else {
        commit('setHash', {
          endHash: list[list.length - 1].hash,
          startHash: list[0].hash
        })
      }

      let itemData = params.newMsg ? { list: list, newMsg: params.newMsg } : list
      commit('addChatItem', itemData)
    }
  },
  /**
   * @des 群聊 获取历史消息【不需要登录】
   * @param {Object} store
   * @param {Object} params
   */
  async getHistoryMsg ({ dispatch, commit, state }, params = {}) {
    let his = localStorage.getItem(params.hash) // 先从本地缓存中获取记录
    let dList = []
    let status = '' // 请求状态
    if (his && state.useCache) {
      dList = JSON.parse(his)
    } else {
      // 本地缓存中没有记录，从接口获取
      let msg = await API.group.getHistoryMsg({
        group_id: state.groupId,
        client_hash: state.startHash
      }).catch(() => {})

      if (msg && msg.data.code === 0 && msg.data.data.list.length > 0) {
        // 重新格式数据
        msg.data.data.list.forEach(n => {
          if (n.msg_type == 4) {
            n.msg = JSON.parse(decryptoMsg(n.msg))
          } else {
            n.msg = decryptoMsg(n.msg)
          }
          let member = msg.data.data.userMap[n.from]
          commit('updateMembers', msg.data.data.userMap)
          if (!member) return
          dList.push({
            name: member ? member.nick_name : 'unknown',
            content: n.msg,
            userId: n.from,
            timestamp: n.create_time_int,
            avatar: member ? member.cover_photo : '',
            hash: n.hash,
            type: n.from == state.userId ? 'me' : 'you',
            msg_type: n.msg_type,
            ext: n.ext ? n.ext : null
          })
        })

        // 保存到本地缓存中
        if (state.useCache) {
          localStorage.setItem(params.hash, JSON.stringify(dList))
        }
      }
    }

    if (dList.length > 0) {
      commit('setHash', {
        startHash: dList[0].hash
      })

      commit('addHistoryList', dList)

      status = 'done'
    } else {
      commit('setHash', {
        startHash: null
      })

      status = 'end'
    }

    return status
  },
  /**
   * @des 私聊 获取历史消息【不需要登录】
   * @param {Object} store
   * @param {Object} params
   */
  async getPrivateHistoryMsg (
    { dispatch, commit, state, rootState },
    params = {}
  ) {
    let his = localStorage.getItem(params.hash) // 先从本地缓存中获取记录
    let dList = []
    let status = '' // 请求状态
    if (his && state.useCache) {
      dList = JSON.parse(his)
    } else {
      // 本地缓存中没有记录，从接口获取
      let msg = await API.person
        .getHistoryMsg({
          session_id: rootState.curSession,
          client_hash: state.startHash
        })
        .catch(() => {})

      if (msg.data.code === 0 && msg.data.data.list.length > 0) {
        // 重新格式数据
        msg.data.data.list.forEach(n => {
          n.msg = decryptoMsg(n.msg)
          let member = msg.data.data.userMap[n.from]
          dList.push({
            name: member ? member.nick_name : 'unknow',
            content: n.msg,
            userId: n.from,
            timestamp: n.create_time_int,
            avatar: member.cover_photo || '',
            hash: n.hash,
            type: n.from == rootState.userId ? 'me' : 'you',
            msg_type: n.msg_type,
            ext: n.ext ? n.ext : null
          })
        })

        // 保存到本地缓存中
        if (state.useCache) {
          localStorage.setItem(params.hash, JSON.stringify(dList))
        }
      }
    }

    if (dList.length > 0) {
      commit('setHash', {
        startHash: dList[0].hash
      })

      commit('addHistoryList', dList)

      status = 'done'
    } else {
      commit('setHash', {
        startHash: null
      })

      status = 'end'
    }

    return status
  },
  /**
   * 发送群聊消息
   * @param {Object} data
   * @param {Object} params
   */
  doSendMsg ({ dispatch, commit, state }, params = {}) {
    return new Promise((resolve, reject) => {
      API.group.sendMsg({
        group_id: state.groupId,
        msg_type: params.type,
        msg: params.msg
      }).then(({ data }) => {
        if (data.code === 0) {
          if (params.createTime) {
            let createTime = params.createTime
            data.data.content = decryptoMsg(data.data.content)
            let list = state.chatList
            for (let i = list.length - 1; i >= 0; i--) {
              let listItem = list[i]
              if (listItem.createTime === createTime) {
                commit('updataChatItem', {
                  index: i,
                  hash: data.data.hash
                })
              }
            }
          } else {
            // 针对用户第一次发言
            commit('updateMembers', data.data.userMap)
            data.data.content = decryptoMsg(data.data.content)
            commit('addChatItem', data.data)
          }
          commit('setHash', {
            endHash: data.data.hash
          })
          commit('updateSessionLastMsgNoDecode', Object.assign(data.data, { group_id: state.groupId }))
          resolve(data.data)
        } else {
          if (params.createTime) {
            dealErrorMsg(state, params.createTime)
          }
        }
      }).catch(err => {
        if (params.createTime) {
          dealErrorMsg(state, params.createTime)
        }
        reject(err)
      })
    })
  },
  /**
   * 发送聊天文件
   * @param {Object} data
   * @param {Object} params
   */
  async doSendFile ({ dispatch, commit, state, rootState }, params = {}) {
    return new Promise((resolve, reject) => {
      let userId = rootState.userId
      let token = rootState.token

      let formData = new FormData()
      formData.append('res', params.res)
      formData.append('user_id', userId)
      formData.append('token', token)

      // 私聊群聊参数调整
      if (state.groupId) {
        formData.append('group_id', state.groupId)
      } else {
        let arr = rootState.curSession.split('-')
        let toUser

        if (arr[0] == rootState.userId) toUser = arr[1]
        else toUser = arr[0]

        formData.append('to_user', toUser)
      }

      let sendUrl = state.groupId ? 'group/sendFile' : 'person/sendFile'
      axios({
        url: [API.host, sendUrl].join(''),
        method: 'post',
        data: formData,
        headers: { 'Content-Type': 'multipart/form-data' }
      })
        .then(({ data }) => {
          if (data.code === 0) {
            if (params.createTime) {
              let createTime = params.createTime
              data.data.content = decryptoMsg(data.data.content)
              let list = state.chatList
              list.forEach(item => {
                if (item.createTime === createTime) {
                  item.res = undefined
                  item.content = data.data.content
                  item.hash = data.data.hash
                  item.loading = false
                  item.fail = false

                  if (!item.ext_info) item.ext_info = {}
                  item.ext_info.cover_url = data.data.ext_info && data.data.ext_info.cover_url
                }
              })
            } else {
              // 针对用户第一次发言
              commit('updateMembers', data.data.userMap)
              data.data.content = decryptoMsg(data.data.content)
              commit('addChatItem', data.data)
            }

            commit('setHash', {
              endHash: data.data.hash
            })
            commit('updateSessionLastMsgNoDecode', Object.assign(data.data, { group_id: state.groupId || rootState.curSession }))
            resolve(data.data)
          } else {
            if (params.createTime) {
              dealErrorMsg(state, params.createTime)
            }
          }
        })
        .catch(err => {
          if (params.createTime) {
            dealErrorMsg(state, params.createTime)
          }
          reject(err)
        })
    })
  },
  /**
   * 发送私聊消息
   * @param {Object} data
   * @param {Object} params
   */
  doSendPrivateMsg ({ dispatch, commit, state, rootState }, params = {}) {
    return new Promise((resolve, reject) => {
      API.person.sendMsg({
        session_id: rootState.curSession,
        msg_type: params.type,
        msg: params.msg
      }).then(({ data }) => {
        if (data.code === 0) {
          if (params.createTime) {
            let createTime = params.createTime
            data.data.content = decryptoMsg(data.data.content)
            let list = state.chatList
            for (let i = list.length - 1; i >= 0; i--) {
              let listItem = list[i]
              if (listItem.createTime === createTime) {
                listItem.hash = data.data.hash
                listItem.loading = false
              }
            }
          } else {
            // 针对用户第一次发言
            commit('updateMembers', data.data.userMap)
            data.data.content = decryptoMsg(data.data.content)
            commit('addChatItem', data.data)
          }
          commit('setHash', {
            endHash: data.data.hash
          })
          commit('updateSessionLastMsgNoDecode', Object.assign(data.data, { group_id: rootState.curSession }))
          resolve(data.data)
        } else {
          if (params.createTime) {
            dealErrorMsg(state, params.createTime)
          }
        }
      }).catch(err => {
        if (params.createTime) {
          dealErrorMsg(state, params.createTime)
        }
        reject(err)
      })
    })
  },
  /**
   * 链接websocket
   * @param {Object} data
   * @param {Object} params
   */
  initSocket ({ commit, state, rootState, rootGetters, dispatch }, params = {}) {
    if (!window.WebSocket) {
      console.error('Error: WebSocket is not supported .')
      return
    }

    let host = `${getWsUrl()}/?user_id=${rootState.userId}&token=${
      rootState.token
    }`
    if (socket) {
      socket.destroy()
      socket = null
    }

    socket = new WsManager(host, {
      autoConnect: true, // 自动连接
      reconnection: true, // 断开自动重连
      reconnectionDelay: 5000, // 重连间隔时间，单位秒
      keepAliveContent: JSON.stringify({ act: 'alive', player: name }) // 心跳包内容
    })

    socket.on('open', res => {})

    socket.on('message', e => {
      let _data = JSON.parse(e)
      let channel = _data.channel
      let data = _data.data
      let muteList = rootGetters.muteList // 免打扰列表

      // 群聊
      if (channel.match('chat:group')) {
        let isMute = muteList.some(v => {
          return v.session_id == data.group_id
        })
        if (data.type === 'msg') {
          if (rootState.curSession == data.group_id) {
            // 当前会话需要加载新消息
            dispatch('getNewMsg', { newMsg: true })

            if (data.from != rootState.userId) commit('addUnreadNums')
          }

          if (!isMute) {
            noticeManager.showNotification(data)
          }
        }
        if (data.type === 'update') {
        }
        if (data.type === 'add_admin') {
        }
        if (data.type === 'remove_admin') {
        }
        if (data.type === 'repeal') {
          commit('repealChatItem', data)
          // 左侧会话
          data.msg_type = -1
          commit('updateSessionLastmsg', data)
        }
        if (data.type === 'block') {
          commit('updateGroupBlockList', {
            type: 'add',
            id: data.to
          })
        }
        if (data.type === 'unblock') {
          commit('updateGroupBlockList', {
            type: 'delete',
            id: data.to
          })
        }

        if (data.type === 'leave') {
          if (data.user_info.user_id == rootState.userId) return

          data.joinMsg = (data.user_info.nick_name || data.user_info.name) + '退出群组'
          commit('addChatItem', data)

          // 本人退出刷新群信息
          if (data.user_id == rootState.userId) {
            dispatch('getGroupInfo')
          } else {
            commit('updateMembersArray', {
              type: 'del',
              userInfo: data.user_info
            })
          }
        }

        if (data.type === 'join') {
          if (data.user_info.user_id == rootState.userId) return

          data.joinMsg = (data.user_info.nick_name || data.user_info.name) + '加入群组'

          commit('updateMembers', {
            [data.user_info.user_id]: data.user_info
          })
          commit('updateMembersArray', {
            type: 'add',
            userInfo: data.user_info
          })
          commit('addChatItem', data)
        }

        if (data.type === 'pin_msg') {
          commit('updateGroupPinMsg', data.pinMsg)
        }

        if (data.type === 'unpin_msg') {
          commit('updateGroupPinMsg', null)
        }

        if (data.type === 'new_redpack' && rootState.curSession == data.group_id) {
          commit('addPacketItem', data)
        }

        if (data.type === 'grab_redpack' && rootState.curSession == data.group_id) {
          if (data.from == rootState.userId || data.to == rootState.userId) {
            commit('addPacketTip', data)
          }
        }
      }

      // 私聊
      if (channel.match('chat:person')) {
        if (!rootState.curSession) return
        let curId = +data.to > +data.from ? `${data.from}-${data.to}` : `${data.to}-${data.from}`
        let isMute = muteList.some(v => {
          return v.session_id == curId
        })
        if (data.type === 'msg') {
          if (rootState.curSession == curId) {
            // 当前会话需要加载新消息
            dispatch('getPrivateNewMsg')

            if (data.from != rootState.userId) commit('addUnreadNums')
          }

          // 如果在隐藏tab就需要 通知
          if (!isMute) {
            noticeManager.showNotification(data)
          }
        }
        if (data.type === 'repeal') {
          commit('repealChatItem', data)
          let sessionId = data.from > data.to ? `${data.to}-${data.from}` : `${data.from}-${data.to}`
          data.group_id = sessionId
          data.msg_type = -1
          commit('updateSessionLastmsg', data)
        }
        // if (data.type === 'new_redpack' && rootGetters.otherUserId == data.from) {
        if (data.type === 'new_redpack') {
          commit('addPacketItem', data)
        }
        if (data.type === 'grab_redpack' && rootGetters.otherUserId == data.from) {
          if (data.from == rootState.userId || data.to == rootState.userId) {
            commit('addPacketTip', data)
          }
        }

        if (data.type === 'join_group') {
          data.joinMsg = '你加入了该群组'
          commit('updateMembers', {
            [rootState.userInfo.user_id]: rootState.userInfo
          })
          commit('updateMembersArray', {
            type: 'add',
            userInfo: rootState.userInfo
          })
          commit('addChatItem', data)
        }

        if (data.type === 'leave_group') {
          data.joinMsg = '你退出了该群组'
          commit('updateMembersArray', {
            type: 'del',
            userInfo: rootState.userInfo
          })
          commit('addChatItem', data)
          dispatch('getGroupInfo')
        }
      }

      // 有新session 更新sessionList
      if (data.type === 'msg' || data.type === 'new_redpack') {
        let sessionList = rootState.chat.sessionList
        let curId
        if (data.group_id) {
          curId = data.group_id
        } else {
          curId = +data.to > +data.from ? `${data.from}-${data.to}` : `${data.to}-${data.from}`
        }
        let isInSession = sessionList.some(v => {
          return v.session_id == curId
        })

        let baseObj = {
          session_id: curId,
          cont: decryptoMsg(data.content),
          unread: rootState.userId == data.from ? 0 : 1,
          update_time_int: data.timestamp,
          timestamp: data.timestamp
        }

        if (!isInSession) {
          if (!data.group_id) {
            // 私聊要拿对方的头像
            API.user.getOtherInfo({
              target_id: rootState.userId === data.from ? data.to : data.from
            }).then(({ data }) => {
              let obj = {
                cover_photo: data.data.cover_photo,
                is_group: '0',
                name: data.data.nick_name
              }
              commit('addSessionItem', Object.assign(obj, baseObj))
            })
          } else {
            API.group.getGroupInfo({
              group_id: data.group_id
            }).then(({ data }) => {
              let group = data.data.group
              let obj = {
                cover_photo: group.cover_photo,
                is_group: '1',
                is_auth: group.is_auth,
                name: group.group_title
              }
              commit('addSessionItem', Object.assign(obj, baseObj))
            })
          }
        }

        if (data.from != rootState.userId) {
          commit('setSessionItemUnread', Object.assign({ curSession: rootState.curSession }, baseObj))
        }
        commit('updateSessionLastmsg', Object.assign(data, { sessionId: curId }))
      }
    })
  },
  /**
   * 撤回消息
   * @param {Object} params
   * {index:number, session_id:string, hash:string}
   */
  async doRepealGroupMsg ({ dispatch, commit, state }, params = {}) {
    try {
      await API.group.repealGroupMsg({
        group_id: state.groupId,
        hash: params.hash
      })
    } catch (error) {}
  },
  /**
   * 封禁群用户
   */
  async doBlockUser ({ state }, params = {}) {
    try {
      await API.group.blockUser({
        group_id: state.groupId,
        block_id: params.id
      })
    } catch (error) {}
  },
  /**
   * 解禁用户
   */
  async doUnBlockUser ({ state }, params = {}) {
    try {
      await API.group.unblockUser({
        group_id: state.groupId,
        block_id: params.id
      })
    } catch (error) {}
  },
  /**
   * 更新置顶
   */
  async doPinMsg ({ state }, params = {}) {
    try {
      await API.group.pinMsg({
        group_id: state.groupId,
        hash: params.hash
      })
    } catch (error) {}
  },
  /**
   * 取消置顶
   */
  async doUnpinMsg ({ state }, params = {}) {
    try {
      await API.group.unpinMsg({
        group_id: state.groupId,
        hash: params.hash
      })
    } catch (error) {}
  },
  /**
   * 加入群组
   */
  async joinGroup ({ state, commit }, params = {}) {
    try {
      await API.group.joinGroup({
        group_id: state.groupId
      })
      commit('updateJoin', true)
      commit('changeHotGroupStatus', {
        groupId: state.groupId,
        isJoin: 1
      })
    } catch (error) {}
  }
}

export default actions
