<template>
  <div>
    <div class="chat-wrap" v-if="selected">
      <div class="chat-title">
        {{ selected.username || selected.name }}
      </div>
      <div class="record-warp">
        <!-- 私聊 -->
        <el-scrollbar
          v-if="tab === 'friends'"
          style="height: 95%"
          ref="myScrollbar"
        >
          <div
            class="record-list"
            v-for="(item, i) in friend_record_list"
            :key="i"
          >
            <!-- receive msg record -->
            <div class="record-item" v-if="item.toid === socket.id">
              <div class="avatar">
                <el-avatar
                  shape="square"
                  src="https://img2.baidu.com/it/u=1077360284,2857506492&fm=26&fmt=auto&gp=0.jpg"
                ></el-avatar>
              </div>
              <div class="group-record-item">
                <!-- 链接 -->
                <a
                  class="message-content-text receive-record-item"
                  v-if="_isUrl(item.msg)"
                  :href="item.msg"
                  target="_blank"
                  style="margin-left: 10px; margin-top: 15px;"
                >
                  {{ item.msg }}
                </a>
                <!-- 文本 -->
                <div
                  class="message-content-text receive-record-item"
                  v-if="item.type === 'text'"
                  v-html="_parseHtml(item.msg)"
                  style="margin-left: 10px; margin-top: 15px;"
                ></div>
                <!-- 图片 -->
                <div
                  class="message-content-image receive-record-item"
                  v-if="item.type === 'image'"
                  :style="getImageStyle(item.msg)"
                  style="margin-left: 10px; margin-top: 15px;"
                >
                  <viewer style="display: flex; align-items: center">
                    <img :src="baseUrl + item.msg" alt="" />
                  </viewer>
                </div>
                <!-- 视频格式文件 -->
                <div
                  class="message-content-image receive-record-item"
                  v-if="item.type === 'video'"
                  style="margin-left: 10px; margin-top: 15px;"
                >
                  <video
                    style="width: 255px"
                    src="https://media.w3.org/2010/05/sintel/trailer.mp4"
                    controls="controls"
                  >
                    您的浏览器不支持 video 标签。
                  </video>
                </div>
              </div>
            </div>

            <!-- self send msg record -->
            <div v-if="item.toid !== socket.id" class="record-item send-record">
              <!-- 链接 -->
              <a
                class="message-content-text"
                v-if="_isUrl(item.msg)"
                :href="item.msg"
                target="_blank"
              >
                {{ item.msg }}
              </a>
              <!-- 文本 -->
              <div
                class="message-content-text"
                v-if="item.type === 'text'"
                v-html="_parseHtml(item.msg)"
              ></div>
              <!-- 图片 -->
              <div
                class="message-content-image"
                v-if="item.type === 'image'"
                :style="getImageStyle(item.msg)"
              >
                <viewer style="display: flex; align-items: center">
                  <img :src="baseUrl + item.msg" alt="" />
                </viewer>
              </div>
              <!-- 附件类型消息 -->
              <!-- <div class="message-content-file" v-else-if="item.type === 'file'" @click="download(item)">
                <img class="message-content-icon" :src="getFileIcon(item)" alt="" />
                <div class="message-content-detail">
                  <div class="file-name">
                    {{ getFileName(item).name }}
                  </div>
                  <div class="file-size">
                    {{ getFileName(item).size }}
                  </div>
                </div>
              </div> -->
              <!-- 视频格式文件 -->
              <div class="message-content-image" v-if="item.type === 'video'">
                <video
                  style="width: 255px"
                  src="https://media.w3.org/2010/05/sintel/trailer.mp4"
                  controls="controls"
                >
                  您的浏览器不支持 video 标签。
                </video>
              </div>
              <!-- <div class="avatar">
                <el-avatar
                  shape="square"
                  src="https://img2.baidu.com/it/u=1077360284,2857506492&fm=26&fmt=auto&gp=0.jpg"
                ></el-avatar>
              </div> -->
            </div>
          </div>
        </el-scrollbar>

        <!-- 群聊 -->
        <el-scrollbar
          v-if="tab === 'groups'"
          style="height: 95%"
          ref="myScrollbar"
        >
          <div
            class="record-list"
            v-for="(item, i) in room_record_list"
            :key="i"
          >
            <!-- receive msg record -->
            <div class="record-item" v-if="item.id !== socket.id">
              <div class="avatar">
                <el-avatar
                  shape="square"
                  src="https://img2.baidu.com/it/u=1077360284,2857506492&fm=26&fmt=auto&gp=0.jpg"
                ></el-avatar>
              </div>
              <div class="group-record-item">
                <div class="username">
                  {{ item.username }}
                </div>
                <!-- 链接 -->
                <a
                  class="message-content-text receive-record-item"
                  v-if="_isUrl(item.msg)"
                  :href="item.msg"
                  target="_blank"
                >
                  {{ item.msg }}
                </a>
                <!-- 文本 -->
                <div
                  class="message-content-text receive-record-item"
                  v-if="item.type === 'text'"
                  v-html="_parseHtml(item.msg)"
                ></div>
                <!-- 图片 -->
                <div
                  class="message-content-image receive-record-item"
                  v-if="item.type === 'image'"
                  :style="getImageStyle(item.msg)"
                >
                  <viewer style="display: flex; align-items: center">
                    <img :src="baseUrl + item.msg" alt="" />
                  </viewer>
                </div>
                <!-- 附件类型消息 -->
                <!-- <div class="message-content-file" v-else-if="item.type === 'file'" @click="download(item)">
                <img class="message-content-icon" :src="getFileIcon(item)" alt="" />
                <div class="message-content-detail">
                  <div class="file-name">
                    {{ getFileName(item).name }}
                  </div>
                  <div class="file-size">
                    {{ getFileName(item).size }}
                  </div>
                </div>
              </div> -->
                <!-- 视频格式文件 -->
                <div
                  class="message-content-image receive-record-item"
                  v-if="item.type === 'video'"
                >
                  <video
                    style="width: 255px"
                    src="https://media.w3.org/2010/05/sintel/trailer.mp4"
                    controls="controls"
                  >
                    您的浏览器不支持 video 标签。
                  </video>
                </div>
              </div>
            </div>

            <!-- self send msg record -->
            <div v-if="item.id === socket.id" class="record-item send-record">
              <!-- 链接 -->
              <a
                class="message-content-text"
                v-if="_isUrl(item.msg)"
                :href="item.msg"
                target="_blank"
              >
                {{ item.msg }}
              </a>
              <!-- 文本 -->
              <div
                class="message-content-text"
                v-if="item.type === 'text'"
                v-html="_parseHtml(item.msg)"
              ></div>
              <!-- 图片 -->
              <div
                class="message-content-image"
                v-if="item.type === 'image'"
                :style="getImageStyle(item.msg)"
              >
                <viewer style="display: flex; align-items: center">
                  <img :src="baseUrl + item.msg" alt="" />
                </viewer>
              </div>
              <!-- 附件类型消息 -->
              <!-- <div class="message-content-file" v-else-if="item.type === 'file'" @click="download(item)">
                <img class="message-content-icon" :src="getFileIcon(item)" alt="" />
                <div class="message-content-detail">
                  <div class="file-name">
                    {{ getFileName(item).name }}
                  </div>
                  <div class="file-size">
                    {{ getFileName(item).size }}
                  </div>
                </div>
              </div> -->
              <!-- 视频格式文件 -->
              <div class="message-content-image" v-if="item.type === 'video'">
                <video
                  style="width: 255px"
                  src="https://media.w3.org/2010/05/sintel/trailer.mp4"
                  controls="controls"
                >
                  您的浏览器不支持 video 标签。
                </video>
              </div>
              <!-- <div class="avatar">
                <el-avatar
                  shape="square"
                  src="https://img2.baidu.com/it/u=1077360284,2857506492&fm=26&fmt=auto&gp=0.jpg"
                ></el-avatar>
              </div> -->
            </div>
          </div>
        </el-scrollbar>
      </div>
      <div class="send-msg-wrap">
        <div class="send-header">
          <div class="tools" style="margin: 10px">
            <el-popover placement="top" width="300" trigger="click">
              <Emoji @addEmoji="addEmoji" />
              <el-button
                class="iconfont open_emoji_icon"
                style="color:rgb(44,60,80)"
                type="text"
                slot="reference"
                >&#xe612;</el-button
              >
            </el-popover>
            <el-upload
              ref="upload"
              class="file-uploader"
              action="/api/upload/"
              :show-file-list="false"
              :on-success="handleSuccess"
              :before-upload="beforeUpload"
              style="display: inline"
            >
              <i
                id="upload-btn"
                class="el-icon-folder-opened"
                @click="upload"
              ></i>
            </el-upload>
            <i class="el-icon-folder-add"></i>
            <i class="el-icon-folder-opened"></i>
          </div>
        </div>
        <div class="input-box">
          <div
            id="charInput"
            @click="saveRangeLocal"
            @focus="saveRangeLocal"
            @input="saveRangeLocal"
            @keydown.enter="stopPropagation"
            @keyup.enter="sendMsg"
            class="chatframe_input_con scrollbar"
            contenteditable="true"
          ></div>
          <div class="send-footer">
            <el-button
              type="info"
              plain
              class="send-btn"
              size="small"
              @click="sendMsg"
              >发送</el-button
            >
          </div>
        </div>
      </div>
    </div>
    <div class="chat-wrap" v-if="!selected">
      <el-empty description="请选择聊天对象"></el-empty>
    </div>
  </div>
</template>

<script>
import { isUrl, parseHtml } from "@/utils/common";
import Emoji from "./Emoji.vue";
import { mapState, mapActions } from "vuex";
let emojiData = require("./../assets/emoji/emoji.json");
import request from "@/api/require";
export default {
  name: "ChatFrame",
  props: ["selected", "tab"],
  components: {
    Emoji
  },
  data() {
    return {
      baseUrl: "http://192.168.100.8:3000/",
      emojiIcon: emojiData.icon,
      inputRange: "", // 光标
      emojiPath: new Map(), // emoji表情地址map对象,
      msg: "",
      friend_record_list: [],
      room_record_list: [],
      messageType: "",
      uploadProgress: false
    };
  },
  computed: {
    ...mapState({
      self: state => state.app.user
    }),
    ...mapState({
      socket: state => state.chat.socket
    }),
    ...mapState({
      friendRecord: state => state.chat.friendRecord
    }),
    ...mapState({
      roomRecord: state => state.chat.roomRecord
    })
  },
  watch: {
    selected(newVal, o) {
      if (this.tab === "friends") {
        if (this.friendRecord[newVal.id]) {
          this.friend_record_list = this.friendRecord[newVal.id];
        } else {
          this.$store.commit("chat/set_friend_record", [newVal.id]);
          this.friend_record_list = this.friendRecord[newVal.id];
          console.log(`this.friendRecord`, this.friendRecord);
        }
      } else {
        if (this.roomRecord[newVal.id]) {
          this.room_record_list = this.roomRecord[newVal.id];
        } else {
          this.$store.commit("chat/set_room_record", newVal.id);
          this.room_record_list = this.roomRecord[newVal.id];
          console.log(
            `this.room_record_list[newVal.id]`,
            this.room_record_list
          );
        }
      }
      this.$nextTick(() => {
        document.getElementById("charInput").innerText = "";
        this.msg = "";
        this.$refs["myScrollbar"].wrap.scrollTop = this.$refs[
          "myScrollbar"
        ].wrap.scrollHeight;
      });
    }
  },
  methods: {
    handleSuccess(res, file) {
      console.log(`res`, res);
      this.imageUrl = URL.createObjectURL(file.raw);
    },
    beforeUpload(file) {
      this.uploadProgress = true;
      this.fileData = file;
      //  调用函数分割文件 我这里是分割成不超过20M的文件快
      this.fileDataList = this.createFileChunk(file, 1024 * 1024 * 20);
      console.log(`this.fileDataList`, this.fileDataList);
      // return new Promise((reslove, reject)=>{
      //   this.fileUpLoad(reslove, reject);
      // })
      let fd = new FormData();
      fd.append("filename", file);
      // upload_file(fd).then(
      request
        .upload_file(file)
        .then(res => {
          console.log(`res5555`, res);
        })
        .catch(err => {
          console.log(`err`, err);
        });
      this.$http.post(this.baseUrl + "api/upload/", fd).then(
        res => {
          if (
            file.type === "image/jpeg" ||
            file.type === "image/png" ||
            file.type === "image/gif"
          ) {
            this.messageType = "image";
            this.sendMsg(null, res.data.data);
            console.log(`res.data.data`, res.data.data);
            console.log("========is image =====");
          } else {
            this.messageType = "file";
            console.log("=========not image=========");
          }
          // this.importDataBtnText='导入成功';
          console.log(`res1111`, res);
          console.log("======success====");
        },
        res => {
          this.$message.error("文件发送失败");
          console.log("===========shibai====");
          //  this.importDataBtnText='导入失败';
          console.log(res);
        }
      );
      return false;
    },
    submitUpload() {
      this.$refs.upload.submit();
    },

    /**
     * 文本转译/校验
     * @params text
     */
    _parseHtml(text) {
      const regex2 = /!!\[(.+?)\]!!/g;
      const codeList = text.match(regex2);
      let html = text;
      if (codeList) {
        codeList.map(item => {
          const code = item.match(/\[(.+?)\]/g)[0];
          html = html.replace(
            item,
            "<img style='width: 20px; height: 20px;vertical-align: sub;' src='" +
              this.getIconPic(code) +
              "' unicode = '" +
              code +
              "' alt='' >"
          );
        });
      }
      return parseHtml(html);
    },

    /**
     * 是否URL
     * @params text
     */
    _isUrl(text) {
      return isUrl(text);
    },

    // // 初始化上传接口的函数，再上面上传之前调用的
    // fileUpLoad(reslove, reject) {
    //   const paramsData = {
    //     multipartUpload: true, // 是否是文件分步，分块上传
    //     name: this.fileData.name,
    //     size: this.fileData.size,
    //   }
    //   initFileUpload(paramsData).then(res => {
    //     const uploadUrl = res.data.data.uploadUrl
    //     const completeMultipartUrl = res.data.data.completeMultipartUrl
    //     // 文件上传的请求地址
    //      this.uploadUrl = uploadUrl
    //     // 合并文件上传的请求地址
    //     this.completeMultipartUrl = completeMultipartUrl
    //     reslove();
    //   }).catch((err)=>{
    //     reject(err)
    //   })
    // },
    // 文件分割的方法
    createFileChunk(file, size = chunkSize) {
      const fileChunkList = [];
      let count = 0;
      let num = 1;
      while (count < file.size) {
        fileChunkList.push({
          file: file.slice(count, count + size),
          partNumber: num
        });
        count += size;
        num++;
      }
      return fileChunkList;
    },
    /**
     * 根据图片url设置图片框宽高, 注意是图片框
     */
    getImageStyle(src) {
      const arr = src.split("$");
      let width = Number(arr[2]);
      let height = Number(arr[3]);
      if (this.mobile) {
        // 如果是移动端,图片最大宽度138, 返回值加12是因为设置的是图片框的宽高要加入padding值
        if (width > 138) {
          height = (height * 138) / width;
          width = 138;
          return {
            width: `${width + 12}px`,
            height: `${height + 12}px`
          };
        }
      }
      return {
        width: `${width + 12}px`,
        height: `${height + 12}px`
      };
    },

    /**
     * 是否URL
     * @params text
     */
    _isUrl(text) {
      return isUrl(text);
    },

    upload() {},

    // 添加表情, 到输入框
    addEmoji(code) {
      let inputNode = document.getElementById("charInput");
      let html =
        "<img style='width: 20px; height: 20px;vertical-align: sub;' src='" +
        this.getIconPic(code) +
        "' unicode = '" +
        code +
        "' alt='' >";
      let sel = window.getSelection();
      let range = this.inputRange;
      let el = document.createElement("div");
      let frag = document.createDocumentFragment(),
        node,
        lastNode;

      if (!inputNode) {
        return;
      }

      if (!range) {
        inputNode.focus();
        range = window.getSelection().getRangeAt(0);
      }

      range.deleteContents();
      el.innerHTML = html;

      while ((node = el.firstChild)) {
        lastNode = frag.appendChild(node);
      }
      range.insertNode(frag);

      if (lastNode) {
        range = range.cloneRange();
        range.setStartAfter(lastNode);
        range.collapse(true);
        sel.removeAllRanges();
        sel.addRange(range);
      }
    },

    // 初始化emoji的map对象
    initEmojiPic() {
      let map = new Map();

      for (const key in emojiData.icon) {
        emojiData.icon[key].forEach(item => {
          map.set(
            item.unicode,
            require("./../assets/emoji/icon/" + item.unicode + ".png")
          );
        });
      }

      this.emojiPath = map;
    },
    // 通过Unicode码从map中获取emoji
    getIconPic(unicode) {
      return this.emojiPath.get(unicode);
    },

    // ===============================================================
    // 将输入框中的图片替换为emoji表情
    formatInputCon() {
      let inputValue = document.getElementById("charInput").innerHTML;

      inputValue = inputValue.replace(/<img.*?(?:>|\/>)/gi, val => {
        let unicode =
          "!!" + val.match(/unicode=[\'\"]?([^\'\"]*)[\'\"]?/i)[1] + "!!";

        return unicode;
      });

      return inputValue;
    },

    // 将emoji表情转换为图片
    changeEmojiCon(str) {
      let patt = /[\ud800-\udbff][\udc00-\udfff]/g; // 检测utf16字符正则

      str = str.replace(patt, char => {
        let H, L, code;

        if (char.length === 2) {
          H = char.charCodeAt(0); // 取出高位
          L = char.charCodeAt(1); // 取出低位
          code = (H - 0xd800) * 0x400 + 0x10000 + L - 0xdc00; // 转换算法
          return "&#" + code + ";";
        } else {
          return char;
        }
      });

      str = str.replace(/&#{1}[0-9]+;{1}/gi, a => {
        let unicode = a.replace(/^&#{1}/gi, "");

        unicode = unicode.replace(/;{1}$/gi, "");
        unicode =
          "U+" +
          parseFloat(unicode)
            .toString(16)
            .toUpperCase();

        return "<img src='" + this.getIconPic(unicode) + "'/>";
      });

      return str;
    },
    // 延时记录光标到位置
    chartFramRange(type) {
      try {
        if (type === "click") {
          this.inputRange = window.getSelection().getRangeAt(0);
        }

        if (type === "focus") {
          this.inputRange = window.getSelection().getRangeAt(0);
        }
      } catch (err) {
        console.log(type);
      }

      return new Promise((resolve, reject) => {
        setTimeout(() => {
          this.inputRange = window.getSelection().getRangeAt(0);
          resolve(this.inputRange);
        }, 0);
      });
    },

    // 延时记录光标到位置
    saveRangeLocal() {
      setTimeout(() => {
        this.inputRange = window.getSelection().getRangeAt(0);
      }, 0);
    },
    // ================================================================
    // 阻止回车键默认事件
    stopPropagation(e) {
      if (e && e.keyCode === 13) {
        e.cancelBubble = true;
        e.preventDefault();
        e.stopPropagation();
      }
    },
    sendMsg(e, fileurl) {
      console.log(`e============`, e);

      if (fileurl) {
        // 上传文件路径
        this.msg = fileurl;
      } else {
        // 输入框信息
        this.msg = this.formatInputCon().replace(/<br>/g, "\r\n");
        console.log(`this.msg`, this.msg);
      }
      if (this.msg.trim() === "") {
        this.msg = "";
        return;
      }
      if (!this.messageType) {
        this.messageType = "text";
      }
      const msgInfo = {
        ...this.self,
        id: this.socket.id,
        msg: this.msg,
        type: this.messageType
      };
      if (this.tab === "friends") {
        msgInfo.toid = this.selected.id;
        this.socket.emit("private message", this.selected.id, msgInfo);
        const msgData = [this.selected.id, msgInfo];
        this.$store.commit("chat/set_friend_record", msgData);
        this.friend_record_list = this.friendRecord[this.selected.id];
      } else {
        console.log("=======ROOM CHAT========");
        msgInfo.roomId = this.selected.id;
        this.socket.emit("chat-room", this.selected.id, msgInfo);
        this.$store.commit("chat/set_room_record", msgInfo);
        this.room_record_list = this.roomRecord[this.selected.id];
      }
      this.$nextTick(() => {
        // 输入enter后置空
        document.getElementById("charInput").innerText = "";
        this.msg = "";
        this.messageType = "";
        // 滚动到底部
        this.$refs["myScrollbar"].wrap.scrollTop = this.$refs["myScrollbar"].wrap.scrollHeight;
      });
    },

    closeScoket() {
      // 断开连接
      this.$socket.close();
    }
  },
  created() {
    // const room_record_str = getCookie("room_record");
    // const friend_record_str = getCookie("friend_record");
    // if (room_record_str) {
    //   this.room_record = JSON.parse(room_record_str);
    // }
    // if (friend_record_str) {
    //   this.friend_record = JSON.parse(friend_record_str);
    // }
  },
  mounted() {
    this.initEmojiPic();
  }
};
</script>

<style lang="scss" scoped>
.chat-wrap {
  height: 90vh;
  border: 1px solid #ddd;
  border-radius: 2px;
}
.chat-title {
  padding: 20px;
  font-weight: 600;
}
.record-warp {
  padding: 10px;
  height: 63vh;
  background: rgb(245, 245, 245);
}
/* .record-list {
} */
.record-item {
  display: flex;
  padding: 15px 5px;
  margin: 5px;
}
.avatar {
  margin: 10px 5px;
}
.record-item > span {
  padding: 8px 12px;
  border-radius: 5px;
}
.username {
  padding: 4px;
  margin-bottom: 2px;
  font-size: 14px;
  color: gray;
}
.group-record-item > span {
  padding: 8px 12px;
  border-radius: 5px;
  background-color: rgb(199, 206, 200);
}
.send-record {
  position: relative;
  justify-content: flex-end;
}

.send-record > span {
  display: inline-block;
  text-align: right;
}
.message-content-text,
.message-content-image {
  max-width: 600px;
  display: inline-block;
  margin-left: 35px;
  overflow: hidden;
  margin-top: 4px;
  padding: 6px;
  background: rgb(117, 197, 128);
  font-size: 16px;
  border-radius: 5px;
  text-align: left;
  word-break: break-word;
}
.message-content-image {
  max-height: 255px;
  max-width: 255px;
  background: rgb(204, 197, 197);
}
.message-content-image img {
  cursor: pointer;
  max-width: 225px;
  max-height: 225px;
}
.receive-record-item {
  margin: 2px;
  background: #fff;
}
.input-box {
  display: flex;
  overflow: hidden;
  position: relative;
}

.send-footer {
  position: absolute;
  bottom: 0;
  right: 20px;
  padding: 10px;
  text-align: right;
}

.chatframe_input_con {
  display: inline-block;
  width: 92%;
  height: 95px;
  resize: none;
  padding: 5px 15px;
  line-height: 1.5;
  box-sizing: border-box;
  font-size: inherit;
  color: #606266;
  background-color: #fff;
  outline: none;
  overflow-y: scroll;
  margin-bottom: 20px;

  // 超出自动换行 -- 火狐
  word-wrap: break-word;
  word-break: break-all;

  // 滚动样式 细 - 火狐
  scrollbar-width: thin;
}

.chatframe-text {
  min-height: 200px;
  width: 500px;
  box-sizing: border-box;
  padding: 10px 15px;
  margin-top: 5px;
  background: #eaedf1;
  color: #282828;
  border-radius: 4px;
  word-wrap: break-word;
  word-break: break-all;
  line-height: 18px;
  white-space: pre-wrap;
  position: relative;
}

.text_emoji {
  img {
    display: inline-block;
    width: 20px;
    height: 20px;
    vertical-align: bottom;
  }
}
</style>
