<template>
  <div class="chat-detail-con flex-default">
    <div class="chat-scroll">
      <mescroll-vue
        :fixed="false"
        ref="mescrollRef"
        @init="mescrollInit"
        :down="downOption"
        :up="upOption"
      >
        <div class="chat-empty" />
        <!-- :type="item.type"	:status="item.status" :content="item.content" :progress="item.progress" :isSelf="item.isSelf" :hideTime="item.hideTime" -->
        <chat-item
          v-for="(item, index) of list"
          :key="`chat-item-${index}`"
          :index="index"
          :previous="index > 0 ? list[index - 1] : {}"
          :itemData="item"
          :postData="postData"
          @previewItem="previewItem"
        />
        <div class="chat-empty" />
      </mescroll-vue>
    </div>
    <chat-footer
      @confirm="sendText"
      @uploadSuccess="uploadSuccess"
      @uploadFail="uploadFail"
      @chooseFile="chooseFile"
      @on-progress="uploadOnProgress"
    />
    <!-- <m-preview ref="Preview"></m-preview> -->
  </div>
</template>

<script>
import ChatItem from "./chat-item";
import ChatFooter from "./chat-footer";
// import MPreview from "@/pages/components/preview/preview.vue";
import { ChatMsgStatus, ChatMsgType } from "@/enums";
import { deepCopy } from "@/utils/common";
import { mapState } from "vuex";
import { MescrollMixin } from "@/mixins";
export default {
  mixins: [MescrollMixin],
  components: {
    ChatItem,
    ChatFooter,
    // MPreview,
  },
  data() {
    return {
      downOption: {
        autoShowLoading: false,
        callback: this.downCallback,
      },
      upOption: {
        use: false,
        toTop: {
          src: "",
        },
      },
      form: {
        page: 1,
        size: 10,
      },
      list: [],
      postData: {},
      socketTask: null,
      is_open_socket: false,
      type: "",
      previewIndex: 0,
      toId: "",
      reconnectTimeOutObj: null, //重连之后多久再次重连
      timeout: 5000, //多少秒执行检测
      timeoutObj: null, //检测服务器端是否还活着
      lockReconnect: false, //避免重复连接
      status: null, // websocket是否关闭
      reconnectNumber: 0,
      reconnectNumberMax: 100,
    };
  },
  computed: {
    ...mapState(["accountInfo"]),
    getPrviewsList() {
      //预览
      let arr = [];
      for (let i = 0, len = this.list.length; i < len; i++) {
        if (this.list[i].type === ChatMsgType.IMAGE) {
          arr.push({
            type: "img",
            url: this.list[i].content,
            subscript: i,
          });
        } else if (this.list[i].type === ChatMsgType.VIDEO) {
          arr.push({
            type: "video",
            url: this.list[i].content,
            video: this.list[i].content,
            subscript: i,
          });
        }
      }
      return arr;
    },
  },
  mounted() {
    // 获取列表
    let option = this.$route.query;
    this.type = option.type;
    if (option.type === "fromList") {
      let customer = JSON.parse(option.customer);
      customer.customerImage = customer.customerImage || "";
      customer.userId = this.accountInfo.userId;
      customer.userImage = this.accountInfo.headUrl || "";
      customer.userName = this.accountInfo.nickName;
      this.postData = customer;
      this.toId = option.toId;
      // this.requestDataList(option.toId)
    } else {
      let customer = JSON.parse(option.customer);
      customer.customerImage = customer.customerImage || "";
      customer.userId = this.accountInfo.userId;
      customer.userImage = this.accountInfo.headUrl || "";
      customer.userName = this.accountInfo.nickName;
      this.postData = customer;
      // this.requestData()
    }
  },
  created() {
    this.reconnectNumber = 0;
    this.closeSocket();
  },
  beforeDestroy() {
    this.closeSocket();
  },
  methods: {
    initRequest() {
      if (this.type === "fromList") {
        this.requestDataList(this.toId);
      } else {
        this.requestData();
      }
    },
    // reset和start方法主要用来控制心跳的定时。
    reset() {
      // 清除定时器重新发送一个心跳信息
      clearTimeout(this.timeoutObj);
      this.start();
    },
    // 开始心跳
    start() {
      this.timeoutObj = setTimeout(() => {
        //这里发送一个心跳，后端收到后，返回一个心跳消息，
        //onmessage拿到返回的心跳就说明连接正常
        let obj = {
          content: "webscoket心跳",
          type: 120,
        };
        (obj.fromId = this.postData.userId),
          (obj.fromName = this.postData.userName),
          (obj.fromImage = this.postData.userImage),
          (obj.toId = this.groupId),
          (obj.msgType = obj.type);
        this.socketTask.send(JSON.stringify(obj));
      }, this.timeout);
    },
    // 重连
    reconnect() {
      // 防止多个方法调用，多处重连
      if (this.lockReconnect) {
        return;
      }
      if (this.reconnectNumber > this.reconnectNumberMax) {
        this.$toast("网站服务器波动，请稍后再试");
        return;
      }
      this.lockReconnect = true;
      console.log("准备重连");
      //没连接上会一直重连，设置延迟避免请求过多
      this.reconnectTimeOutObj = setTimeout(() => {
        // 重新连接
        this.reconnectNumber++;
        this.initRequest();
        this.lockReconnect = false;
      }, 4000);
    },
    previewItem(obj) {
      //预览
      let flag = false;
      for (let i = 0, len = this.getPrviewsList.length; i < len; i++) {
        if (this.getPrviewsList[i].subscript === obj.index) {
          this.previewIndex = i;
          flag = true;
          break;
        }
      }
      if (flag) {
        this.$previewMedia({
          sources: this.getPrviewsList,
          current: this.previewIndex,
        });
      }
    },
    requestDataList(toId) {
      //列表进入
      this.$api({
        apiName: "customerServiceList",
        postData: { userId: this.accountInfo.userId, toId: toId },
        success: (res) => {
          let data = {
            group: {},
            messageList: [],
          };
          if (res && res.length > 0) {
            data = res[0];
          }
          data.messageList = data.messageList.filter((x) => {
            return x.msgType !== 120;
          });
          let arr = [];
          for (let item of data.messageList) {
            let obj = {};
            obj = deepCopy(item);
            obj.type = item.msgType;
            obj.status = 2;
            if (item.fromId === this.postData.userId) {
              obj.isSelf = true;
              obj.hideTime = true;
            } else {
              obj.hideTime = true;
            }
            arr.push(obj);
          }
          this.list = arr;
          this.$nextTick(() => {
            this.mescroll.scrollTo(99999, 0);
          });
          this.groupId = data.group.groupId;
          this.mescroll.endSuccess();
          this.connectSocketInit(data.group.groupId);
        },
      });
    },
    connectSocketInit(groupId) {
      // 创建webscoket
      const host = window.location.host;
      let protocol = "ws://";
      if (window.location.protocol === "https:") {
        protocol = "wss://";
      }
      this.socketTask = new WebSocket(
        protocol +
          host +
          "/chat/mallcustomer/websocket/" +
          this.accountInfo.userId +
          "/" +
          groupId
      );
      // 消息的发送和接收必须在正常连接打开中,才能发送或接收【否则会失败】
      this.socketTask.onopen = (res) => {
        console.log("WebSocket连接正常打开中...！");
        clearTimeout(this.reconnectTimeOutObj);
        this.start();
        this.is_open_socket = true;
      };
      // 这里仅是事件监听【如果socket关闭了会执行】
      this.socketTask.onclose = () => {
        console.log("已经被关闭了");
        if (this.is_open_socket) {
          this.reconnect();
        }
      };
      this.socketTask.onerror = (res) => {
        console.log(res, "连接错误");
        if (this.is_open_socket) {
          this.reconnect();
        }
      };
      // 注：只有连接正常打开中 ，才能正常收到消息
      this.socketTask.onmessage = (res) => {
        this.reset();
        let obj = JSON.parse(res.data);
        if (obj.msgType !== 120) {
          obj.type = obj.msgType;
          obj.status = 2;
          if (obj.fromId !== this.postData.userId) {
            this.list.push(obj);
            this.$nextTick(() => {
              this.mescroll.scrollTo(99999, 300);
            });
          }
        }
        console.log("收到服务器内容：" + res.data);
      };
    },
    // 关闭websocket【离开这个页面的时候执行关闭】
    closeSocket() {
      this.is_open_socket = false;
      if (this.socketTask) {
        this.socketTask.close();
      }
    },
    requestData() {
      //聊天列表
      this.$api({
        apiName: "contactCustomer",
        postData: this.postData,
        success: (res) => {
          let arr = [],
            messageList = [];
          if (res.messageList && res.messageList.length > 0) {
            messageList = res.messageList.filter((x) => {
              return x.msgType !== 120;
            });
          }
          for (let item of messageList) {
            let obj = {};
            obj = deepCopy(item);
            obj.type = item.msgType;
            obj.status = 2;
            if (item.fromId === this.postData.userId) {
              obj.isSelf = true;
            }
            arr.push(obj);
          }
          this.list = arr;
          this.$nextTick(() => {
            this.mescroll.scrollTo(99999, 0);
          });
          this.groupId = res.group.groupId;
          this.mescroll.endSuccess();
          this.connectSocketInit(res.group.groupId);
        },
      });
    },
    downCallback() {
      // this.requestData();
      this.initRequest();
    },
    chooseFile(data) {
      //图片视频
      this.list.push(data);
      this.$nextTick(() => {
        this.mescroll.scrollTo(99999, 300);
      });
    },
    uploadSuccess(data) {
      //文件上传成功
      let obj = this.list.find((x) => {
        return x.messageId === data.messageId && x.Listid === data.Listid;
      });
      (obj.fromId = this.postData.userId),
        (obj.fromName = this.postData.userName),
        (obj.fromImage = this.postData.userImage),
        (obj.toId = this.groupId),
        (obj.msgType = obj.type);
      this.sendMsg(obj);
    },
    uploadFail(data) {
      //文件上传失败
      let obj = this.list.find((x) => {
        return x.messageId === data.messageId && x.Listid === data.Listid;
      });
      obj.status = ChatMsgStatus.FAIL;
    },
    uploadOnProgress(obj) {
      let data = this.list.find((x) => {
        return x.messageId === obj.messageId && x.Listid === obj.Listid;
      });
      data.progress = obj.progress;
    },
    sendText(data) {
      //提交文字消息
      let obj = Object.assign({}, data);
      (obj.fromId = this.postData.userId),
        (obj.fromName = this.postData.userName),
        (obj.fromImage = this.postData.userImage),
        (obj.toId = this.groupId),
        (obj.msgType = data.type);
      this.list.push(obj);
      this.$nextTick(() => {
        this.mescroll.scrollTo(99999, 300);
      });
      this.sendMsg(obj);
    },
    sendMsg(obj) {
      //发送消息
      if (this.is_open_socket) {
        this.socketTask.send(JSON.stringify(obj));
        let data = this.list.find((x) => {
          return x.messageId === obj.messageId && x.Listid === obj.Listid;
        });
        data.sendTime = new Date().getTime();
        data.status = ChatMsgStatus.SUCCESS;
        console.log("消息发送成功");

        this.$nextTick(() => {
          this.mescroll.scrollTo(99999, 300);
        });
      }
    },
  },
};
</script>

<style lang="less">
.chat-detail-con {
  height: 100%;
  background: #f5f7fb;
  flex-direction: column;
  > div {
    width: 100%;
  }
  .chat-scroll {
    flex: 1;
    min-height: 0;
  }
  .chat-scroll .chat-empty {
    height: 15px;
    width: 100%;
  }
}
</style>
