import API from '@/api'
import { getWsUrl } from '@/util/contract.js'
import WsManager from '@/util/wsManager.js'
import Vue from 'vue'
import {
  addSomeInArray,
  addTimeMsgInItem,
  decryptoMsg,
  addLinkItem,
  removeItemIfEixt,
  formatPinMsg,
  dealErrorMsg
} from '@/util/util.js'
import axios from 'axios'

var socket = null // websocket实例

const group = {
  state: {
    useCache: false, // 是否使用缓存
    adminList: [], // 管理员列表
    blockList: [], // 禁言小分队
    userCounts: '', // 当前房间用户数
    groupName: '', // 当前房间名称
    groupNotice: '', // 群公告
    privateName: '', // 私聊人名称
    coverPhoto: '', // 群头像
    inviteUrl: '', // 邀请链接
    sessionInfo: {}, // 群设置
    groupId: '', // 当前房间ID
    members: {}, // 当前房间用户列表
    userId: '', // 当前用户ID
    pinList: [], // 当前置顶列表
    chatList: [], // 聊天数据列表
    startHash: '', // 当前储存消息列表开始的hash
    endHash: '', // 当前储存消息列表结束的hash
    userInfo: {}, // 用户群角色信息
    unreadNums: 0, // 用户未读消息数
    chatInputFocus: false, // 聊天输入框聚焦
    pinMsg: {} // 置顶消息
  },
  mutations: {
    initGroup (state, data) {
      state.userId = data.userId
      state.groupId = data.groupId
      state.useCache = data.useCache
    },
    initState (state, data) {
      state.endHash = ''
      state.startHash = ''
      state.chatList = []
      state.pinList = []
      state.atList = []
      state.unreadNums = 0
      state.userId = data
    },
    setGroupInfo (state, data) {
      state.groupName = data.groupName
      state.userCounts = data.userCounts
      state.userInfo = data.userInfo
      state.members = data.members
      state.groupNotice = data.groupNotice
      state.inviteUrl = data.inviteUrl
      state.sessionInfo = data.sessionInfo
      state.coverPhoto = data.coverPhoto
      state.adminList = data.adminList
      state.blockList = data.blockList
      if (data.pinMsg) {
        formatPinMsg(data.pinMsg, state.userId)
        state.pinList.push(data.pinMsg)
        removeItemIfEixt(state.pinList, state.chatList, item => item.hash)
      }
      state.pinMsg = data.pinMsg || {}
    },
    addHistoryList (state, data) {
      if (data.length) {
        addSomeInArray(data)
        removeItemIfEixt(state.pinList, data, item => item.hash)
        state.chatList = data.concat(state.chatList)
      }
    },
    addChatItem (state, data) {
      if (data && data.length > 0) {
        addSomeInArray(data)
        removeItemIfEixt(state.pinList, data, item => item.hash)
        state.chatList = state.chatList.concat(data)
      } else {
        let item = {
          name: state.members[data.from]
            ? state.members[data.from].nick_name
            : 'unknown',
          content: data.content,
          userId: data.from,
          timestamp: data.timestamp,
          avatar: state.members[data.from] ? state.members[data.from].cover_photo : '',
          hash: data.hash,
          type: data.from === state.userId ? 'me' : 'you',
          msg_type: data.msg_type,
          loading: Boolean(data.loading),
          res: data.res,
          fail: false
        }
        // 针对自己发送的情况
        if (data.createTime) {
          item.createTime = data.createTime
        }

        addTimeMsgInItem(item, state.chatList)
        addLinkItem(item)
        state.chatList.push(item)
      }
    },
    addPacketItem (state, data) {
      let item = {
        name: state.members[data.from]
          ? state.members[data.from].nick_name
          : 'unknown',
        timestamp: data.timestamp,
        avatar: state.members[data.from] ? state.members[data.from].cover_photo : '',
        userId: data.from,
        msg_type: data.type === 'new_redpack' ? 4 : 5,
        content: JSON.parse(decryptoMsg(data.content)),
        type: data.from === state.userId ? 'me' : 'you',
        ext: { grabbed: 0, redpack_status: 0 },
        hash: data.hash
      }
      addTimeMsgInItem(item, state.chatList)
      state.chatList.push(item)
      state.endHash = data.hash
    },
    addPacketTip (state, data) {
      let item = {
        trxId: data.content.redpack_trx_id,
        from: data.from,
        to: data.to,
        redPackTip: true
      }
      state.chatList.push(item)
    },
    unpdatePacketItem (state, { type, trxId, data }) {
      let list = state.chatList
      let ind = list.findIndex(e => {
        return e.msg_type == 4 && e.content.trxId == trxId
      })
      let item = list[ind]
      item.ext[type] = data
      Vue.set(state.chatList, ind, item)
    },
    reSendChatItem (state, data) {
      let chatList = state.chatList

      chatList.forEach(item => {
        if (item.createTime == data.createTime) {
          item.loading = true
          item.fail = false
        }
      })
    },
    /**
     * 撤回消息，设置消息数据为{ repealMsg: true }
     * @param {state} state
     * @param {Object|Number} data
     */
    repealChatItem (state, data) {
      let { pinList, chatList } = state
      for (let i = chatList.length - 1; i >= 0; i--) {
        let item = chatList[i]
        if (item.hash === data.hash) {
          Vue.set(item, 'repealMsg', true)
          Vue.set(item, 'from', data.from)
        }
      }

      if (pinList.length) {
        removeItemIfEixt(pinList, [data], item => item.hash)
      }
    },

    deleteChatItem (state, hash) {
      let index = state.chatList.findIndex(item => item.hash === hash)
      state.chatList.splice(index, index)
    },

    addUnreadNums (state) {
      state.unreadNums++
    },

    resetUnreadNums (state) {
      state.unreadNums = 0
    },

    setHash (state, data) {
      if (data.startHash) {
        state.startHash = data.startHash
      }
      if (data.endHash) {
        state.endHash = data.endHash
      }
    },
    /**
     * @des 更新置顶
     */
    updatePin (state, data) {
      state.sessionInfo.is_pin = data
    },
    /**
     * @des 更新免打扰
     */
    updateMute (state, data) {
      state.sessionInfo.is_mute = data
    },
    /**
     * @des 更新群信息
     */
    updateGroup (state, { key, data }) {
      state[key] = data
    },
    updateMembers (state, data) {
      state.members = Object.assign({}, state.members, data)
    },
    /**
     * @des 更新members里自己的头像
     */
    updateMemberAvatar (state, { userId, imageUrl }) {
      let members = state.members
      let chatList = state.chatList

      for (let i = 0; i < chatList.length; i++) {
        let id = chatList[i]['userId']
        if (id === userId) {
          let item = chatList[i]
          item['avatar'] = imageUrl
          Vue.set(state.chatList, i, item)
        }
      }
      for (let k in members) {
        if (k === userId) {
          let item = members[k]
          item['cover_photo'] = imageUrl
          Vue.set(state.members, k, item)
          return
        }
      }
    },
    /**
     * @des 更新members里自己的名字
     */
    updateMemberNickName (state, { userId, nickName }) {
      let members = state.members
      let chatList = state.chatList

      for (let i = 0; i < chatList.length; i++) {
        let id = chatList[i]['userId']
        if (id === userId) {
          let item = chatList[i]
          item['name'] = nickName
          Vue.set(state.chatList, i, item)
        }
      }
      for (let k in members) {
        if (k === userId) {
          let item = members[k]
          item['nick_name'] = nickName
          Vue.set(state.members, k, item)
          return
        }
      }
    },

    /**
     * @des 更新聊天输入框聚焦状态
     */
    updateChatInputFocus (state, focus) {
      state.chatInputFocus = focus
    },
    /**
     * @des 更新群组封禁人员列表
     * @param {String} param.type [delete,add]
     * @param {String} param.id
     */
    updateGroupBlockList (state, param) {
      let { type, id } = param
      if (type === 'delete') {
        let index = state.blockList.findIndex(uid => uid == id)
        index !== -1 && state.blockList.splice(index, 1)
      } else if (type === 'add') {
        state.blockList.push(id)
      }
    },
    /**
     *
     * @param {Object|Null} param
     */
    updateGroupPinMsg (state, param) {
      if (param) {
        param.visible = true
        formatPinMsg(param, state.userId)
        state.pinMsg = param
      } else {
        state.pinMsg = {}
        state.pinList = []
      }
    }
  },
  actions: {
    /**
     * @des 获取群基础信息
     * @param {Object} store
     * @param {Object} params
     */
    async getGroupInfo ({ dispatch, commit, state }, params) {
      let info = await API.group
        .getGroupInfo({ group_id: state.groupId })
        .catch(() => {})
      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 userInfo = info.data.data.userInfo
        let sessionInfo = info.data.data.sessionInfo
        pinMsg && (pinMsg.visible = true)
        let _members = {}
        members.forEach(n => {
          _members[n.user_id] = n
        })
        commit('setGroupInfo', {
          userCounts: members.length,
          groupName: group.group_title,
          members: _members,
          userInfo,
          groupNotice: group.group_notice,
          inviteUrl: group.invite_url,
          sessionInfo,
          coverPhoto: group.cover_photo,
          adminList: adminList,
          blockList: blockList,
          pinMsg: pinMsg
        })
      }
    },

    /**
     * @des 群聊 获取最新消息【不需要登录】
     * @param {Object} store
     * @param {Object} params
     */
    async getNewMsg ({ dispatch, commit, state }, params = {}) {
      let msg = await API.group
        .getNewMsg({
          group_id: state.groupId,
          client_hash: state.endHash
        })
        .catch(() => {})

      if (msg.data.code === 0 && msg.data.data.list.length > 0) {
        let list = []
        msg.data.data.list.forEach(n => {
          let member = msg.data.data.userMap[n.from]
          if (!member) return
          list.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.chatList.length) {
          commit('setHash', {
            endHash: list[list.length - 1].hash
          })
        } else {
          commit('setHash', {
            endHash: list[list.length - 1].hash,
            startHash: list[0].hash
          })
        }

        commit('addChatItem', list)
      }
      return 'done'
    },
    /**
     * @des 私聊 获取最新消息【不需要登录】
     * @param {Object} store
     * @param {Object} params
     */
    async getPrivateNewMsg ({ dispatch, commit, state, rootState }, params = {}) {
      let msg = await API.person
        .getNewMsg({
          session_id: rootState.curSession,
          client_hash: state.endHash
        })
        .catch(() => {})
      // 有聊天记录
      if (msg.data.code === 0 && msg.data.data.list.length > 0) {
        let list = []
        // 更新members信息
        let members = msg.data.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']
            })
          }
        }

        msg.data.data.list.forEach(n => {
          let member = msg.data.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
          })
        })

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

        commit('addChatItem', list)
      }
      return 'done'
    },
    /**
     * @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.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]
            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: params.hash
          })
          .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) {
                    listItem.hash = data.data.hash
                    listItem.loading = false
                  }
                }
              } else {
                // 针对用户第一次发言
                commit('updateMembers', data.data.userMap)
                commit('addChatItem', data.data)
              }
              commit('setHash', {
                endHash: data.data.hash
              })
              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('group_id', state.groupId)
        formData.append('res', params.res)
        formData.append('user_id', userId)
        formData.append('token', token)

        axios({
          url: API.host + 'group/sendFile',
          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
                  }
                })
              } else {
                // 针对用户第一次发言
                commit('updateMembers', data.data.userMap)
                commit('addChatItem', data.data)
              }

              commit('setHash', {
                endHash: data.data.hash
              })

              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, 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) {
              commit('addChatItem', data.data)
              resolve(data.data)
            }
          })
          .catch(err => reject(err))
      })
    },
    doUploadFile ({ dispatch, commit, state }, params = {}) {
      API.session.fileUpload({
        name: 'res'
      })
    },
    /**
     * 链接websocket
     * @param {Object} data
     * @param {Object} params
     */
    initSocket ({ commit, rootState, 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
        // 群聊
        if (channel.match('chat:group')) {
          if (data.type === 'msg' && data.from !== rootState.userId) {
            // 用户打开当前群
            if (rootState.curSession === data.group_id) {
              dispatch('getNewMsg')
              commit('addUnreadNums')
            }
          }
          if (data.type === 'leave') {
          }
          if (data.type === 'update') {
          }
          if (data.type === 'add_admin') {
          }
          if (data.type === 'remove_admin') {
          }
          if (data.type === 'repeal') {
            commit('repealChatItem', data)
          }
          if (data.type === 'unblock') {
            commit('updateGroupBlockList', {
              type: 'delete',
              id: data.to
            })
          }

          if (data.type === 'join') {
            commit('updateMembers', data.user_info)
          }

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

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

        // 私聊
        if (channel.match('chat:person')) {
          if (data.type === 'msg') {
            // 用户打开当前聊天
            if (rootState.curSession.indexOf(data.to) > -1) {
              // commit('addChatItem', data)
              dispatch('getPrivateNewMsg')
              commit('addUnreadNums')
            }
          }
          if (data.type === 'repeal') {
            commit('repealChatItem', data.data)
          }
        }
      })
    },
    /**
     * 撤回消息
     * @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) {}
    }
  },
  getters: {}
}

export default group
