import { insertTagToEditor } from "./utils";
// import { randomCode } from "../../utils/utils";

let _this = null;

export function dataUrlToBlob(base64Buf) {
  console.log(base64Buf);
  const bufs = base64Buf.split(".");
  const mime = bufs[0].match(/:(.*?);/)[1];
  const bstr = window.atob(bufs[1]);
  const len = bstr.length;
  const u8arr = new Uint8Array(len);
  for (let i = 0; i < len; i++) {
    u8arr[i] = bstr.charCodeAt(i);
  }
  return new Blob([u8arr], { type: mime });
}

function fileToBase64(file) {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.readAsDataURL(file);
    reader.onload = () => resolve(reader.result);
    reader.onerror = (error) => reject(error);
  });
}

function getDataUrlFromImageUrl(url) {
  const img = new Image();
  img.setAttribute("crossorigin", "anonymous");
  img.src = url;

  return new Promise((resolve, reject) => {
    const canvas = document.createElement("canvas");
    const ctx = canvas.getContext("2d");
    canvas.width = img.width;
    canvas.height = img.height;
    // console.dir(img);
    img.onload = function () {
      ctx.drawImage(img, 0, 0);
      resolve(canvas.toDataURL("image/png"));
    };
    img.onerror = function (err) {
      reject(err);
    };
  });
}

function dataItemGetAsString(dataTransferItem) {
  return new Promise((resolve, reject) => {
    try {
      dataTransferItem.getAsString((s) => {
        resolve(s);
      });
    } catch (error) {
      reject(error);
    }
  });
}

// function checkHtmlIsFromOffice(htmlDom) {
//   const meta = htmlDom.querySelector("meta[name='Originator']");
//   return meta && meta.getAttribute("content").includes("Microsoft Word");
// }

function checkDomIsBlock(dom) {
  if (dom.nodeType === Node.ELEMENT_NODE) {
    const disPlay = window.getComputedStyle(dom).display;
    if (disPlay) {
      return disPlay === "block";
    } else {
      const blockDomNames = [
        "div",
        "p",
        "h1",
        "h2",
        "h3",
        "h4",
        "h5",
        "h6",
        "ul",
        "ol",
        "table",
        "tr",
      ];
      return blockDomNames.includes(dom.tagName.toLowerCase());
    }
  }
}

function checkDomHasTextContent(content) {
  let cont = content.replace(/\n/g, "");
  return !!cont;
}

function checkDomIsUnvalid(dom) {
  const unvalidFunc = [
    (node) =>
      node.tagName &&
      ["meta", "link", "script", "style", "title"].includes(
        node.tagName.toLowerCase()
      ),
    (node) => node.nodeType === Node.COMMENT_NODE,
  ];

  return unvalidFunc.some((unfunc) => unfunc(dom));
}

function getHtmlValidDom(htmlDom, checkBlock) {
  let doms = [];
  let curBlockDoms = [];

  const findDom = (nodeList) => {
    nodeList.forEach((node) => {
      if (checkDomIsUnvalid(node)) return;

      if (checkBlock && checkDomIsBlock(node) && curBlockDoms.length) {
        doms.push(curBlockDoms);
        curBlockDoms = [];
      }

      if (node.childNodes.length) {
        findDom(node.childNodes);
        return;
      }

      if (
        (node.tagName && node.tagName.toLowerCase() === "img") ||
        (node.nodeType === Node.TEXT_NODE &&
          checkDomHasTextContent(node.textContent))
      ) {
        curBlockDoms.push(node);
      }
    });
  };

  findDom(htmlDom.childNodes);

  if (curBlockDoms.length) {
    doms.push(curBlockDoms);
    curBlockDoms = [];
  }
  console.log(doms);
  return doms;
}

// function getOfficeHtmlValidDom(htmlDom) {
//   let doms = [];
//   htmlDom.querySelectorAll("p").forEach((pDom) => {
//     const elems = getHtmlValidDom(pDom, false);
//     if (elems.length) doms.push(...elems);
//   });
//   return doms;
// }

async function pasteHtmlItem(htmlItem) {
  const cont = await dataItemGetAsString(htmlItem).catch((e) => {
    console.log(e);
  });
  if (!cont) return;

  const divDom = document.createElement("div");
  divDom.innerHTML = cont;
  console.log(divDom);

  const groups = getHtmlValidDom(divDom, true);

  for (let i = 0; i < groups.length; i++) {
    for (let j = 0; j < groups[i].length; j++) {
      const element = groups[i][j];
      if (element.tagName && element.tagName.toLowerCase() === "img") {
        await pasteImageDom(element);
      } else {
        document.execCommand("insertText", false, element.textContent);
      }
    }
    document.execCommand("insertParagraph");
  }
}

async function pasteImageDom(imgDom) {
  console.log(imgDom);
  const src = imgDom.getAttribute("src");
  if (!src) return;
  let attributes = {};
  if (imgDom.getAttribute("width"))
    attributes.width = imgDom.getAttribute("width");
  if (imgDom.getAttribute("height"))
    attributes.height = imgDom.getAttribute("height");

  if (src.includes("base64")) {
    insertTagToEditor(null, "IMG", src, attributes);
  } else if (
    src.includes("http://") ||
    src.includes("https://") ||
    src.includes("file:///")
  ) {
    const dataUrl = await getDataUrlFromImageUrl(src).catch(() => {});
    // console.log(dataUrl);
    if (!dataUrl) return;
    insertTagToEditor(null, "IMG", dataUrl, attributes);
  } else {
    console.log("unknown image url");
  }
}

async function pasteImage(file, attributes) {
  if (file.size > _this.maxImageSize) {
    _this.$message(`单张图片超过限制，最大为 ${_this.maxImageSize / 1024} KB.`);
    return;
  }

  // 默认转base64;
  const srcBase64 = await fileToBase64(file);
  insertTagToEditor(null, "IMG", srcBase64, attributes);
}

async function pasteText(textItem) {
  const cont = await dataItemGetAsString(textItem).catch((e) => {
    console.log(e);
  });
  if (!cont) return;

  document.execCommand("insertText", false, cont);
}

function filterItem(dataItems, filterFunc) {
  let data = [];
  for (let index = 0; index < dataItems.length; index++) {
    if (filterFunc(dataItems[index])) data.push(dataItems[index]);
  }
  return data;
}

export async function pasteHandle(event) {
  _this = this;
  // 禁止默认粘贴
  event.preventDefault();
  const clipboard = event.clipboardData;

  const htmlItems = filterItem(
    clipboard.items,
    (item) => item.kind == "string" && item.type.match("^text/html")
  );
  if (htmlItems.length) {
    console.log("... paste: html ");
    for (let index = 0; index < htmlItems.length; index++) {
      await pasteHtmlItem(htmlItems[index]);
    }
    _this.$refs.editor.dispatchEvent(new Event("input"));
    return;
  }

  const fileItems = filterItem(
    clipboard.items,
    (item) => item.kind == "file" && item.type.match("^image/")
  );
  if (fileItems.length) {
    console.log("... paste: file ");
    for (let index = 0; index < fileItems.length; index++) {
      const file = fileItems[index].getAsFile();
      await pasteImage(file);
    }
    _this.$refs.editor.dispatchEvent(new Event("input"));
    return;
  }

  for (var i = 0; i < clipboard.items.length; i++) {
    const clipboardItem = clipboard.items[i];
    if (
      clipboardItem.kind == "string" &&
      clipboardItem.type.match("^text/plain")
    ) {
      console.log("... paste: text ");
      await pasteText(clipboardItem);
    } else {
      console.log("... paste: other ");
    }
  }
}
