<template>
  <div class="box-ft">
    <chat-at
      ref="chatAt"
      v-if="atShow"
      @atperson="atPerson"
      :curInd="atInd"
      :filterList="filterMembers">
    </chat-at>
    <div class="input-ctrl" v-if="showLoginBtn">
      <span v-if="showLoginBtn === 'loading'">{{ $t('mini.logining') }}</span>
      <span v-else class="enable" @click="handleLogin">{{ $t('mini.login') }}</span>
    </div>
    <div class="input-con" v-else>
      <div class="more-icon" @click.stop="handleMoreClick"></div>
      <form class="input-wrap" @submit="handleSend">
        <textarea
          @keydown.up="handleUp"
          @keydown.down="handleDown"
          @keydown.left="handleLeft"
          @keydown.right="handleRight"
          @keydown.delete="handleDel"
          @keydown.esc="handleEsc"
          cols="1"
          ref="chatInput"
          rows="1"
          @keydown.enter="handleKeyDown"
          placeholder="Write a message"
          v-model="inputMsg"
          @focus="handleFocus"
          @blur="handleBlur"
          :style="{height:inputHeight}"
        />
      </form>
      <div class="emoji-icon" @click.stop="handleEmojiClick"></div>
      <div class="btn-send" @click="handleSend">{{ $t('chat.send') }}</div>
    </div>

    <toolbar ref="toolbar" :toolShow="toolShow" @handleFile="handleFile"></toolbar>

    <emoji @addEmoji="addEmoji" :emojiShow="showEmoji" v-show="showEmoji" @closeEmojiList="closeEmojiList"></emoji>
  </div>
</template>

<script>
import emoji from '@/components/emoji'
import chatAt from '@/components/chatAt'
import toolbar from '@/components/chatInput/toolbar'
import { mapActions, mapState, mapMutations } from 'vuex'
import { Message } from 'element-ui'
import ImageMin from '@/util/imageMin.js'
import { chatAtMixin, chatInputMixin, changeLangMixin } from '@/mixins'
import { accountLoginMixin } from '@/mixins/login'
import { emojiList } from '@/util/emoji'

export default {
  name: 'chatMini',
  mixins: [accountLoginMixin, chatAtMixin, chatInputMixin, changeLangMixin],
  components: {
    emoji,
    chatAt,
    toolbar
  },
  props: {
    groupId: [Number, String],
    showLoginBtn: [Boolean, String] // 显示登录按钮
  },
  computed: {
    ...mapState([
      'account',
      'group',
      'userId',
      'userInfo'
    ]),
    ...mapState({
      chatInputFocus: state => state.group.chatInputFocus,
      blockList: state => state.group.blockList,
      pinMsg: state => state.group.pinMsg,
      atList: state => state.group.atList,
      chatList: state => state.group.chatList,
      unreadNums: state => state.group.unreadNums,
      sessionList: state => state.chat.sessionList
    }),
    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
    },
    linkToCreator () {
      let { creator, userId } = this.group
      let sessionId = creator > userId ? `${userId}-${creator}` : `${creator}-${userId}`
      return `${location.origin}/#/pm/${sessionId}`
    },
    isAdmin () {
      return (this.group.adminList && this.group.adminList.some(id => id == this.userId)) || this.group.creator == this.userId
    }
  },
  data () {
    return {
      showEmoji: false, // 显示表情选择框
      loading: false,
      inputMsg: '', // 用户输入的内容
      atInd: 0, // @人索引
      inputHeight: 18,
      toolShow: false
    }
  },
  watch: {
    inputMsg (val, newval) {
      let ele = this.$refs.chatInput
      this.inputHeight = 'auto'

      this.$nextTick(() => {
        this.inputHeight = Math.max(18, Math.min(ele.scrollHeight, 75)) + 'px'
      })
    },
    chatInputFocus (val, newval) {
      if (this.showLoginBtn) return
      let ele = this.$refs.chatInput
      if (val) {
        if (document.activeElement !== ele) {
          this.placeEnd(ele)
          ele.focus()
        }
      } else {
        if (document.activeElement === ele) {
          ele.blur()
        }
      }
    }
  },
  async mounted () {
    document.body.addEventListener('click', () => {
      this.showEmoji = false
      this.toolShow = false
    })
  },
  beforeDestroy () {
  },
  methods: {
    ...mapMutations([
      'addChatItem',
      'updateChatInputFocus'
    ]),
    ...mapActions([
      'doSendMsg',
      'doSendFile'
    ]),
    handleLogin () {
      this.$emit('handleLogin')
    },
    handleMoreClick () {
      this.showEmoji = false
      this.toolShow = !this.toolShow

      this.checkNeedToBottom()
    },
    handleEmojiClick () {
      this.toolShow = false
      this.showEmoji = !this.showEmoji

      this.checkNeedToBottom()
    },
    checkNeedToBottom () {
      if (!this.isBottom) return

      this.$nextTick(() => {
        this.resizeToBottom()
      })
    },
    /**
     * 聊天窗体滚动到底部
     */
    resizeToBottom () {
      this.$emit('resizeToBottom')
    },
    /**
     * @des 点击，查看未读消息
     * 直接滚动到聊天列表底部
     */
    doSetRead () {
      this.resizeToBottom()
    },
    /**
     * 添加表情
     */
    addEmoji (value) {
      this.inputMsg += value
    },
    /**
     * @des 处理消息发送
     */
    async handleSend (e) {
      // 判断是否被禁言
      if (this.blockList.some(id => id == this.userId)) {
        Message({
          message: this.$t('chat.youAreBan'),
          type: 'error'
        })
        return
      }
      // 替换emoji字符串
      let _inputMsg = this.inputMsg
      let parts = _inputMsg.match(/\["[a-z0-9A-Z_]+"\]/g)
      for (let k in parts) {
        let emoji = this.emojiMap[parts[k]]
        if (emoji) {
          _inputMsg = _inputMsg.replace(parts[k], emoji)
        }
      }
      let text = _inputMsg.trim()

      if (text.length === 0) {
        Message({
          message: this.$t('chat.cannotBeEmpty'),
          type: 'warning'
        })
        return
      }

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

      // 清空输入框
      this.inputMsg = ''

      // 用户不是第一次发言
      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

        await this.doSendMsg(opt)
      } else {
        // 发言后，才滚动底部
        await this.doSendMsg(opt)
      }

      // 滚到底部
      this.$nextTick(function () {
        this.resizeToBottom()
      })

      e.preventDefault()
      return false
    },
    placeEnd (el) {
      var range = document.createRange()
      range.selectNodeContents(el)
      range.collapse(false)
      var sel = window.getSelection()
      sel.removeAllRanges()
      sel.addRange(range)
    },
    /**
     * 文件预处理
     * @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)
        this.toolShow = false
        setTimeout(() => {
          this.$refs.toolbar.resetInput()
          this.resizeToBottom()
        }, 100)
      } catch (error) {
        Message({
          message: this.$t('chat.maxUploadTips'),
          type: 'warning'
        })
      }
    }
  }
}
</script>

<style lang="scss" scoped>
@charset "UTF-8";

$chatContBg: #eeeeee;

.box-ft{
  position: relative;
  background: $chatContBg;
  border-top: 1px solid #d6d6d6;
  .input-con{
    position: relative;
    display: flex;
    align-items: flex-end;
    background-color: #fafafa;
    padding: 6px 0;
  }
  .input-wrap{
    flex: 1;
    padding: 10px 0;
    background-color: #ffffff;
    border-radius: 4px;
  }
  .more-icon{
    width: 38px;
    height: 38px;
    background: url('../../assets/more-icon.png') center center no-repeat;
    background-size: 22px 22px;
    cursor: pointer;
    &:hover{
      opacity: .6;
    }
  }
  .emoji-icon{
    width: 38px;
    height: 38px;
    background: url('../../assets/m-face-icon.png') center center no-repeat;
    background-size: 22px 22px;
    cursor: pointer;
    &:hover{
      opacity: .6;
    }
  }
  .btn-send{
    margin-right: 4px;
    font-size: 12px;
    color: #ffffff;
    padding: 0 10px;
    height: 28px;
    line-height: 28px;
    margin-bottom: 3px;
    background: #2b9ff6;
    border-radius: 3px;
    cursor: pointer;
    &:hover{
      opacity: 0.8;
    }
  }
  form{
    @include flex(1);
  }
  textarea {
    display: block;
    width: 100%;
    height: 18px;
    max-height: 175px;
    font-size: 14px;
    color: #000000;
    line-height: 16px;
    padding: 1px;
    padding-left: 8px;
    margin: 0;
    border: none;
    outline: none;
    background: none;
    box-sizing: border-box;
    resize:  none;
  }
  .input-ctrl{
    span{
      width: 120px;
      margin: 4px auto;
      height: 30px;
      line-height: 30px;
      color: #ffffff;
      font-size: 12px;
      text-align: center;
      display: block;
      background-image: -webkit-linear-gradient( 90deg, rgb(25,145,235) 0%, rgb(46,161,248) 100%);
      border-radius: 3px;
      &.enable{
        cursor: pointer;
        &:hover{
          opacity: 0.7;
        }
      }
    }
  }
}
</style>
