"use strict";
Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: "Module" } });
const Vue = require("vue");
require("../../../adapter-vue.js");
const TUIChatEngine = require("@tencentcloud/chat-uikit-engine");
const core = require("@tiptap/core");
const Document = require("@tiptap/extension-document");
const Paragraph = require("@tiptap/extension-paragraph");
const Placeholder = require("@tiptap/extension-placeholder");
const Text = require("@tiptap/extension-text");
const Mention = require("@tiptap/extension-mention");
const messageInputFile = require("./message-input-file.js");
const index = require("./message-input-at/index.js");
const index$1 = require("../emoji-config/index.js");
const env = require("../../../utils/env.js");
const conversationDraft = require("../utils/conversationDraft.js");
const _hoisted_1 = {
  key: 0,
  class: "message-input-mute"
};
const _hoisted_2 = ["contenteditable"];
const _sfc_main = /* @__PURE__ */ Vue.defineComponent({
  __name: "message-input-editor",
  props: {
    placeholder: {
      type: String,
      default: "this is placeholder"
    },
    replayOrReferenceMessage: {
      type: Object,
      default: () => ({})
    },
    isMuted: {
      type: Boolean,
      default: true
    },
    muteText: {
      type: String,
      default: ""
    },
    enableInput: {
      type: Boolean,
      default: true
    },
    enableAt: {
      type: Boolean,
      default: true
    },
    enableDragUpload: {
      type: Boolean,
      default: true
    },
    enableTyping: {
      type: Boolean,
      default: true
    }
  },
  emits: ["sendMessage", "onTyping", "onAt"],
  setup(__props, { expose: __expose, emit: __emit }) {
    const props = __props;
    const emits = __emit;
    const { placeholder, enableAt, enableDragUpload, enableTyping } = Vue.toRefs(props);
    const isEditorEmpty = Vue.ref(true);
    const isEditorBlur = Vue.ref(true);
    const isC2C = Vue.ref(false);
    const currentConversationID = Vue.ref("");
    const currentQuoteMessage = Vue.ref();
    const editorDom = Vue.ref();
    let editor = null;
    const fileMap = /* @__PURE__ */ new Map();
    function onCurrentConversationIDUpdated(conversationID) {
      if (currentConversationID.value !== conversationID) {
        if (currentConversationID.value) {
          conversationDraft.default.setStore(
            currentConversationID.value,
            getEditorHTML(),
            conversationDraft.default.generateAbstract(getEditorContent()),
            currentQuoteMessage.value
          );
        }
        resetEditor();
        if (conversationID) {
          conversationDraft.default.getStore(conversationID, setEditorContent);
        }
      }
      currentConversationID.value = conversationID;
    }
    function onQuoteMessageUpdated(options) {
      currentQuoteMessage.value = options;
    }
    Vue.onMounted(() => {
      editor = env.isPC ? new core.Editor({
        element: editorDom.value,
        extensions: [
          Document,
          Paragraph,
          Text,
          Placeholder.configure({
            emptyEditorClass: "is-editor-empty",
            placeholder: placeholder.value
          }),
          Mention.configure({
            HTMLAttributes: {
              class: "mention"
            },
            suggestion: enableAt.value && index.default()
          }),
          messageInputFile.default.configure({
            inline: true,
            allowBase64: true
          })
        ],
        autofocus: !env.isH5,
        editable: true,
        injectCSS: false,
        editorProps: {
          transformPastedText() {
            return "";
          }
        },
        // handle input editor typing (only in C2C and enable typing)
        onUpdate({ editor: editor2, transaction }) {
          var _a, _b;
          if (!enableTyping.value || !isC2C.value) return;
          isEditorBlur.value = !editor2.isFocused;
          if (((_b = (_a = transaction == null ? void 0 : transaction.doc) == null ? void 0 : _a.content) == null ? void 0 : _b.size) > 2) {
            isEditorEmpty.value = false;
          } else {
            isEditorEmpty.value = true;
          }
        },
        onFocus() {
          var _a;
          if (env.isH5 && ((_a = document == null ? void 0 : document.getElementById("app")) == null ? void 0 : _a.style)) {
            const keyboardHeight = document.body.scrollHeight - window.innerHeight;
            document.getElementById("app").style.marginBottom = `${keyboardHeight}px`;
            document.getElementById("app").style.height = `calc(100% - ${keyboardHeight}px)`;
          }
          if (!enableTyping.value || !isC2C.value) return;
          isEditorBlur.value = true;
        },
        onBlur() {
          var _a;
          if (env.isH5 && ((_a = document == null ? void 0 : document.getElementById("app")) == null ? void 0 : _a.style)) {
            document.getElementById("app").style.marginBottom = ``;
            document.getElementById("app").style.height = `100%`;
          }
          if (!enableTyping.value || !isC2C.value) return;
          isEditorBlur.value = true;
        }
      }) : null;
      TUIChatEngine.TUIStore.watch(TUIChatEngine.StoreName.CONV, {
        currentConversationID: onCurrentConversationIDUpdated
      });
      TUIChatEngine.TUIStore.watch(TUIChatEngine.StoreName.CHAT, {
        quoteMessage: onQuoteMessageUpdated
      });
    });
    Vue.onUnmounted(() => {
      TUIChatEngine.TUIStore.unwatch(TUIChatEngine.StoreName.CONV, {
        currentConversationID: onCurrentConversationIDUpdated
      });
      TUIChatEngine.TUIStore.unwatch(TUIChatEngine.StoreName.CHAT, {
        quoteMessage: onQuoteMessageUpdated
      });
      fileMap.clear();
    });
    function handleEnter(e) {
      var _a;
      if (env.isH5) {
        return;
      }
      e == null ? void 0 : e.preventDefault();
      e == null ? void 0 : e.stopPropagation();
      if (e.keyCode === 13 && e.ctrlKey) {
        (_a = editor == null ? void 0 : editor.commands) == null ? void 0 : _a.insertContent("<p></p>");
      } else if (e.keyCode === 13) {
        emits("sendMessage");
      }
    }
    function handleH5Input(e) {
      var _a;
      if (env.isH5) {
        e.data === "@" && emits("onAt", true);
        isEditorEmpty.value = ((_a = editorDom.value) == null ? void 0 : _a.childNodes) ? false : true;
      }
    }
    function handleH5Blur() {
      env.isH5 && (isEditorBlur.value = true);
    }
    function handleH5Focus() {
      env.isH5 && (isEditorBlur.value = false);
    }
    function insertAt(atInfo) {
      var _a;
      const mentionText = document.createElement("span");
      mentionText.innerHTML = atInfo.label;
      mentionText.className = "mention";
      mentionText.id = atInfo.id;
      (_a = editorDom.value) == null ? void 0 : _a.appendChild(mentionText);
    }
    function handlePCFileDrop(e) {
      env.isPC && handleFileDropOrPaste(e, "drop");
    }
    function handlePaste(e) {
      if (!e.clipboardData) {
        return;
      }
      if (env.isPC && e.clipboardData.files.length) {
        handleFileDropOrPaste(e, "paste");
      } else {
        handlePasteText(e);
        scrollToCaret(editorDom.value);
      }
    }
    function handlePasteText(e) {
      var _a, _b;
      e.preventDefault();
      const html = (_a = e.clipboardData) == null ? void 0 : _a.getData("text/html");
      const text = ((_b = e.clipboardData) == null ? void 0 : _b.getData("text/plain")) || "";
      if (!html) {
        const renderArray = index$1.parseTextToRenderArray(text);
        insertEditorContent(renderArray);
      }
    }
    async function handleFileDropOrPaste(e, type) {
      var _a, _b, _c;
      e.preventDefault();
      e.stopPropagation();
      if (!enableDragUpload.value && type === "drop") {
        return;
      }
      if (type === "drop" && e.dataTransfer || type === "paste" && e.clipboardData) {
        const files = type === "drop" ? (_a = e == null ? void 0 : e.dataTransfer) == null ? void 0 : _a.files : (_b = e == null ? void 0 : e.clipboardData) == null ? void 0 : _b.files;
        for (let i = 0; i < files.length; i++) {
          const file = files[i];
          const isImage = file.type.startsWith("image/");
          const fileSrc = isImage ? URL.createObjectURL(file) : await drawFileCanvasToImageUrl(file);
          (_c = editor == null ? void 0 : editor.commands) == null ? void 0 : _c.insertContent({
            type: "custom-image",
            attrs: {
              src: fileSrc,
              alt: file == null ? void 0 : file.name,
              class: isImage ? "normal" : "file"
            }
          });
          fileMap.set(fileSrc, file);
          if (i === files.length - 1) {
            setTimeout(() => {
              var _a2, _b2;
              (_a2 = editor == null ? void 0 : editor.commands) == null ? void 0 : _a2.focus("end");
              (_b2 = editor == null ? void 0 : editor.commands) == null ? void 0 : _b2.scrollIntoView();
            }, 10);
          }
        }
      }
    }
    const fileIconDomMap = /* @__PURE__ */ new Map();
    const addImageProcess = (src, type) => {
      return new Promise((resolve, reject) => {
        if (fileIconDomMap.has(type)) {
          resolve(fileIconDomMap.get(type));
        } else {
          const img = new Image();
          img.crossOrigin = "anonymous";
          img.onload = () => {
            fileIconDomMap.set(type, img);
            resolve(img);
          };
          img.onerror = reject;
          img.src = src;
        }
      });
    };
    const drawFileCanvasToImageUrl = async (file) => {
      const { name, type } = file;
      const canvas = document.createElement("canvas");
      const width = 160;
      const height = 50;
      canvas.style.width = width + "px";
      canvas.style.height = height + "px";
      const scale = window.devicePixelRatio;
      canvas.width = Math.floor(width * scale);
      canvas.height = Math.floor(height * scale);
      const ctx = canvas.getContext("2d");
      if (!ctx) {
        return "";
      }
      ctx.scale(scale, scale);
      const { iconSrc, iconType } = handleFileIconForShow(type);
      const img = await addImageProcess(iconSrc, iconType);
      ctx == null ? void 0 : ctx.drawImage(img, 10, 10, 30, 30);
      const nameForShow = handleNameForShow(name);
      ctx.fillText(nameForShow, 45, 22);
      const dataURL = canvas.toDataURL();
      return dataURL;
    };
    const handleFileIconForShow = (type) => {
      const urlBase = "https://web.sdk.qcloud.com/component/TUIKit/assets/file-";
      const fileTypes = [
        "image",
        "pdf",
        "text",
        "ppt",
        "presentation",
        "sheet",
        "zip",
        "word",
        "video",
        "unknown"
      ];
      let url = "";
      let iconType = "";
      fileTypes.forEach((typeName) => {
        if (type.includes(typeName)) {
          url = urlBase + typeName + ".svg";
          iconType = typeName;
        }
      });
      return {
        iconSrc: url ? url : urlBase + "unknown.svg",
        iconType: iconType ? iconType : "unknown"
      };
    };
    const handleNameForShow = (value) => {
      if (!value) {
        return value;
      }
      let res = "";
      let length = 0;
      for (let i = 0; i < (value == null ? void 0 : value.length); i++) {
        if (length > 16) {
          res += "...";
          break;
        }
        res += value[i];
        if (/[a-z]|[0-9]|[,;.!@#-+/\\$%^*()<>?:"'{}~]/i.test(value[i])) {
          length += 1;
        } else {
          length += 2;
        }
      }
      return res;
    };
    function getEditorContent() {
      return env.isPC ? parsePCEditorContent() : parseH5EditorContent();
    }
    function parsePCEditorContent() {
      var _a, _b;
      const editorJSON = editor == null ? void 0 : editor.getJSON();
      const content = [];
      handleEditorContent(editorJSON, content);
      if (content.length > 0 && content[content.length - 1] && content[content.length - 1].type === "text" && ((_b = (_a = content[content.length - 1].payload) == null ? void 0 : _a.text) == null ? void 0 : _b.endsWith("\n"))) {
        const text = content[content.length - 1].payload.text || "";
        content[content.length - 1].payload.text = text == null ? void 0 : text.substring(
          0,
          text.lastIndexOf("\n")
        );
      }
      return content;
    }
    function handleEditorContent(root, content) {
      var _a;
      if (!root || !root.type) {
        return;
      }
      if (root.type !== "text" && root.type !== "custom-image" && root.type !== "mention") {
        if (root.type === "paragraph") {
          handleEditorNode(root, content);
        }
        if ((_a = root.content) == null ? void 0 : _a.length) {
          root.content.forEach((item) => {
            handleEditorContent(item, content);
          });
        }
        return;
      } else {
        handleEditorNode(root, content);
      }
    }
    function handleEditorNode(node, content) {
      var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u;
      if (node.type === "paragraph") {
        if (content.length > 0 && content[content.length - 1] && ((_a = content[content.length - 1]) == null ? void 0 : _a.type) === "text") {
          content[content.length - 1].payload.text += "\n";
        }
      } else if (node.type === "text" || node.type === "custom-image" && ((_c = (_b = node == null ? void 0 : node.attrs) == null ? void 0 : _b.class) == null ? void 0 : _c.includes("emoji"))) {
        const text = node.type === "text" ? node == null ? void 0 : node.text : (_d = node == null ? void 0 : node.attrs) == null ? void 0 : _d.alt;
        if (content.length > 0 && content[content.length - 1] && ((_e = content[content.length - 1]) == null ? void 0 : _e.type) === "text") {
          content[content.length - 1].payload.text += text;
        } else {
          content.push({
            type: "text",
            payload: { text }
          });
        }
      } else if (node.type === "custom-image" && ((_g = (_f = node == null ? void 0 : node.attrs) == null ? void 0 : _f.class) == null ? void 0 : _g.includes("normal"))) {
        content.push({
          type: "image",
          payload: { file: fileMap == null ? void 0 : fileMap.get((_h = node == null ? void 0 : node.attrs) == null ? void 0 : _h.src) }
        });
      } else if (node.type === "custom-image" && ((_j = (_i = node == null ? void 0 : node.attrs) == null ? void 0 : _i.class) == null ? void 0 : _j.includes("file"))) {
        const file = fileMap == null ? void 0 : fileMap.get((_k = node == null ? void 0 : node.attrs) == null ? void 0 : _k.src);
        content.push({
          type: ((_l = file == null ? void 0 : file.type) == null ? void 0 : _l.includes("video")) ? "video" : "file",
          payload: { file }
        });
      } else if (node.type === "mention") {
        const text = "@" + ((_m = node == null ? void 0 : node.attrs) == null ? void 0 : _m.label) + " ";
        if (content.length > 0 && content[content.length - 1] && ((_n = content[content.length - 1]) == null ? void 0 : _n.type) === "text") {
          content[content.length - 1].payload.text += text;
        } else {
          content.push({
            type: "text",
            payload: { text }
          });
        }
        if ((_p = (_o = content[content.length - 1]) == null ? void 0 : _o.payload) == null ? void 0 : _p.atUserList) {
          (_t = (_r = (_q = content[content.length - 1]) == null ? void 0 : _q.payload) == null ? void 0 : _r.atUserList) == null ? void 0 : _t.push((_s = node == null ? void 0 : node.attrs) == null ? void 0 : _s.id);
        } else {
          content[content.length - 1].payload.atUserList = [(_u = node == null ? void 0 : node.attrs) == null ? void 0 : _u.id];
        }
      }
    }
    function parseH5EditorContent() {
      var _a, _b, _c;
      const root = editorDom.value;
      let text = "";
      const atUserList = [];
      try {
        for (const child of root.childNodes) {
          if (child.nodeName === "#text" || child.nodeName === "SPAN" || ((_a = child.classList) == null ? void 0 : _a.contains("custom-image-emoji")) || ((_b = child.classList) == null ? void 0 : _b.contains("mention"))) {
            text += child.nodeValue || child.alt || child.innerHTML || "";
            if (((_c = child.classList) == null ? void 0 : _c.contains("mention")) && child.id && !(atUserList == null ? void 0 : atUserList.includes(child.id))) {
              atUserList.push(child.id);
            }
          }
        }
      } catch (error) {
        if (error instanceof Error) {
          throw error;
        }
      }
      return [
        {
          type: "text",
          payload: {
            text,
            atUserList
          }
        }
      ];
    }
    function addEmoji(emojiData) {
      var _a, _b, _c, _d, _e;
      if (env.isPC) {
        (_a = editor == null ? void 0 : editor.commands) == null ? void 0 : _a.insertContent({
          type: "custom-image",
          attrs: {
            src: emojiData == null ? void 0 : emojiData.url,
            alt: emojiData == null ? void 0 : emojiData.emoji.key,
            title: emojiData == null ? void 0 : emojiData.emoji.key,
            class: "emoji"
          }
        });
      } else {
        const emojiImgNode = document.createElement("img");
        emojiImgNode == null ? void 0 : emojiImgNode.setAttribute("src", emojiData == null ? void 0 : emojiData.url);
        emojiImgNode == null ? void 0 : emojiImgNode.setAttribute("class", "custom-image custom-image-emoji");
        emojiImgNode == null ? void 0 : emojiImgNode.setAttribute("alt", emojiData == null ? void 0 : emojiData.emoji.key);
        emojiImgNode == null ? void 0 : emojiImgNode.setAttribute("title", emojiData == null ? void 0 : emojiData.emoji.key);
        emojiImgNode == null ? void 0 : emojiImgNode.setAttribute("width", "20px");
        emojiImgNode == null ? void 0 : emojiImgNode.setAttribute("height", "20px");
        (_b = editorDom.value) == null ? void 0 : _b.appendChild(emojiImgNode);
        const spanNode = document.createElement("span");
        spanNode.contentEditable = "true";
        (_c = editorDom.value) == null ? void 0 : _c.appendChild(spanNode);
      }
      if (!env.isH5) {
        (_d = editor == null ? void 0 : editor.commands) == null ? void 0 : _d.focus();
        (_e = editor == null ? void 0 : editor.commands) == null ? void 0 : _e.scrollIntoView();
      }
    }
    function blur() {
      var _a, _b;
      env.isPC ? (_a = editor == null ? void 0 : editor.commands) == null ? void 0 : _a.blur() : (_b = editorDom.value) == null ? void 0 : _b.blur();
    }
    function resetEditor() {
      var _a;
      (_a = editor == null ? void 0 : editor.commands) == null ? void 0 : _a.clearContent(true);
      isEditorBlur.value = true;
      isEditorEmpty.value = true;
      env.isH5 && (editorDom.value.innerHTML = "");
    }
    function getEditorHTML() {
      if (env.isPC) {
        return editor == null ? void 0 : editor.getHTML();
      }
      return editorDom.value.innerHTML;
    }
    function setEditorContent(content) {
      var _a;
      if (env.isPC) {
        (_a = editor == null ? void 0 : editor.commands) == null ? void 0 : _a.setContent(content);
      } else {
        editorDom.value.innerHTML = content;
      }
    }
    function insertEditorContent(content) {
      const selection = window.getSelection();
      if (selection && selection.rangeCount) {
        const currentRange = selection.getRangeAt(0);
        content.forEach((item) => {
          const newNode = item.type === "image" ? createEmojiNode(item.emojiKey || "", item.content) : createTextNode(item.content);
          currentRange.insertNode(newNode);
          currentRange.setStartAfter(newNode);
          if (item.type === "image" && env.isH5) {
            const textNode = document.createElement("span");
            textNode.contentEditable = "true";
            currentRange.insertNode(textNode);
            currentRange.setStartAfter(textNode);
          }
        });
        currentRange.collapse(false);
        selection.removeAllRanges();
        selection.addRange(currentRange);
      }
    }
    function createTextNode(text) {
      return document.createTextNode(text);
    }
    function createEmojiNode(key, url) {
      const imgNode = document.createElement("img");
      imgNode.src = url;
      imgNode.alt = key || "";
      imgNode.classList.add("custom-image", "custom-image-emoji");
      imgNode.width = 20;
      imgNode.height = 20;
      return imgNode;
    }
    function scrollToCaret(el) {
      const selection = window.getSelection();
      if (selection && selection.rangeCount > 0) {
        const range = selection.getRangeAt(0);
        const newRange = document.createRange();
        const emptyPlaceholder = "​";
        const textNode = document.createTextNode(emptyPlaceholder);
        newRange.setStart(range.startContainer, range.startOffset);
        newRange.insertNode(textNode);
        const rect = newRange.getBoundingClientRect();
        if (textNode.parentNode) {
          textNode.parentNode.removeChild(textNode);
        }
        el.scrollTop = rect.top - el.getBoundingClientRect().top;
      }
    }
    Vue.watch(
      () => [isEditorEmpty.value, isEditorBlur.value],
      (newVal, oldVal) => {
        if (newVal !== oldVal) {
          emits("onTyping", isEditorEmpty.value, isEditorBlur.value);
        }
      },
      {
        immediate: true,
        deep: true
      }
    );
    __expose({
      getEditorContent,
      addEmoji,
      resetEditor,
      insertAt,
      setEditorContent,
      getEditorHTML,
      insertEditorContent,
      blur
    });
    return (_ctx, _cache) => {
      return Vue.openBlock(), Vue.createElementBlock("div", {
        class: Vue.normalizeClass(["message-input-editor-container", Vue.unref(env.isH5) && "message-input-editor-container-h5"])
      }, [
        __props.isMuted ? (Vue.openBlock(), Vue.createElementBlock("div", _hoisted_1, Vue.toDisplayString(__props.muteText), 1)) : Vue.createCommentVNode("", true),
        !__props.isMuted && __props.enableInput ? (Vue.openBlock(), Vue.createElementBlock("div", {
          key: 1,
          ref_key: "editorDom",
          ref: editorDom,
          class: "message-input-editor-area",
          contenteditable: Vue.unref(env.isH5),
          onKeydown: Vue.withKeys(handleEnter, ["enter"]),
          onDrop: handlePCFileDrop,
          onPaste: handlePaste,
          onInput: handleH5Input,
          onBlur: handleH5Blur,
          onFocus: handleH5Focus
        }, null, 40, _hoisted_2)) : Vue.createCommentVNode("", true)
      ], 2);
    };
  }
});
exports.default = _sfc_main;
