import XEUtils from "xe-utils";
import { toCssUnit } from "../../ui/src/dom.mjs";
let canvasEl = null;
let fontEl = null;
const fontCacheMaps = {};
function getMarkCanvas() {
  if (!canvasEl) {
    canvasEl = document.createElement("canvas");
    canvasEl.style.position = "absolute";
    canvasEl.style.top = "0";
    canvasEl.style.left = "0";
  }
  return canvasEl;
}
function removeMarkElement(elem) {
  if (elem) {
    const parentEl = elem.parentNode;
    if (parentEl) {
      parentEl.removeChild(elem);
    }
  }
}
function calcFontWH(text, fontSize) {
  const fKey = `${fontSize}_${text}`;
  if (!fontCacheMaps[fKey]) {
    if (!fontEl) {
      fontEl = document.createElement("span");
    }
    if (!fontEl.parentNode) {
      document.body.append(fontEl);
    }
    fontEl.textContent = text;
    fontEl.style.fontSize = toCssUnit(fontSize);
    const width = fontEl.offsetWidth;
    const height = fontEl.offsetHeight;
    fontCacheMaps[fKey] = {
      width,
      height
    };
  }
  return fontCacheMaps[fKey];
}
function calcContentWH(contList) {
  let contentWidth = 0;
  let contentHeight = 0;
  contList.forEach((item) => {
    contentWidth = Math.max(item.width, contentWidth);
    contentHeight = Math.max(item.height, contentHeight);
  });
  return {
    contentWidth,
    contentHeight
  };
}
function calcCanvasWH(contentWidth, opts) {
  const { gap } = opts;
  const [gapX = 0, gapY = 0] = gap ? XEUtils.isArray(gap) ? gap : [gap, gap] : [];
  const canvasWidth = contentWidth + XEUtils.toNumber(gapX);
  const canvasHeight = contentWidth + XEUtils.toNumber(gapY);
  return {
    canvasWidth,
    canvasHeight
  };
}
function getFontConf(item, key, opts) {
  return (item.font ? item.font[key] : "") || (opts.font ? opts.font[key] : "");
}
function createMarkFont(contConf, defaultFontSize, opts) {
  const { offset } = opts;
  const text = XEUtils.toValueString(contConf.textContent);
  const fontSize = XEUtils.toNumber(getFontConf(contConf, "fontSize", opts) || defaultFontSize) || 14;
  const [offsetX = 0, offsetY = 0] = offset ? XEUtils.isArray(offset) ? offset : [offset, offset] : [];
  const { width, height } = calcFontWH(text, fontSize);
  return {
    text,
    fontSize,
    font: contConf.font,
    width: width + XEUtils.toNumber(offsetX),
    height: height + XEUtils.toNumber(offsetY)
  };
}
function drayFont(ctx, item, opts) {
  const fontWeight = getFontConf(item, "fontWeight", opts);
  ctx.fillStyle = `${getFontConf(item, "color", opts) || "rgba(0, 0, 0, 0.15)"}`;
  ctx.font = [
    getFontConf(item, "fontStyle", opts) || "normal",
    fontWeight === "bold" || fontWeight === "bolder" ? "bold" : "",
    toCssUnit(item.fontSize),
    getFontConf(item, "fontFamily", opts) || "sans-serif"
  ].join(" ");
}
function getContentUrl(content, defaultFontSize, options) {
  const opts = Object.assign({}, options);
  const { rotate } = opts;
  const deg = XEUtils.toNumber(rotate);
  const contList = (XEUtils.isArray(content) ? content : [content]).map((item) => {
    if (item) {
      if (item.textContent) {
        return createMarkFont(item, defaultFontSize, opts);
      }
      return createMarkFont({
        textContent: `${item}`
      }, defaultFontSize, opts);
    }
    return createMarkFont({
      textContent: ""
    }, defaultFontSize, opts);
  });
  removeMarkElement(fontEl);
  return new Promise((resolve) => {
    const canvasEl2 = getMarkCanvas();
    if (!canvasEl2.parentNode) {
      document.body.append(canvasEl2);
    }
    const ctx = canvasEl2.getContext("2d");
    if (ctx && contList.length) {
      const { contentWidth, contentHeight } = calcContentWH(contList);
      const { canvasWidth, canvasHeight } = calcCanvasWH(contentWidth, opts);
      canvasEl2.width = canvasWidth;
      canvasEl2.height = canvasHeight;
      const x = (canvasWidth - contentWidth) / 2;
      const y = (canvasHeight - contentHeight) / 2;
      const drayX = x + contentWidth / 2;
      const drayY = y + contentHeight / 2;
      ctx.save();
      ctx.translate(drayX, drayY);
      ctx.rotate(deg * Math.PI / 180);
      ctx.translate(-drayX, -drayY);
      let offsetHeight = 0;
      contList.forEach((item) => {
        const align = getFontConf(item, "align", opts);
        drayFont(ctx, item, opts);
        ctx.fillText(item.text, x + (align === "center" ? (contentWidth - item.width) / 2 : 0), y + (contentHeight + contentHeight) / 2 + offsetHeight, contentWidth);
        offsetHeight += item.height;
      });
      ctx.restore();
      resolve(canvasEl2.toDataURL());
      removeMarkElement(canvasEl2);
    } else {
      resolve("");
      removeMarkElement(canvasEl2);
    }
  });
}
export {
  getContentUrl
};
