import { toJpeg, toPng, toSvg } from "html-to-image";
function getCanvasBackgroundColor() {
    const reactFlowElement = document.querySelector('.react-flow');
    if (reactFlowElement) {
        const color = getComputedStyle(reactFlowElement).getPropertyValue('--canvas-background').trim();
        if (color) return color;
    }
    return '#ffffff';
}
const RENDER_STABILIZATION_DELAY_MS = 300;
const DEFAULT_OPTIONS = {
    width: 1920,
    height: 1080,
    fitToContent: true,
    backgroundColor: void 0,
    format: 'png',
    quality: 0.95,
    minZoom: 0.01,
    maxZoom: 2,
    padding: 0.05,
    viewportSelector: '.react-flow__viewport',
    includeImages: true,
    pixelRatio: 3,
    skipFonts: false
};
function getExportFunction(format) {
    switch(format){
        case 'jpeg':
            return toJpeg;
        case 'svg':
            return toSvg;
        case 'png':
        default:
            return toPng;
    }
}
function getFileExtension(format) {
    return 'jpeg' === format ? 'jpg' : format;
}
function getMimeType(format) {
    switch(format){
        case 'jpeg':
            return 'image/jpeg';
        case 'svg':
            return 'image/svg+xml';
        case 'png':
        default:
            return 'image/png';
    }
}
function wait(ms) {
    return new Promise((resolve)=>setTimeout(resolve, ms));
}
function yieldToMain() {
    return new Promise((resolve)=>{
        setTimeout(resolve, 0);
    });
}
const DEFAULT_NODE_WIDTH = 150;
const DEFAULT_NODE_HEIGHT = 50;
function getNodesBounds(nodes) {
    if (0 === nodes.length) return {
        x: 0,
        y: 0,
        width: 0,
        height: 0
    };
    let minX = 1 / 0;
    let minY = 1 / 0;
    let maxX = -1 / 0;
    let maxY = -1 / 0;
    for (const node of nodes){
        const nodeWidth = node.measured?.width ?? node.width ?? DEFAULT_NODE_WIDTH;
        const nodeHeight = node.measured?.height ?? node.height ?? DEFAULT_NODE_HEIGHT;
        minX = Math.min(minX, node.position.x);
        minY = Math.min(minY, node.position.y);
        maxX = Math.max(maxX, node.position.x + nodeWidth);
        maxY = Math.max(maxY, node.position.y + nodeHeight);
    }
    return {
        x: minX,
        y: minY,
        width: maxX - minX,
        height: maxY - minY
    };
}
async function exportCanvasToImage(reactFlowInstance, options = {}) {
    const opts = {
        ...DEFAULT_OPTIONS,
        ...options,
        backgroundColor: options.backgroundColor ?? getCanvasBackgroundColor()
    };
    const nodes = reactFlowInstance.getNodes();
    if (0 === nodes.length) throw new Error('Cannot export canvas: no nodes found');
    const reactFlowWrapper = document.querySelector('.react-flow');
    if (!reactFlowWrapper) throw new Error('Cannot find React Flow wrapper element');
    const viewportElement = document.querySelector(opts.viewportSelector);
    if (!viewportElement) throw new Error(`Cannot find viewport element with selector: ${opts.viewportSelector}`);
    const originalViewport = reactFlowInstance.getViewport();
    await yieldToMain();
    const bounds = getNodesBounds(nodes);
    const paddingAmount = Math.max(bounds.width, bounds.height) * opts.padding;
    const containerWidth = reactFlowWrapper.clientWidth || opts.width;
    const containerHeight = reactFlowWrapper.clientHeight || opts.height;
    const contentWidth = bounds.width + 2 * paddingAmount;
    const contentHeight = bounds.height + 2 * paddingAmount;
    const fitZoomX = containerWidth / contentWidth;
    const fitZoomY = containerHeight / contentHeight;
    const fitZoom = Math.min(fitZoomX, fitZoomY, opts.maxZoom);
    const centeredX = (containerWidth - contentWidth * fitZoom) / 2 - bounds.x * fitZoom + paddingAmount * fitZoom;
    const centeredY = (containerHeight - contentHeight * fitZoom) / 2 - bounds.y * fitZoom + paddingAmount * fitZoom;
    reactFlowInstance.setViewport({
        x: centeredX,
        y: centeredY,
        zoom: fitZoom
    }, {
        duration: 0
    });
    await yieldToMain();
    await new Promise((resolve)=>{
        requestAnimationFrame(()=>{
            requestAnimationFrame(()=>{
                resolve();
            });
        });
    });
    await wait(RENDER_STABILIZATION_DELAY_MS);
    await yieldToMain();
    const exportFn = getExportFunction(opts.format);
    const defaultFilter = (node)=>{
        const className = node.className;
        if ('string' == typeof className) {
            if (className.includes('react-flow__minimap') || className.includes('react-flow__controls') || className.includes('react-flow__attribution') || className.includes('react-flow__panel') || className.includes('react-flow__background')) return false;
        }
        return true;
    };
    const combinedFilter = (node)=>{
        if (!defaultFilter(node)) return false;
        if (!opts.includeImages) {
            const tagName = node.tagName?.toLowerCase();
            if ('img' === tagName || 'image' === tagName) return false;
        }
        if (opts.filter && !opts.filter(node)) return false;
        return true;
    };
    const isSvgFormat = 'svg' === opts.format;
    const exportOptions = {
        backgroundColor: opts.backgroundColor,
        width: containerWidth,
        height: containerHeight,
        cacheBust: false,
        skipFonts: opts.skipFonts,
        filter: combinedFilter,
        ...!isSvgFormat && {
            pixelRatio: opts.pixelRatio
        },
        ...'jpeg' === opts.format && {
            quality: opts.quality
        }
    };
    let dataUrl;
    try {
        dataUrl = await exportFn(viewportElement, exportOptions);
    } finally{
        reactFlowInstance.setViewport(originalViewport);
    }
    const resultWidth = isSvgFormat ? containerWidth : containerWidth * opts.pixelRatio;
    const resultHeight = isSvgFormat ? containerHeight : containerHeight * opts.pixelRatio;
    return {
        dataUrl,
        width: resultWidth,
        height: resultHeight,
        format: opts.format
    };
}
async function downloadCanvasAsImage(reactFlowInstance, filename = 'canvas-export', options = {}) {
    const result = await exportCanvasToImage(reactFlowInstance, options);
    const extension = getFileExtension(result.format);
    const fullFilename = filename.endsWith(`.${extension}`) ? filename : `${filename}.${extension}`;
    const link = document.createElement('a');
    link.download = fullFilename;
    link.href = result.dataUrl;
    link.click();
}
async function copyCanvasToClipboard(reactFlowInstance, options = {}) {
    if (!navigator.clipboard?.write) throw new Error('Clipboard API is not supported in this browser. Try using a modern browser like Chrome, Firefox, or Edge.');
    const result = await exportCanvasToImage(reactFlowInstance, {
        ...options,
        format: 'png'
    });
    const response = await fetch(result.dataUrl);
    const blob = await response.blob();
    await navigator.clipboard.write([
        new ClipboardItem({
            [blob.type]: blob
        })
    ]);
}
export { copyCanvasToClipboard, downloadCanvasAsImage, exportCanvasToImage, getFileExtension, getMimeType };
