'use client';
"use strict";
Object.defineProperty(exports, "__esModule", {
    value: true
});
function _export(target, all) {
    for(var name in all)Object.defineProperty(target, name, {
        enumerable: true,
        get: all[name]
    });
}
_export(exports, {
    cloneLegendsToSVG: function() {
        return cloneLegendsToSVG;
    },
    exportChartsAsImage: function() {
        return exportChartsAsImage;
    }
});
const _d3selection = require("d3-selection");
const _reactutilities = require("@fluentui/react-utilities");
const _index = require("./index");
const _useLegendsStylesstyles = require("../components/Legends/useLegendsStyles.styles");
async function exportChartsAsImage(charts, legendsToSvg, isRTL = false, opts = {}) {
    if (charts.length === 0 && !legendsToSvg) {
        throw new Error('No charts or legends to export');
    }
    const chartImages = await Promise.all(charts.map((chart)=>{
        return new Promise((resolve)=>{
            const svg = cloneStyledSVG(chart.container, isRTL);
            const svgDataUrl = svgToBase64(svg.node);
            resolve({
                dataUrl: svgDataUrl,
                width: svg.width,
                height: svg.height
            });
        });
    }));
    const grid = []; // Sparse 2D array
    charts.forEach((chart, i)=>{
        const row = chart.row || 0;
        const col = chart.col || 0;
        if (!grid[row]) {
            grid[row] = [];
        }
        grid[row][col] = chartImages[i];
    });
    if (legendsToSvg) {
        let totalWidth = 0;
        grid.forEach((row)=>{
            let rowWidth = 0;
            row.forEach((item)=>{
                rowWidth += item.width;
            });
            totalWidth = Math.max(totalWidth, rowWidth);
        });
        const svg = legendsToSvg(totalWidth, isRTL);
        if (svg.node) {
            const svgDataUrl = svgToBase64(svg.node);
            grid.push([
                {
                    dataUrl: svgDataUrl,
                    width: svg.width,
                    height: svg.height
                }
            ]);
        }
    }
    return svgToPng(grid, opts);
}
const SVG_STYLE_PROPERTIES = [
    'display',
    'fill',
    'fill-opacity',
    'opacity',
    'stroke',
    'stroke-width',
    'transform',
    'border-collapse'
];
const SVG_TEXT_STYLE_PROPERTIES = [
    'font-family',
    'font-size',
    'font-weight',
    'text-anchor',
    'background-color',
    'color',
    'padding',
    'text-align',
    'border'
];
const ANNOTATION_HTML_STYLE_PROPERTIES = [
    'align-items',
    'background',
    'background-color',
    'border',
    'border-radius',
    'box-shadow',
    'box-sizing',
    'color',
    'column-gap',
    'display',
    'flex',
    'flex-direction',
    'font-family',
    'font-size',
    'font-style',
    'font-weight',
    'gap',
    'height',
    'justify-content',
    'letter-spacing',
    'line-height',
    'margin',
    'max-height',
    'max-width',
    'min-height',
    'min-width',
    'opacity',
    'overflow',
    'padding',
    'pointer-events',
    'position',
    'row-gap',
    'text-align',
    'text-decoration',
    'text-transform',
    'top',
    'right',
    'bottom',
    'left',
    'visibility',
    'white-space',
    'width',
    'z-index'
];
const ANNOTATION_FOREIGN_OBJECT_STYLE_PROPERTIES = [
    'overflow',
    'pointer-events'
];
function cloneStyledSVG(chartContainer, isRTL) {
    if (!chartContainer) {
        throw new Error('Chart container is not defined');
    }
    const svg = chartContainer.querySelector('svg');
    if (!svg) {
        throw new Error('SVG not found');
    }
    let clonedSvg = (0, _d3selection.select)(svg.cloneNode(true)).attr('width', null).attr('height', null).attr('viewBox', null);
    let svgElements = svg.getElementsByTagName('*');
    let clonedSvgElements = clonedSvg.node().getElementsByTagName('*');
    const TEXT_ELEMENTS = [
        'text'
    ];
    const TABLE_ELEMENTS = [
        'table',
        'thead',
        'tbody',
        'tr',
        'th',
        'td'
    ];
    for(let i = 0; i < svgElements.length; i++){
        const tag = svgElements[i].tagName.toLowerCase();
        if (TEXT_ELEMENTS.includes(tag) || TABLE_ELEMENTS.includes(tag)) {
            (0, _index.copyStyle)([
                ...SVG_STYLE_PROPERTIES,
                ...SVG_TEXT_STYLE_PROPERTIES
            ], svgElements[i], clonedSvgElements[i]);
        } else {
            (0, _index.copyStyle)(SVG_STYLE_PROPERTIES, svgElements[i], clonedSvgElements[i]);
        }
    }
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    svgElements = null;
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    clonedSvgElements = null;
    const originalForeignObjects = svg.querySelectorAll('foreignObject');
    const clonedForeignObjects = clonedSvg.node().querySelectorAll('foreignObject');
    originalForeignObjects.forEach((originalFo, index)=>{
        const clonedFo = clonedForeignObjects[index];
        if (!clonedFo) {
            return;
        }
        const originalRoot = originalFo.firstElementChild;
        const clonedRoot = clonedFo.firstElementChild;
        if (originalRoot && clonedRoot) {
            (0, _index.copyStyle)(ANNOTATION_HTML_STYLE_PROPERTIES, originalRoot, clonedRoot);
        }
        const originalHtmlElements = originalFo.querySelectorAll('*');
        const clonedHtmlElements = clonedFo.querySelectorAll('*');
        originalHtmlElements.forEach((originalEl, elementIndex)=>{
            const clonedEl = clonedHtmlElements[elementIndex];
            if (clonedEl) {
                (0, _index.copyStyle)(ANNOTATION_HTML_STYLE_PROPERTIES, originalEl, clonedEl);
            }
        });
    });
    const annotationSvg = chartContainer.querySelector('[data-chart-annotation-svg="true"]');
    let annotationClone = null;
    if (annotationSvg) {
        annotationClone = annotationSvg.cloneNode(true);
        (0, _index.copyStyle)(SVG_STYLE_PROPERTIES, annotationSvg, annotationClone);
        const annotationElements = annotationSvg.getElementsByTagName('*');
        const clonedAnnotationElements = annotationClone.getElementsByTagName('*');
        for(let i = 0; i < annotationElements.length; i++){
            const original = annotationElements[i];
            const cloned = clonedAnnotationElements[i];
            const tag = original.tagName.toLowerCase();
            const isSvgElement = original instanceof SVGElement;
            const isTextElement = tag === 'text';
            const isHtmlElement = (0, _reactutilities.isHTMLElement)(original);
            if (isSvgElement) {
                if (isTextElement) {
                    (0, _index.copyStyle)([
                        ...SVG_STYLE_PROPERTIES,
                        ...SVG_TEXT_STYLE_PROPERTIES
                    ], original, cloned);
                } else {
                    (0, _index.copyStyle)(SVG_STYLE_PROPERTIES, original, cloned);
                }
            }
            if (isHtmlElement) {
                (0, _index.copyStyle)(ANNOTATION_HTML_STYLE_PROPERTIES, original, cloned);
            }
            if (tag === 'foreignobject') {
                (0, _index.copyStyle)(ANNOTATION_FOREIGN_OBJECT_STYLE_PROPERTIES, original, cloned);
            }
        }
    }
    const { width, height } = svg.getBoundingClientRect();
    clonedSvg.attr('width', width).attr('height', height).attr('viewBox', `0 0 ${width} ${height}`).attr('direction', isRTL ? 'rtl' : 'ltr');
    if (annotationClone) {
        clonedSvg.selectAll('[data-chart-annotation-layer="true"]').remove();
        (0, _d3selection.select)(annotationClone).attr('x', 0).attr('y', 0).attr('width', width).attr('height', height);
        clonedSvg.append(()=>annotationClone);
    }
    const result = {
        node: clonedSvg.node(),
        width,
        height
    };
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    clonedSvg = null;
    return result;
}
const LEGEND_TEXT_STYLE_PROPERTIES_MAP = {
    color: 'fill',
    'font-family': 'font-family',
    'font-size': 'font-size',
    'font-weight': 'font-weight'
};
function cloneLegendsToSVG(legends, svgWidth, config, legendContainer) {
    if (legends.length === 0) {
        return {
            node: null,
            width: 0,
            height: 0
        };
    }
    const { selectedLegends, centerLegends, textClassName, isRTL } = config;
    const legendGroup = (0, _d3selection.create)('svg:g');
    let legendX = centerLegends ? 0 : _useLegendsStylesstyles.LEGEND_CONTAINER_MARGIN_START;
    let legendY = _useLegendsStylesstyles.LEGEND_CONTAINER_MARGIN_TOP;
    let legendLine = [];
    const legendLines = [];
    const legendLineWidths = [];
    const noLegendsSelected = Object.keys(selectedLegends).length === 0;
    for(let i = 0; i < legends.length; i++){
        const textOffset = _useLegendsStylesstyles.LEGEND_PADDING + _useLegendsStylesstyles.LEGEND_SHAPE_SIZE + _useLegendsStylesstyles.LEGEND_SHAPE_MARGIN_END;
        const legendText = (0, _index.measureTextWithDOM)(legends[i].title, `.${textClassName}`, legendContainer);
        const legendWidth = textOffset + legendText.width + _useLegendsStylesstyles.LEGEND_PADDING;
        const legendItem = legendGroup.append('g');
        legendLine.push({
            elem: legendItem,
            width: legendWidth
        });
        if (legendX + legendWidth > svgWidth && legendLine.length > 1) {
            legendLine.pop();
            legendLines.push(legendLine);
            legendLineWidths.push(legendX);
            legendLine = [
                {
                    elem: legendItem,
                    width: legendWidth
                }
            ];
            legendX = centerLegends ? 0 : _useLegendsStylesstyles.LEGEND_CONTAINER_MARGIN_START;
            legendY += _useLegendsStylesstyles.LEGEND_HEIGHT;
        }
        const isLegendActive = selectedLegends[legends[i].title] || noLegendsSelected;
        legendItem.append('rect').attr('x', legendX + (isRTL ? legendWidth - _useLegendsStylesstyles.LEGEND_PADDING - _useLegendsStylesstyles.LEGEND_SHAPE_SIZE : _useLegendsStylesstyles.LEGEND_PADDING)).attr('y', legendY + _useLegendsStylesstyles.LEGEND_PADDING).attr('width', _useLegendsStylesstyles.LEGEND_SHAPE_SIZE).attr('height', _useLegendsStylesstyles.LEGEND_SHAPE_SIZE).style('fill', isLegendActive ? legends[i].color : 'transparent').style('stroke-width', _useLegendsStylesstyles.LEGEND_SHAPE_BORDER).style('stroke', legends[i].color);
        legendItem.append('text').attr('x', legendX + (isRTL ? legendWidth - textOffset : textOffset)).attr('y', legendY + _useLegendsStylesstyles.LEGEND_PADDING).attr('dominant-baseline', 'hanging').style('opacity', isLegendActive ? 1 : _useLegendsStylesstyles.INACTIVE_LEGEND_TEXT_OPACITY).text(legends[i].title).call((selection)=>(0, _index.copyStyle)(LEGEND_TEXT_STYLE_PROPERTIES_MAP, legendText.node, selection.node()));
        legendX += legendWidth;
    }
    legendLines.push(legendLine);
    legendLineWidths.push(legendX);
    legendY += _useLegendsStylesstyles.LEGEND_HEIGHT;
    if (centerLegends) {
        legendLines.forEach((ln, idx)=>{
            const lineOffsetX = Math.max((svgWidth - legendLineWidths[idx]) / 2, 0);
            let remLineWidth = legendLineWidths[idx];
            let itemOffsetX = 0;
            ln.forEach((item)=>{
                const newOffsetX = lineOffsetX + (isRTL ? remLineWidth - item.width - itemOffsetX : 0);
                item.elem.attr('transform', `translate(${newOffsetX}, 0)`);
                remLineWidth -= item.width;
                itemOffsetX += item.width;
            });
        });
    } else if (isRTL) {
        const w1 = Math.max(svgWidth, ...legendLineWidths);
        legendLines.forEach((ln)=>{
            let remLineWidth = w1 - _useLegendsStylesstyles.LEGEND_CONTAINER_MARGIN_START;
            let itemOffsetX = _useLegendsStylesstyles.LEGEND_CONTAINER_MARGIN_START;
            ln.forEach((item)=>{
                const newOffsetX = remLineWidth - item.width - itemOffsetX;
                item.elem.attr('transform', `translate(${newOffsetX}, 0)`);
                remLineWidth -= item.width;
                itemOffsetX += item.width;
            });
        });
    }
    const w1 = Math.max(svgWidth, ...legendLineWidths);
    const h1 = legendY;
    const svg = (0, _d3selection.create)('svg').attr('width', w1).attr('height', h1).attr('viewBox', `0 0 ${w1} ${h1}`);
    svg.append(()=>legendGroup.node());
    return {
        node: svg.node(),
        width: w1,
        height: h1
    };
}
async function svgToPng(grid, opts = {}) {
    let totalWidth = 0;
    let totalHeight = 0;
    const positionedImages = grid.map((row)=>{
        let rowWidth = 0;
        let rowHeight = 0;
        const items = row.map((item)=>{
            const positioned = {
                ...item,
                x: rowWidth,
                y: totalHeight
            };
            rowWidth += item.width;
            rowHeight = Math.max(rowHeight, item.height);
            return positioned;
        });
        totalWidth = Math.max(totalWidth, rowWidth);
        totalHeight += rowHeight;
        return items;
    }).flat();
    const scale = opts.scale || 1;
    const w0 = opts.width || totalWidth;
    const h0 = opts.height || totalHeight;
    const scaleX = scale * w0 / totalWidth;
    const scaleY = scale * h0 / totalHeight;
    totalWidth = scaleX * totalWidth;
    totalHeight = scaleY * totalHeight;
    const canvas = document.createElement('canvas');
    canvas.width = totalWidth;
    canvas.height = totalHeight;
    const ctx = canvas.getContext('2d');
    if (!ctx) {
        throw new Error('Canvas context is null');
    }
    ctx.fillStyle = opts.background || 'transparent';
    ctx.fillRect(0, 0, totalWidth, totalHeight);
    await Promise.all(positionedImages.map((item)=>new Promise((resolve, reject)=>{
            const img = new Image();
            img.onload = ()=>{
                ctx.drawImage(img, scaleX * item.x, scaleY * item.y, scaleX * item.width, scaleY * item.height);
                resolve();
            };
            img.onerror = reject;
            img.src = item.dataUrl;
        })));
    return canvas.toDataURL('image/png');
}
function svgToBase64(svgNode) {
    if (!svgNode) {
        throw new Error('SVG node is null');
    }
    const svgData = new XMLSerializer().serializeToString(svgNode);
    const svgDataUrl = 'data:image/svg+xml;base64,' + btoa(unescapePonyfill(encodeURIComponent(svgData)));
    return svgDataUrl;
}
const hex2 = /^[\da-f]{2}$/i;
const hex4 = /^[\da-f]{4}$/i;
/**
 * A ponyfill for the deprecated `unescape` method, taken from the `core-js` library.
 *
 * Source: {@link https://github.com/zloirock/core-js/blob/167136f479d3b8519953f2e4c534ecdd1031d3cf/packages/core-js/modules/es.unescape.js core-js/packages/core-js/modules/es.unescape.js}
 */ function unescapePonyfill(str) {
    let result = '';
    const length = str.length;
    let index = 0;
    let chr;
    let part;
    while(index < length){
        chr = str.charAt(index++);
        if (chr === '%') {
            if (str.charAt(index) === 'u') {
                part = str.slice(index + 1, index + 5);
                if (hex4.exec(part)) {
                    result += String.fromCharCode(parseInt(part, 16));
                    index += 5;
                    continue;
                }
            } else {
                part = str.slice(index, index + 2);
                if (hex2.exec(part)) {
                    result += String.fromCharCode(parseInt(part, 16));
                    index += 2;
                    continue;
                }
            }
        }
        result += chr;
    }
    return result;
}
