import { mapActions, mapState, mapMutations } from 'vuex'
import { scrollMsgIntoView } from '@/util/util.js'
import { emojiList } from '@/util/emoji'
import { Message } from 'element-ui'
import ImageMin from '@/util/imageMin.js'

// 聊天mixin 用于chatRoom组件
export const chatMixin = {
  watch: {
    '$route' () {
      this.bdHiden = true
      // 切换房间
      this.groupSet = false
      this.lockMore = false
      this.lockEnd = false
      this.enableScroll = false
      this.initRoom()
    },
    unreadNums (val, newval) {
      if (val > 0 && this.isBottom) {
        setTimeout(this.resizeToBottom.bind(this), 150)
      }
    },
    chatList (val) {
      let lastVal = val[val.length - 1]
      if (lastVal && lastVal.msg_type == 4) {
        // 自己发的红包自动滚动到底部
        this.$nextTick(this.resizeToBottom)
      }
    },
    isJoinGroup (val) {
      if (val == 1) setTimeout(this.resizeToBottom.bind(this), 100)
    }
  },
  data () {
    return {
      groupSet: false,
      lockMore: false,
      lockEnd: false,
      enableScroll: false, // 记录滚动条是否激活的状态
      isBottom: true,
      scrollHeight: 100, // 滚动条高度
      isScrollToView: false,
      isShowGroudMgr: false // 是否显示群管理
    }
  },
  computed: {
    ...mapState(['group', 'userId', 'userInfo', '']),
    ...mapState({
      creator: state => state.group.creator,
      isJoin: state => state.group.isJoin,
      pinMsg: state => state.group.pinMsg,
      pinList: state => state.group.pinList,
      atList: state => state.group.atList,
      unreadNums: state => state.group.unreadNums,
      chatList: state => state.group.chatList,
      members: state => state.group.members,
      sessionId: state => state.curSession,
      sessionInfo: state => state.group.sessionInfo
    }),
    isPrivate () {
      return this.$store.getters.isPrivate
    },
    isCreator () {
      return this.userId == this.creator
    },
    isJoinGroup () {
      if (this.group && this.group.groupId) {
        return this.isJoin ? 1 : 0
      } else {
        return 1
      }
    }
  },
  mounted () {
    this.initRoom()
    document.addEventListener('contextmenu', e => e.preventDefault())
  },
  methods: {
    ...mapMutations([
      'initGroup',
      'resetUnreadNums',
      'addChatItem',
      'deleteChatItem',
      'initState',
      'clearAtList',
      'curSession',
      'setSessionItemUnread'
    ]),
    ...mapActions([
      'getGroupInfo',
      'getUserInfo',
      'getNewMsg',
      'getHistoryMsg',
      'doSendMsg',
      'getPrivateNewMsg',
      'getPrivateHistoryMsg',
      'doSendPrivateMsg'
    ]),
    async initRoom () {
      if (!this.userInfo) {
        await this.getUserInfo()
      }
      this.$store.commit('changeSessionId', this.$route.params.id)
      this.initState(this.userInfo)
      if (this.isPrivate) {
        this.initPersonChat()
      } else {
        this.initGroupChat()
      }
    },
    /**
     * @des 私聊初始化处理
     */
    async initPersonChat () {
      await this.getPrivateNewMsg()

      this.$nextTick(() => {
        this.resizeToBottom()
        this.bdHiden = false
      })
    },
    /**
     * @des 聊天群初始化处理
     */
    async initGroupChat () {
      this.initGroup({
        userId: this.userId,
        groupId: this.sessionId,
        useCache: false
      })
      this.isShowGroudMgr = false

      await this.getGroupInfo()

      await this.getNewMsg()

      this.$nextTick(() => {
        this.resizeToBottom()
        this.bdHiden = false
      })
    },
    /**
     * @des 滚动事件监听
     */
    initScrollEvent () {},
    /**
     * @des 聊天窗体滚动事件处理集
     */
    async handleScroll (e) {
      // 防止切换房间时触发滚动处理
      if (!this.group.chatList.length) {
        return
      }
      // 防止滚动到置顶消息触发滚动
      if (this.isScrollToView) {
        return
      }
      // 激活滚动条
      this.enableScroll = true
      let totalHeight = this.$refs.msgWrap.offsetHeight
      let scrollTop = e.target.scrollTop

      // 差不多滚动到顶部
      if (scrollTop === 0 && !this.lockMore) {
        if (this.group.endHash !== null) {
          this.lockMore = true
          let res
          if (this.isPrivate) {
            res = await this.getPrivateHistoryMsg()
          } else {
            res = await this.getHistoryMsg()
          }
          if (res === 'end') {
            this.lockEnd = true
          } else {
            let scrollBottom = totalHeight - scrollTop
            this.$nextTick(() => {
              e.target.scrollTop =
                this.$refs.msgWrap.offsetHeight - scrollBottom
              setTimeout(() => {
                this.lockMore = false
              }, 800)
            })
          }
        }
      }

      // 滚动到底部清空未读消息状态
      if (scrollTop + e.target.offsetHeight > totalHeight) {
        this.isBottom = true
        if (this.group.unreadNums) {
          this.resetUnreadNums()
        }
      } else {
        this.isBottom = false
      }
    },
    /**
     * @des 聊天窗体滚动到底部
     */
    resizeToBottom () {
      this.$refs.scrollWrap.scrollTop = this.$refs.msgWrap.offsetHeight
      this.resetUnreadNums()
      this.isBottom = true
    },
    /**
     * @des 点击，查看未读消息
     * 直接滚动到聊天列表底部
     */
    doSetRead () {
      this.resizeToBottom()
    },
    /**
     * @des 引用某条消息
     */
    quoteMsg (msg) {
      this.$refs.inputArea.inputMsg = msg
    },
    /**
     * @des 某条消息被删除
     */
    deleteMsg (hash) {
      this.deleteChatItem(hash)
    },
    pinMsgClose () {
      this.pinMsg.visible = false
    },
    scrollToView () {
      if (this.pinList.length) {
        let node = this.$refs.msgWrap.querySelector('.msg-item')
        scrollMsgIntoView(
          this.$refs.scrollWrap,
          node.offsetTop - (this.pinMsg ? 40 : 10),
          node
        )
      } else {
        let hash = this.pinMsg.hash
        let index = this.group.chatList.findIndex(item => item.hash === hash)
        if (index >= 0) {
          let node = this.$refs.msgWrap
            .querySelectorAll('.msg-item')
            .item(index)
          scrollMsgIntoView(
            this.$refs.scrollWrap,
            node.offsetTop - (this.pinMsg ? 40 : 10),
            node
          )
        }
      }
      // 防止加载更多
      this.isScrollToView = true
      setTimeout(() => {
        this.isScrollToView = false
      }, 2000)
    },
    scrollToMsg (index) {
      let hash = this.atList[index].hash
      let eleIndex = this.group.chatList.findIndex(item => item.hash === hash)
      if (eleIndex >= 0) {
        let pinLen = this.group.pinList.length
        let node = this.$refs.msgWrap
          .querySelectorAll('.msg-item')
          .item(eleIndex + pinLen)
        scrollMsgIntoView(
          this.$refs.scrollWrap,
          node.offsetTop - (this.pinMsg ? 40 : 10),
          node
        )
      }
      this.clearAtList()
    },
    joinGroup () {
      this.$store.dispatch('joinGroup')
    },
    // 群管理
    showGroudMgr (flag) {
      this.isShowGroudMgr = flag == 1
    }
  }
}

// 聊天输入框mixin
export const inputMixin = {
  computed: {
    ...mapState(['group', 'userId', 'curSession']),
    ...mapState({
      chatInputFocus: state => state.group.chatInputFocus,
      blockList: state => state.group.blockList
    }),
    isPrivate () {
      return this.$store.getters.isPrivate
    },
    emojiMap () {
      var emojiMap = {}
      for (let i in emojiList) {
        let arr = emojiList[i]
        arr.forEach(v => {
          let names = JSON.stringify(v.names)
          let emoji = v.surrogates
          emojiMap[names] = emoji
        })
      }
      return emojiMap
    }
  },
  data () {
    return {
      emojiShow: false,
      inputMsg: '',
      atInd: 0
    }
  },
  mounted () {
    document.body.addEventListener('click', () => {
      this.emojiShow = false
    })
  },
  methods: {
    ...mapMutations(['updateChatInputFocus', 'addChatItem']),
    ...mapActions(['doSendMsg', 'doSendFile', 'doSendPrivateMsg']),
    addEmoji (val) {
      this.inputMsg += val
      this.emojiShow = false
      this.$refs.chatInput.focus()
    },
    /**
     * @des 处理消息发送
     */
    handleSend (e) {
      // 判断是否被禁言
      if (this.blockList.some(id => id == this.userId)) {
        Message({
          message: '您已被禁言',
          type: 'error'
        })
        return
      }

      // 替换emoji字符串
      let _inputMsg = this.inputMsg
      for (let k in this.emojiMap) {
        if (_inputMsg.indexOf(k) > -1) {
          let reg = new RegExp(k, 'g')
          _inputMsg = _inputMsg.replace(reg, this.emojiMap[k])
        }
      }

      let text = _inputMsg.trim()

      if (text.length === 0) {
        Message({
          message: '聊天内容不能为空',
          type: 'warning'
        })
        return
      }

      let opt = {
        type: 0,
        msg: text
      }

      // 用户不是第一次发言
      if (this.group.members[this.userId]) {
        let createTime = Date.now()
        this.addChatItem({
          from: this.userId,
          content: text,
          hash: `${createTime}`,
          timestamp: createTime,
          createTime,
          msg_type: '0',
          loading: true
        })
        opt.createTime = createTime
      }

      this.$store.commit('setSessionItemUnread', {
        session_id: this.curSession,
        unread: 0,
        curSession: this.curSession,
        cont: this.inputMsg
      })

      this.isPrivate ? this.doSendPrivateMsg(opt) : this.doSendMsg(opt)

      // 滚到底部
      this.$nextTick(function () {
        this.inputMsg = ''
        this.resizeToBottom ? this.resizeToBottom() : this.$emit('toBottom')
      })

      e.preventDefault()
      return false
    },
    /**
     * 文件预处理
     * @return {Object} data 预处理文件信息
     * @param {Number} data.type
     * @param {File} data.res
     */
    async preHandleFile (file) {
      let type = file.type
      let size = file.size
      if (type.match('video')) {
        return size > 3 * 1024 * 1024
          ? Promise.reject(new Error(file))
          : Promise.resolve({
            type: 2,
            res: file
          })
      } else if (type.match('audio')) {
        return size > 2 * 1024 * 1024
          ? Promise.reject(new Error(file))
          : Promise.resolve({
            type: 3,
            res: file
          })
      } else if (type.match('image')) {
        let image = await new ImageMin({
          file: file,
          maxSize: 1024 * 1024
        })
        return {
          type: 1,
          preview: image.base64,
          res: image.res
        }
      }
    },
    /**
     * @des 处理文件发送
     */
    async handleFile (e) {
      let inputfile
      if (e.constructor === File) {
        inputfile = e
      } else {
        inputfile = e.target.files[0]
      }

      try {
        let fileInfo = await this.preHandleFile(inputfile)
        let opt = { res: fileInfo.res }
        if (this.group.members[this.userId]) {
          let createTime = Date.now()
          this.addChatItem({
            content: fileInfo.preview || '',
            from: this.userId,
            hash: `${createTime}`,
            msg_type: fileInfo.type,
            timestamp: createTime,
            res: fileInfo.res,
            loading: true,
            createTime
          })
          opt.createTime = createTime
        }
        this.doSendFile(opt)
        setTimeout(() => {
          if (this.$refs.inputFile) {
            this.$refs.inputFile.value = null
          }
          if (this.$refs.inputFile1) {
            this.$refs.inputFile1.value = null
          }
          if (this.$refs.inputFile2) {
            this.$refs.inputFile2.value = null
          }
          if (this.$refs.inputFile3) {
            this.$refs.inputFile3.value = null
          }
          this.resizeToBottom ? this.resizeToBottom() : this.$emit('toBottom')
        }, 100)
      } catch (error) {
        Message({
          message: '上传文件大小限制：音频2M以内，视频3M以内',
          type: 'warning'
        })
      }
    }
  }
}
