import { getConfig, log } from './mermaidUtils.js';
import ZenUml from '@zenuml/core';

const regexp = /^\s*zenuml/;

// Create a Zen UML container outside the svg first for rendering, otherwise the Zen UML diagram cannot be rendered properly
function createTemporaryZenumlContainer(id: string) {
  const container = document.createElement('div');
  container.id = `container-${id}`;
  container.style.display = 'flex';
  container.innerHTML = `<div id="zenUMLApp-${id}"></div>`;
  const app = container.querySelector(`#zenUMLApp-${id}`)!;
  return { container, app };
}

// Create a foreignObject to wrap the Zen UML container in the svg
function createForeignObject(id: string) {
  const foreignObject = document.createElementNS('http://www.w3.org/2000/svg', 'foreignObject');
  foreignObject.setAttribute('x', '0');
  foreignObject.setAttribute('y', '0');
  foreignObject.setAttribute('width', '100%');
  foreignObject.setAttribute('height', '100%');
  const { container, app } = createTemporaryZenumlContainer(id);
  foreignObject.appendChild(container);
  return { foreignObject, container, app };
}

/**
 * Draws a Zen UML in the tag with id: id based on the graph definition in text.
 *
 * @param text - The text of the diagram
 * @param id - The id of the diagram which will be used as a DOM element id¨
 */
export const draw = async function (text: string, id: string) {
  log.info('draw with Zen UML renderer', ZenUml);

  text = text.replace(regexp, '');
  const { securityLevel } = getConfig();
  // Handle root and Document for when rendering in sandbox mode
  let sandboxElement: HTMLIFrameElement | null = null;
  if (securityLevel === 'sandbox') {
    sandboxElement = document.getElementById('i' + id) as HTMLIFrameElement;
  }

  const root = securityLevel === 'sandbox' ? sandboxElement?.contentWindow?.document : document;

  const svgContainer = root?.querySelector(`svg#${id}`);

  if (!root || !svgContainer) {
    log.error('Cannot find root or svgContainer');
    return;
  }

  const { foreignObject, container, app } = createForeignObject(id);
  svgContainer.appendChild(foreignObject);
  // @ts-expect-error @zenuml/core@3.0.0 exports the wrong type for ZenUml
  const zenuml = new ZenUml(app);
  // default is a theme name. More themes to be added and will be configurable in the future
  await zenuml.render(text, { theme: 'default', mode: 'static' });

  const { width, height } = window.getComputedStyle(container);
  log.debug('zenuml diagram size', width, height);
  svgContainer.setAttribute('style', `width: ${width}; height: ${height};`);
};

export default {
  draw,
};
