import useXComponentConfig from "../_utils/hooks/use-x-component-config.js";
import { isEmptyNode } from "../_utils/vue.js";
import warning from "../_utils/warning.js";
import ActionsWithSub from "../actions/index.js";
import localeValues from "../locale/en_US.js";
import useLocale from "../locale/useLocale.js";
import code_highlighter_default from "../code-highlighter/index.js";
import { initializeMermaid, parseMermaid, renderMermaid } from "./loader.js";
import style_default from "./style/index.js";
import { computed, createVNode, defineComponent, mergeProps, onBeforeUnmount, ref, useAttrs, watch } from "vue";
import { useConfig } from "antdv-next/config-provider/context";
import { Button, Segmented, Tooltip } from "antdv-next";
import { DownloadOutlined, ZoomInOutlined, ZoomOutOutlined } from "@antdv-next/icons";
//#region components/mermaid/Mermaid.tsx
var RenderType = /* @__PURE__ */ function(RenderType) {
	RenderType["Code"] = "code";
	RenderType["Image"] = "image";
	return RenderType;
}(RenderType || {});
var idSeed = 0;
function throttle(fn, wait) {
	let timer = null;
	let lastTime = 0;
	let pendingArgs = null;
	const run = (args) => {
		lastTime = Date.now();
		fn(...args);
	};
	const throttled = (...args) => {
		pendingArgs = args;
		const remaining = wait - (Date.now() - lastTime);
		if (remaining <= 0 || lastTime === 0) {
			if (timer !== null) {
				clearTimeout(timer);
				timer = null;
			}
			const execArgs = pendingArgs;
			pendingArgs = null;
			if (execArgs) run(execArgs);
			return;
		}
		if (timer === null) timer = setTimeout(() => {
			timer = null;
			const execArgs = pendingArgs;
			pendingArgs = null;
			if (execArgs) run(execArgs);
		}, remaining);
	};
	throttled.cancel = () => {
		if (timer !== null) {
			clearTimeout(timer);
			timer = null;
		}
		pendingArgs = null;
	};
	return throttled;
}
var XMermaid = /* @__PURE__ */ defineComponent({
	name: "AxMermaid",
	inheritAttrs: false,
	props: {
		content: {
			type: String,
			required: true
		},
		prefixCls: {
			type: String,
			default: "antd-mermaid"
		},
		rootClass: {
			type: String,
			default: ""
		},
		class: {
			type: [
				String,
				Object,
				Array
			],
			default: void 0
		},
		style: {
			type: [
				String,
				Object,
				Array
			],
			default: void 0
		},
		classes: {
			type: Object,
			default: () => ({})
		},
		styles: {
			type: Object,
			default: () => ({})
		},
		header: {
			type: [
				String,
				Number,
				Object,
				Array
			],
			default: void 0
		},
		renderType: {
			type: String,
			default: void 0
		},
		defaultRenderType: {
			type: String,
			default: RenderType.Image
		},
		config: {
			type: Object,
			default: void 0
		},
		actions: {
			type: Object,
			default: () => ({})
		},
		codeHighlighterProps: {
			type: Object,
			default: void 0
		}
	},
	emits: ["update:renderType", "renderTypeChange"],
	setup(props, { emit, expose, slots }) {
		const attrs = useAttrs();
		const configCtx = useConfig();
		const [contextLocale] = useLocale("Mermaid", localeValues.Mermaid);
		const contextConfig = useXComponentConfig("mermaid");
		const rootRef = ref();
		const graphRef = ref();
		const renderBaseId = `mermaid-${idSeed++}`;
		const [hashId, cssVarCls] = style_default(computed(() => props.prefixCls));
		const internalRenderType = ref(props.defaultRenderType);
		const scale = ref(1);
		const position = ref({
			x: 0,
			y: 0
		});
		const isDragging = ref(false);
		const lastMousePos = ref({
			x: 0,
			y: 0
		});
		const mergedRenderType = computed(() => {
			return props.renderType ?? internalRenderType.value;
		});
		const mergedActions = computed(() => {
			return {
				enableZoom: props.actions?.enableZoom ?? true,
				enableDownload: props.actions?.enableDownload ?? true,
				enableCopy: props.actions?.enableCopy ?? true,
				customActions: props.actions?.customActions ?? []
			};
		});
		const mergedClasses = computed(() => ({
			...contextConfig.value.classes,
			...props.classes
		}));
		const mergedStyles = computed(() => ({
			...contextConfig.value.styles,
			...props.styles
		}));
		const domAttrs = computed(() => {
			const { class: _class, style: _style, ...rest } = attrs;
			return rest;
		});
		const getNamedSlot = (name) => slots[name] ?? slots[name.replace(/[A-Z]/g, (s) => `-${s.toLowerCase()}`)];
		const resolvedCustomActions = computed(() => mergedActions.value.customActions.map((item, index) => {
			const iconSlotInfo = {
				item,
				index,
				originNode: item.icon
			};
			const iconFromSlot = getNamedSlot("customActionIconRender")?.(iconSlotInfo);
			const actionSlotInfo = {
				item,
				index,
				originNode: item.actionRender !== void 0 ? typeof item.actionRender === "function" ? item.actionRender(item) : item.actionRender : void 0
			};
			const actionFromSlot = getNamedSlot("customActionRender")?.(actionSlotInfo);
			return {
				...item,
				icon: iconFromSlot !== void 0 && !isEmptyNode(iconFromSlot) ? iconFromSlot : item.icon,
				actionRender: actionFromSlot !== void 0 && !isEmptyNode(actionFromSlot) ? actionFromSlot : item.actionRender
			};
		}));
		function applySvgTransform() {
			if (mergedRenderType.value !== RenderType.Image) return;
			const svgEl = graphRef.value?.querySelector("svg");
			if (!svgEl) return;
			svgEl.style.transform = `scale(${scale.value}) translate(${position.value.x}px, ${position.value.y}px)`;
			svgEl.style.transformOrigin = "center";
			svgEl.style.transition = isDragging.value ? "none" : "transform 0.1s ease-out";
			svgEl.style.cursor = isDragging.value ? "grabbing" : "grab";
		}
		const renderDiagram = throttle(async () => {
			if (mergedRenderType.value === RenderType.Code) {
				if (graphRef.value) graphRef.value.innerHTML = "";
				return;
			}
			if (!props.content?.trim()) return;
			const graphEl = graphRef.value;
			if (!graphEl) return;
			try {
				if (await parseMermaid(props.content, { suppressErrors: true }) === false) throw new Error("Invalid Mermaid syntax");
				const { svg } = await renderMermaid(`${renderBaseId}-${idSeed++}-${props.content.length || 0}`, props.content);
				graphEl.innerHTML = svg;
				applySvgTransform();
			} catch (error) {
				warning(false, "Mermaid", `Render failed: ${String(error)}`);
			}
		}, 100);
		function switchRenderType(nextType) {
			if (props.renderType === void 0) internalRenderType.value = nextType;
			emit("update:renderType", nextType);
			emit("renderTypeChange", nextType);
		}
		function handleMouseDown(event) {
			if (mergedRenderType.value !== RenderType.Image) return;
			event.preventDefault();
			isDragging.value = true;
			lastMousePos.value = {
				x: event.clientX,
				y: event.clientY
			};
		}
		function handleMouseMove(event) {
			if (!isDragging.value) return;
			if (mergedRenderType.value !== RenderType.Image) return;
			event.preventDefault();
			const deltaX = event.clientX - lastMousePos.value.x;
			const deltaY = event.clientY - lastMousePos.value.y;
			position.value = {
				x: position.value.x + deltaX / scale.value,
				y: position.value.y + deltaY / scale.value
			};
			lastMousePos.value = {
				x: event.clientX,
				y: event.clientY
			};
		}
		function handleMouseUp() {
			isDragging.value = false;
		}
		function handleZoomIn() {
			scale.value = Math.min(scale.value + .2, 3);
		}
		function handleZoomOut() {
			scale.value = Math.max(scale.value - .2, .5);
		}
		function handleReset() {
			scale.value = 1;
			position.value = {
				x: 0,
				y: 0
			};
		}
		function handleDownload() {
			const svgElement = graphRef.value?.querySelector("svg");
			if (!svgElement) return;
			const svgString = new XMLSerializer().serializeToString(svgElement);
			const canvas = document.createElement("canvas");
			const ctx = canvas.getContext("2d");
			if (!ctx) return;
			const { width, height } = svgElement.getBoundingClientRect();
			const dpr = globalThis.window?.devicePixelRatio || 1;
			canvas.width = width * dpr;
			canvas.height = height * dpr;
			canvas.style.width = `${width}px`;
			canvas.style.height = `${height}px`;
			ctx.scale(dpr, dpr);
			const img = new Image();
			img.onload = () => {
				ctx.drawImage(img, 0, 0, width, height);
				const link = document.createElement("a");
				link.download = `${Date.now()}.png`;
				link.href = canvas.toDataURL("image/png", 1);
				link.click();
			};
			img.src = `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svgString)}`;
		}
		const defaultHeaderActions = computed(() => {
			const items = [];
			if (mergedRenderType.value === RenderType.Image) {
				if (mergedActions.value.enableZoom) items.push({
					key: "zoomIn",
					icon: createVNode(ZoomInOutlined, null, null),
					label: contextLocale.value.zoomIn,
					onItemClick: handleZoomIn
				}, {
					key: "zoomOut",
					icon: createVNode(ZoomOutOutlined, null, null),
					label: contextLocale.value.zoomOut,
					onItemClick: handleZoomOut
				}, {
					key: "zoomReset",
					actionRender: () => createVNode(Tooltip, { "title": contextLocale.value.zoomReset }, { default: () => [createVNode(Button, {
						"type": "text",
						"size": "small",
						"onClick": handleReset
					}, { default: () => [contextLocale.value.zoomReset] })] })
				});
				if (mergedActions.value.enableDownload) items.push({
					key: "download",
					icon: createVNode(DownloadOutlined, null, null),
					label: contextLocale.value.download,
					onItemClick: handleDownload
				});
			}
			if (mergedRenderType.value === RenderType.Code && mergedActions.value.enableCopy) items.push({
				key: "copy",
				actionRender: () => createVNode(ActionsWithSub.Copy, { "text": props.content }, null)
			});
			return [...items, ...resolvedCustomActions.value];
		});
		function renderHeader() {
			if (props.header === null) return null;
			if (slots.header) return slots.header();
			if (props.header !== void 0) return props.header;
			return createVNode("div", {
				"class": [`${props.prefixCls}-header`, mergedClasses.value.header],
				"style": mergedStyles.value.header
			}, [createVNode(Segmented, {
				"options": [{
					label: contextLocale.value.image,
					value: RenderType.Image
				}, {
					label: contextLocale.value.code,
					value: RenderType.Code
				}],
				"value": mergedRenderType.value,
				"onChange": (value) => switchRenderType(value)
			}, null), createVNode(ActionsWithSub, { "items": defaultHeaderActions.value }, null)]);
		}
		watch(() => props.renderType, (next) => {
			if (next !== void 0) internalRenderType.value = next;
		});
		watch(() => props.config, (nextConfig) => {
			initializeMermaid({
				startOnLoad: false,
				securityLevel: "strict",
				theme: "default",
				fontFamily: "monospace",
				suppressErrorRendering: true,
				...nextConfig
			});
		}, {
			immediate: true,
			deep: true
		});
		watch([
			() => props.content,
			() => props.config,
			mergedRenderType,
			() => graphRef.value
		], () => {
			if (!graphRef.value) return;
			renderDiagram();
		}, {
			immediate: true,
			deep: true
		});
		watch([
			mergedRenderType,
			() => mergedActions.value.enableZoom,
			() => graphRef.value
		], ([currentRenderType, enableZoom], _prev, onCleanup) => {
			const graphEl = graphRef.value;
			if (!graphEl) return;
			if (currentRenderType !== RenderType.Image || enableZoom === false) return;
			let lastTime = 0;
			const wheelHandler = (event) => {
				event.preventDefault();
				event.stopPropagation();
				const now = Date.now();
				if (now - lastTime < 16) return;
				lastTime = now;
				const delta = event.deltaY > 0 ? -.1 : .1;
				scale.value = Math.max(.5, Math.min(3, scale.value + delta));
			};
			graphEl.addEventListener("wheel", wheelHandler, { passive: false });
			onCleanup(() => {
				graphEl.removeEventListener("wheel", wheelHandler);
			});
		}, { immediate: true });
		watch([
			scale,
			position,
			mergedRenderType,
			isDragging
		], () => {
			applySvgTransform();
		}, { deep: true });
		onBeforeUnmount(() => {
			renderDiagram.cancel();
		});
		expose({ get nativeElement() {
			return rootRef.value;
		} });
		return () => {
			if (!props.content) return null;
			return createVNode("div", mergeProps({ "ref": rootRef }, domAttrs.value, {
				"class": [
					props.prefixCls,
					contextConfig.value.classes?.root,
					props.rootClass,
					mergedClasses.value.root,
					hashId.value,
					cssVarCls.value,
					attrs.class,
					props.class,
					{ [`${props.prefixCls}-rtl`]: configCtx.value.direction === "rtl" }
				],
				"style": [
					contextConfig.value.style,
					contextConfig.value.styles?.root,
					mergedStyles.value.root,
					attrs.style,
					props.style
				]
			}), [
				renderHeader(),
				createVNode("div", {
					"ref": graphRef,
					"class": [
						`${props.prefixCls}-graph`,
						mergedRenderType.value === RenderType.Code && `${props.prefixCls}-graph-hidden`,
						mergedClasses.value.graph
					],
					"style": mergedStyles.value.graph,
					"onMousedown": handleMouseDown,
					"onMousemove": handleMouseMove,
					"onMouseup": handleMouseUp,
					"onMouseleave": handleMouseUp
				}, null),
				mergedRenderType.value === RenderType.Code ? createVNode("div", {
					"class": [`${props.prefixCls}-code`, mergedClasses.value.code],
					"style": mergedStyles.value.code
				}, [createVNode(code_highlighter_default, mergeProps({
					"showLineNumbers": false,
					"showLanguage": false,
					"showThemeToggle": false
				}, props.codeHighlighterProps, {
					"content": props.content,
					"language": "mermaid",
					"showCopyButton": false,
					"styles": {
						root: {
							border: "none",
							borderRadius: 0
						},
						content: { backgroundColor: "transparent" },
						code: {
							backgroundColor: "transparent",
							maxHeight: "100%"
						},
						...props.codeHighlighterProps?.styles
					}
				}), null)]) : null
			]);
		};
	}
});
//#endregion
export { XMermaid as default };
