"use strict";
const common_vendor = require("../../common/vendor.js");
const sheep_index = require("../../sheep/index.js");
function useChatWebSocket(socketConfig) {
  let SocketIo = null;
  const state = common_vendor.reactive({
    chatDotNum: 0,
    //总状态红点
    chatList: [],
    //会话信息
    customerUserInfo: {},
    //用户信息
    customerServerInfo: {
      //客服信息
      title: "连接中...",
      state: "connecting",
      avatar: null,
      nickname: ""
    },
    socketState: {
      isConnect: true,
      //是否连接成功
      isConnecting: false,
      //重连中，不允许新的socket开启。
      tip: ""
    },
    chatHistoryPagination: {
      page: 0,
      //当前页
      list_rows: 10,
      //每页条数
      last_id: 0,
      //最后条ID
      lastPage: 0,
      //总共多少页
      loadStatus: "loadmore"
      //loadmore-加载前的状态，loading-加载中的状态，nomore-没有更多的状态
    },
    templateChatList: [],
    //猜你想问
    chatConfig: {},
    // 配置信息
    isSendSucces: -1
    // 是否发送成功 -1=发送中|0=发送成功|1发送失败
  });
  const socketInit = (config, callBack) => {
    state.chatConfig = config;
    if (SocketIo && SocketIo.connected)
      return;
    if (state.socketState.isConnecting)
      return;
    SocketIo = common_vendor.io(config.chat_domain, {
      reconnection: true,
      // 默认 true    是否断线重连
      reconnectionAttempts: 5,
      // 默认无限次   断线尝试次数
      reconnectionDelay: 1e3,
      // 默认 1000，进行下一次重连的间隔。
      reconnectionDelayMax: 5e3,
      // 默认 5000， 重新连接等待的最长时间 默认 5000
      randomizationFactor: 0.5,
      // 默认 0.5 [0-1]，随机重连延迟时间
      timeout: 2e4,
      // 默认 20s
      transports: ["websocket", "polling"],
      // websocket | polling,
      ...config
    });
    SocketIo.on("connect", async (res) => {
      socketReset(callBack);
      console.log("socket:connect");
    });
    SocketIo.on("message", (res) => {
      if (res.error === 0) {
        res.data;
        state.chatList.push(formatMessage(res.data.message));
        callBack && callBack();
      }
    });
    SocketIo.on("customer_service_access", (res) => {
      if (res.error === 0) {
        editCustomerServerInfo({
          title: res.data.customer_service.name,
          state: "online",
          avatar: res.data.customer_service.avatar
        });
        state.chatList.push(formatMessage(res.data.message));
      }
    });
    SocketIo.on("waiting_queue", (res) => {
      if (res.error === 0) {
        editCustomerServerInfo({
          title: res.data.title,
          state: "waiting",
          avatar: ""
        });
      }
    });
    SocketIo.on("no_customer_service", (res) => {
      if (res.error === 0) {
        editCustomerServerInfo({
          title: "暂无客服在线...",
          state: "waiting",
          avatar: ""
        });
      }
      state.chatList.push(formatMessage(res.data.message));
    });
    SocketIo.on("customer_service_online", (res) => {
      if (res.error === 0) {
        editCustomerServerInfo({
          title: res.data.customer_service.name,
          state: "online",
          avatar: res.data.customer_service.avatar
        });
      }
    });
    SocketIo.on("customer_service_offline", (res) => {
      if (res.error === 0) {
        editCustomerServerInfo({
          title: res.data.customer_service.name,
          state: "offline",
          avatar: res.data.customer_service.avatar
        });
      }
    });
    SocketIo.on("customer_service_busy", (res) => {
      if (res.error === 0) {
        editCustomerServerInfo({
          title: res.data.customer_service.name,
          state: "busy",
          avatar: res.data.customer_service.avatar
        });
      }
    });
    SocketIo.on("customer_service_break", (res) => {
      if (res.error === 0) {
        editCustomerServerInfo({
          title: "客服服务结束",
          state: "offline",
          avatar: ""
        });
        state.socketState.isConnect = false;
        state.socketState.tip = "当前服务已结束";
      }
      state.chatList.push(formatMessage(res.data.message));
    });
    SocketIo.on("custom_error", (error) => {
      editCustomerServerInfo({
        title: error.msg,
        state: "offline",
        avatar: ""
      });
      console.log("custom_error:", error);
    });
    SocketIo.on("error", (error) => {
      console.log("error:", error);
    });
    SocketIo.on("connect_error", (error) => {
      console.log("connect_error");
    });
    SocketIo.on("connect_timeout", (error) => {
      console.log(error, "connect_timeout");
    });
    SocketIo.on("disconnect", (error) => {
      console.log(error, "disconnect");
    });
    SocketIo.on("reconnect", (error) => {
      console.log(error, "reconnect");
    });
    SocketIo.on("reconnect_attempt", (error) => {
      state.socketState.isConnect = false;
      state.socketState.isConnecting = true;
      editCustomerServerInfo({
        title: `重连中，第${error}次尝试...`,
        state: "waiting",
        avatar: ""
      });
      console.log(error, "reconnect_attempt");
    });
    SocketIo.on("reconnecting", (error) => {
      console.log(error, "reconnecting");
    });
    SocketIo.on("reconnect_error", (error) => {
      console.log("reconnect_error");
    });
    SocketIo.on("reconnect_failed", (error) => {
      state.socketState.isConnecting = false;
      editCustomerServerInfo({
        title: `重连失败，请刷新重试~`,
        state: "waiting",
        avatar: ""
      });
      console.log(error, "reconnect_failed");
      state.isSendSucces = 1;
    });
  };
  const socketReset = (callBack) => {
    state.chatList = [];
    state.chatHistoryList = [];
    state.chatHistoryPagination = {
      page: 0,
      per_page: 10,
      last_id: 0,
      totalPage: 0
    };
    socketConnection(callBack);
  };
  const socketClose = () => {
    SocketIo.emit("customer_logout", {}, (res) => {
      console.log("socket:退出", res);
    });
  };
  const socketTest = () => {
    SocketIo.emit("test", {}, (res) => {
      console.log("test:test", res);
    });
  };
  const socketSendMsg = (data, sendMsgCallBack) => {
    state.isSendSucces = -1;
    state.chatList.push(data);
    sendMsgCallBack && sendMsgCallBack();
    SocketIo.emit(
      "message",
      {
        message: formatInput(data),
        ...data.customData
      },
      (res) => {
        state.isSendSucces = res.error;
      }
    );
  };
  const socketConnection = (callBack) => {
    SocketIo.emit(
      "connection",
      {
        auth: "user",
        token: common_vendor.index.getStorageSync("socketUserToken") || "",
        session_id: common_vendor.index.getStorageSync("socketSessionId") || ""
      },
      (res) => {
        if (res.error === 0) {
          socketCustomerLogin(callBack);
          common_vendor.index.setStorageSync("socketSessionId", res.data.session_id);
          state.customerUserInfo = res.data.chat_user;
          state.socketState.isConnect = true;
        } else {
          editCustomerServerInfo({
            title: `服务器异常！`,
            state: "waiting",
            avatar: ""
          });
          state.socketState.isConnect = false;
        }
      }
    );
  };
  const getUserToken = async (id) => {
    const res = await chat.unifiedToken();
    if (res.error === 0) {
      common_vendor.index.setStorageSync("socketUserToken", res.data.token);
    }
    return res;
  };
  const socketCustomerLogin = (callBack) => {
    SocketIo.emit(
      "customer_login",
      {
        room_id: state.chatConfig.room_id
      },
      (res) => {
        state.templateChatList = res.data.questions.length ? res.data.questions : [];
        state.chatList.push({
          from: "customer_service",
          // 用户customer右 |  顾客customer_service左 | 系统system中间
          mode: "template",
          // goods,order,image,text,system
          date: (/* @__PURE__ */ new Date()).getTime(),
          //时间
          content: {
            //内容
            list: state.templateChatList
          }
        });
        res.error === 0 && socketHistoryList(callBack);
      }
    );
  };
  const socketHistoryList = (historyCallBack) => {
    state.chatHistoryPagination.loadStatus = "loading";
    state.chatHistoryPagination.page += 1;
    SocketIo.emit("messages", state.chatHistoryPagination, (res) => {
      if (res.error === 0) {
        state.chatHistoryPagination.total = res.data.messages.total;
        state.chatHistoryPagination.lastPage = res.data.messages.last_page;
        state.chatHistoryPagination.page = res.data.messages.current_page;
        res.data.messages.data.forEach((item) => {
          item.message_type && state.chatList.unshift(formatMessage(item));
        });
        state.chatHistoryPagination.loadStatus = state.chatHistoryPagination.page < state.chatHistoryPagination.lastPage ? "loadmore" : "nomore";
        if (state.chatHistoryPagination.last_id == 0) {
          state.chatHistoryPagination.last_id = res.data.messages.data.length ? res.data.messages.data[0].id : 0;
        }
        state.chatHistoryPagination.page === 1 && historyCallBack && historyCallBack();
      }
    });
  };
  const editCustomerServerInfo = (data) => {
    state.customerServerInfo = {
      ...state.customerServerInfo,
      ...data
    };
  };
  const showTime = (item, index) => {
    if (common_vendor.unref(state.chatList)[index + 1]) {
      let dateString = common_vendor.dayjs(common_vendor.unref(state.chatList)[index + 1].date).fromNow();
      if (dateString === common_vendor.dayjs(common_vendor.unref(item).date).fromNow()) {
        return false;
      } else {
        dateString = common_vendor.dayjs(common_vendor.unref(item).date).fromNow();
        return true;
      }
    }
    return false;
  };
  const formatTime = (time) => {
    let diffTime = (/* @__PURE__ */ new Date()).getTime() - time;
    if (diffTime > 28 * 24 * 60 * 1e3) {
      return common_vendor.dayjs(time).format("MM/DD HH:mm");
    }
    if (diffTime > 360 * 28 * 24 * 60 * 1e3) {
      return common_vendor.dayjs(time).format("YYYY/MM/DD HH:mm");
    }
    return common_vendor.dayjs(time).fromNow();
  };
  const getFocus = (virtualNode) => {
    if (window.getSelection) {
      let chatInput2 = common_vendor.unref(virtualNode);
      chatInput2.focus();
      let range = window.getSelection();
      range.selectAllChildren(chatInput2);
      range.collapseToEnd();
    } else if (document.selection) {
      let range = document.selection.createRange();
      range.moveToElementText(chatInput);
      range.collapse(false);
      range.select();
    }
  };
  const upload = (name, file) => {
    return new Promise((resolve, reject) => {
      let data = new FormData();
      data.append("file", file, name);
      data.append("group", "chat");
      ajax({
        url: "/upload",
        method: "post",
        headers: {
          "Content-Type": "multipart/form-data"
        },
        data,
        success: function(res) {
          resolve(res);
        },
        error: function(err) {
          reject(err);
        }
      });
    });
  };
  const onPaste = async (e) => {
    let paste = e.clipboardData || window.clipboardData;
    let filesArr = Array.from(paste.files);
    filesArr.forEach(async (child) => {
      if (child && child.type.includes("image")) {
        e.preventDefault();
        let file = child;
        const img = await readImg(file);
        const blob = await compressImg(img, file.type);
        const { data } = await upload(file.name, blob);
        let image = `<img class="full-url" src='${data.fullurl}'>`;
        document.execCommand("insertHTML", false, image);
      } else {
        document.execCommand("insertHTML", false, paste.getData("text"));
      }
    });
  };
  const onDrop = async (e) => {
    e.preventDefault();
    let filesArr = Array.from(e.dataTransfer.files);
    filesArr.forEach(async (child) => {
      if (child && child.type.includes("image")) {
        let file = child;
        const img = await readImg(file);
        const blob = await compressImg(img, file.type);
        const { data } = await upload(file.name, blob);
        let image = `<img class="full-url" src='${data.fullurl}' >`;
        document.execCommand("insertHTML", false, image);
      } else {
        ElMessage({
          message: "禁止拖拽非图片资源",
          type: "warning"
        });
      }
    });
  };
  const formatChatInput = (virtualNode, formatInputCallBack) => {
    let res = "";
    let elemArr = Array.from(virtualNode.childNodes);
    elemArr.forEach((child, index) => {
      if (child.nodeName === "#text") {
        res += child.nodeValue;
        if (
          //文本节点的后面是图片，并且不是emoji,分开发送。输入框中的图片和文本表情分开。
          elemArr[index + 1] && elemArr[index + 1].nodeName === "IMG" && elemArr[index + 1] && elemArr[index + 1].name !== "emoji"
        ) {
          const data = {
            from: "customer",
            mode: "text",
            date: (/* @__PURE__ */ new Date()).getTime(),
            content: {
              text: filterXSS(res)
            }
          };
          formatInputCallBack && formatInputCallBack(data);
          res = "";
        }
      } else if (child.nodeName === "BR") {
        res += "<br/>";
      } else if (child.nodeName === "IMG") {
        if (child.name !== "emoji") {
          let srcReg = /src=[\'\']?([^\'\']*)[\'\']?/i;
          let src = child.outerHTML.match(srcReg);
          const data = {
            from: "customer",
            mode: "image",
            date: (/* @__PURE__ */ new Date()).getTime(),
            content: {
              url: src[1],
              path: src[1].replace(/http:\/\/[^\/]*/, "")
            }
          };
          formatInputCallBack && formatInputCallBack(data);
        } else {
          res += child.outerHTML;
        }
      } else if (child.nodeName === "DIV") {
        res += `<div style='width:200px; white-space: nowrap;'>${child.outerHTML}</div>`;
      }
    });
    if (res) {
      const data = {
        from: "customer",
        mode: "text",
        date: (/* @__PURE__ */ new Date()).getTime(),
        content: {
          text: filterXSS(res)
        }
      };
      formatInputCallBack && formatInputCallBack(data);
    }
    common_vendor.unref(virtualNode).innerHTML = "";
  };
  const callBackNotice = (res) => {
    ElNotification({
      title: "socket",
      message: res.msg,
      showClose: true,
      type: res.error === 0 ? "success" : "warning",
      duration: 1200
    });
  };
  const formatInput = (message) => {
    let obj = {};
    switch (message.mode) {
      case "text":
        obj = {
          message_type: "text",
          message: message.content.text
        };
        break;
      case "image":
        obj = {
          message_type: "image",
          message: message.content.path
        };
        break;
      case "goods":
        obj = {
          message_type: "goods",
          message: message.content.item
        };
        break;
      case "order":
        obj = {
          message_type: "order",
          message: message.content.item
        };
        break;
    }
    return obj;
  };
  const formatMessage = (message) => {
    let obj = {};
    switch (message.message_type) {
      case "system":
        obj = {
          from: "system",
          // 用户customer左 |  顾客customer_service右 | 系统system中间
          mode: "system",
          // goods,order,image,text,system
          date: message.create_time * 1e3,
          //时间
          content: {
            //内容
            text: message.message
          }
        };
        break;
      case "text":
        obj = {
          from: message.sender_identify,
          mode: message.message_type,
          date: message.create_time * 1e3,
          //时间
          sender: message.sender,
          content: {
            text: message.message,
            messageId: message.id
          }
        };
        break;
      case "image":
        obj = {
          from: message.sender_identify,
          mode: message.message_type,
          date: message.create_time * 1e3,
          //时间
          sender: message.sender,
          content: {
            url: sheep_index.sheep.$url.cdn(message.message),
            messageId: message.id
          }
        };
        break;
      case "goods":
        obj = {
          from: message.sender_identify,
          mode: message.message_type,
          date: message.create_time * 1e3,
          //时间
          sender: message.sender,
          content: {
            item: message.message,
            messageId: message.id
          }
        };
        break;
      case "order":
        obj = {
          from: message.sender_identify,
          mode: message.message_type,
          date: message.create_time * 1e3,
          //时间
          sender: message.sender,
          content: {
            item: message.message,
            messageId: message.id
          }
        };
        break;
    }
    return obj;
  };
  const readImg = (file) => {
    return new Promise((resolve, reject) => {
      const img = new Image();
      const reader = new FileReader();
      reader.onload = function(e) {
        img.src = e.target.result;
      };
      reader.onerror = function(e) {
        reject(e);
      };
      reader.readAsDataURL(file);
      img.onload = function() {
        resolve(img);
      };
      img.onerror = function(e) {
        reject(e);
      };
    });
  };
  const compressImg = (img, type = "image/jpeg", mx = 1e3, mh = 1e3, quality = 1) => {
    return new Promise((resolve, reject) => {
      const canvas = document.createElement("canvas");
      const context = canvas.getContext("2d");
      const { width: originWidth, height: originHeight } = img;
      const maxWidth = mx;
      const maxHeight = mh;
      let targetWidth = originWidth;
      let targetHeight = originHeight;
      if (originWidth > maxWidth || originHeight > maxHeight) {
        if (originWidth / originHeight > 1) {
          targetWidth = maxWidth;
          targetHeight = Math.round(maxWidth * (originHeight / originWidth));
        } else {
          targetHeight = maxHeight;
          targetWidth = Math.round(maxHeight * (originWidth / originHeight));
        }
      }
      canvas.width = targetWidth;
      canvas.height = targetHeight;
      context.clearRect(0, 0, targetWidth, targetHeight);
      context.drawImage(img, 0, 0, targetWidth, targetHeight);
      canvas.toBlob(
        function(blob) {
          resolve(blob);
        },
        type,
        quality
      );
    });
  };
  return {
    compressImg,
    readImg,
    formatMessage,
    formatInput,
    callBackNotice,
    socketInit,
    socketSendMsg,
    socketClose,
    socketHistoryList,
    getFocus,
    formatChatInput,
    onDrop,
    onPaste,
    upload,
    getUserToken,
    state,
    socketTest,
    showTime,
    formatTime
  };
}
exports.useChatWebSocket = useChatWebSocket;
