<template>
  <!-- <div ref="svgRef" data-zoom-on-wheel="zoom-amount: 0.01; min-scale: 0.3; max-scale: 20;"
  data-pan-on-drag v-html="svg" :class="props.class"></div> -->
  <div ref="svgRef" v-html="svg" :class="props.class"></div>
</template>

<script setup>
import { onMounted, onUnmounted, ref, toRaw, nextTick } from "vue";
import { render, init } from "./mermaid";
import svgPanZoom from 'svg-pan-zoom';

//get mermaid settings
import { useData } from "vitepress";

const pluginSettings = ref({
  securityLevel: "loose",
  startOnLoad: false,
  externalDiagrams: [],
});
const svgRef = ref(null)
const { page } = useData();
const { frontmatter } = toRaw(page.value);
const mermaidPageTheme = frontmatter.mermaidTheme || "";

const props = defineProps({
  graph: {
    type: String,
    required: true,
  },
  id: {
    type: String,
    required: true,
  },
  class:{
    type: String,
    required: false,
    default: "mermaid",
  },
  zoomable:{
    type: Boolean,
    required: false,
    default: false,
  }
});

const svg = ref(null);
let mut = null;
let panZoomTiger;


function makePanZoom(svg) {
  const height = svg.getBBox().height;
  const aHeight = height > 600 ? 600 : height;
  svg.setAttribute('style', 'height: ' + aHeight + 'px;overflow:scroll;');

  if (!panZoomTiger) {
    panZoomTiger = svgPanZoom(`#${props.id}`, {
      zoomEnabled: true,
      controlIconsEnabled: false,
      fit: true,
      minZoom: 0.8
    });
  }
  panZoomTiger.updateBBox();
  panZoomTiger.resize();
  panZoomTiger.fit(); // fit works as expected
}


onMounted(async () => {
  await init(pluginSettings.value.externalDiagrams);
  let settings = await import("virtual:mermaid-config");
  if (settings?.default) pluginSettings.value = settings.default;

  mut = new MutationObserver(async () => await renderChart());
  mut.observe(document.documentElement, { attributes: true });
  await renderChart();
  //refresh images on first render
  const hasImages =
    /<img([\w\W]+?)>/.exec(decodeURIComponent(props.graph))?.length > 0;
  if (hasImages)
    setTimeout(() => {
      let imgElements = document.getElementsByTagName("img");
      let imgs = Array.from(imgElements);
      if (imgs.length) {
        Promise.all(
          imgs
            .filter((img) => !img.complete)
            .map(
              (img) =>
                new Promise((resolve) => {
                  img.onload = img.onerror = resolve;
                })
            )
        ).then(async () => {
          await renderChart();
        });
      }
    }, 100);
});

onUnmounted(() => {
  panZoomTiger && panZoomTiger.destroy();
  mut.disconnect();
});

const renderChart = async () => {
  const hasDarkClass = document.documentElement.classList.contains("dark");
  let mermaidConfig = {
    ...pluginSettings.value,
  };

  if (mermaidPageTheme) mermaidConfig.theme = mermaidPageTheme;
  if (hasDarkClass) mermaidConfig.theme = "dark";

  let svgCode = await render(
    props.id,
    decodeURIComponent(props.graph),
    mermaidConfig
  );
  // This is a hack to force v-html to re-render, otherwise the diagram disappears
  // when **switching themes** or **reloading the page**.
  // The cause is that the diagram is deleted during rendering (out of Vue's knowledge).
  // Because svgCode does NOT change, v-html does not re-render.
  // This is not required for all diagrams, but it is required for c4c, mindmap and zenuml.
  const salt = Math.random().toString(36).substring(7);
  svg.value = `${svgCode} <span style="display: none">${salt}</span>`;
  nextTick(function () {
    if (props.zoomable) {
      makePanZoom(svgRef.value.querySelector('svg'))
    }
  })
};
</script>

<style>
[data-zoom-on-wheel] {
  overflow: auto !important;
}
</style>