<script>
import { computed, defineComponent, h } from "vue";
import { md } from "../../../utils/markdown";
import { TRIGGER_CLASS } from "../../../utils/markdown-tooltip";
import { Tooltip, TooltipContent, TooltipTrigger } from "../tooltip";
const hasTooltip = (tokens) => {
  for (const tok of tokens) {
    if (tok.type === "tooltip") return true;
    if (tok.children && hasTooltip(tok.children)) return true;
  }
  return false;
};
const tokenAttrs = (tok) => {
  if (!tok.attrs) return {};
  const out = {};
  for (const [name, value] of tok.attrs) out[name] = value;
  return out;
};
const renderTooltip = (tok) => {
  const meta = tok.meta;
  return h(Tooltip, { delayDuration: 180 }, () => [
    h(TooltipTrigger, { asChild: true }, () => h("span", {
      class: TRIGGER_CLASS,
      innerHTML: md.renderInline(meta.trigger)
    })),
    h(TooltipContent, { class: "max-w-xs text-xs" }, () => h("span", {
      class: "prose prose-zinc text-xs",
      innerHTML: md.render(meta.content)
    }))
  ]);
};
const renderInlineChildren = (children) => {
  const vnodes = [];
  let bufferStart = 0;
  for (let i = 0; i <= children.length; i++) {
    const tok = children[i];
    const isTooltip = tok?.type === "tooltip";
    if (!tok || isTooltip) {
      if (i > bufferStart) {
        const run = children.slice(bufferStart, i);
        const html = md.renderer.render(run, md.options, {});
        vnodes.push(h("span", { innerHTML: html }));
      }
      if (tok && isTooltip) {
        vnodes.push(renderTooltip(tok));
        bufferStart = i + 1;
      }
    }
  }
  return vnodes;
};
const findMatchingClose = (tokens, openIdx) => {
  let depth = 1;
  for (let i = openIdx + 1; i < tokens.length; i++) {
    const tok = tokens[i];
    if (tok.nesting === 1) depth++;
    else if (tok.nesting === -1) {
      depth--;
      if (depth === 0) return i;
    }
  }
  return tokens.length;
};
const renderBlockTokens = (tokens) => {
  const vnodes = [];
  let i = 0;
  while (i < tokens.length) {
    const tok = tokens[i];
    if (tok.nesting === 1) {
      const closeIdx = findMatchingClose(tokens, i);
      const children = tokens.slice(i + 1, closeIdx);
      vnodes.push(h(tok.tag || "div", tokenAttrs(tok), renderBlockTokens(children)));
      i = closeIdx + 1;
    } else if (tok.type === "inline") {
      vnodes.push(...renderInlineChildren(tok.children ?? []));
      i++;
    } else {
      const html = md.renderer.render([tok], md.options, {});
      vnodes.push(h("span", { innerHTML: html }));
      i++;
    }
  }
  return vnodes;
};
export default defineComponent({
  name: "UiMarkdown",
  props: {
    source: { type: String, required: true },
    block: { type: Boolean, default: false }
  },
  setup(props) {
    const rendered = computed(() => {
      if (props.block) {
        const tokens = md.parse(props.source, {});
        if (!hasTooltip(tokens)) return { fast: md.render(props.source) };
        return { vnodes: renderBlockTokens(tokens) };
      }
      const children = md.parseInline(props.source, {})[0]?.children ?? [];
      if (!hasTooltip(children)) return { fast: md.renderInline(props.source) };
      return { vnodes: renderInlineChildren(children) };
    });
    return () => {
      const r = rendered.value;
      if ("fast" in r) return h("span", { innerHTML: r.fast });
      return h("span", {}, r.vnodes);
    };
  }
});
</script>
