import { container, vglobal, VWindow } from "./../../../vrender";

import { Bounds, isValid } from "@visactor/vutils";

export const cancelRenderChartQueue = !1;

export let chartRenderKeys = [];

export let chartRenderQueueList = [];

let requestAnimationFrameId, batchRenderChartCount = 5, isHandlingChartQueue = !1;

export function setBatchRenderChartCount(count) {
    isValid(count) && (batchRenderChartCount = count);
}

export function clearChartRenderQueue() {
    chartRenderKeys = [], chartRenderQueueList = [], isHandlingChartQueue = !1, vglobal.getCancelAnimationFrame()(requestAnimationFrameId);
}

export function IsHandlingChartQueue() {
    return isHandlingChartQueue;
}

export function renderChart(chart) {
    var _a, _b, _c, _d, _e, _f, _g;
    const {axes: axes, dataId: dataId, data: data, spec: spec, ClassType: ClassType, canvas: canvas, mode: mode, modeParams: modeParams, dpr: dpr} = chart.attribute;
    let {chartInstance: chartInstance} = chart;
    chartInstance || (chartInstance = new ClassType(spec, {
        renderCanvas: canvas,
        mode: "node" === mode ? "node" : "desktop-browser",
        modeParams: modeParams,
        canvasControled: !1,
        viewBox: {
            x1: 0,
            x2: 0,
            y1: 0,
            y2: 0
        },
        dpr: dpr,
        interactive: !1,
        animation: !1,
        autoFit: !1
    }), chartInstance.renderSync(), chart.chartInstance = chartInstance);
    const viewBox = chart.getViewBox();
    viewBox.x2 <= viewBox.x1 && (viewBox.x2 = viewBox.x1 + 1), viewBox.y2 <= viewBox.y1 && (viewBox.y2 = viewBox.y1 + 1), 
    chartInstance.updateViewBox({
        x1: 0,
        x2: viewBox.x2 - viewBox.x1,
        y1: 0,
        y2: viewBox.y2 - viewBox.y1
    }, !1, !1);
    const chartStage = chartInstance.getStage(), matrix = chart.globalTransMatrix, stageMatrix = chart.stage.window.getViewBoxTransform().clone();
    stageMatrix.multiply(matrix.a, matrix.b, matrix.c, matrix.d, matrix.e, matrix.f), 
    chartStage.window.setViewBoxTransform && chartStage.window.setViewBoxTransform(stageMatrix.a, stageMatrix.b, stageMatrix.c, stageMatrix.d, stageMatrix.e, stageMatrix.f);
    const {table: table} = chart.getRootNode();
    let updateSpec = !1;
    if (table.options.specFormat) {
        const formatResult = table.options.specFormat(chart.attribute.spec, chartInstance, chart);
        if (formatResult.needFormatSpec && formatResult.spec) {
            const spec = formatResult.spec;
            chartInstance.updateSpecSync(spec, !1, {
                reuse: !1,
                morph: !1
            }), updateSpec = null === (_a = formatResult.updateSpec) || void 0 === _a || _a;
        }
    }
    if (!updateSpec) if (null == axes || axes.forEach(((axis, index) => {
        var _a, _b, _c, _d, _e;
        "band" === axis.type ? chartInstance.updateModelSpec({
            type: "axes",
            index: index
        }, {
            domain: axis.domain.slice(0)
        }, !0) : chartInstance.updateModelSpecSync({
            type: "axes",
            index: index
        }, {
            min: null !== (_b = null === (_a = axis.range) || void 0 === _a ? void 0 : _a.min) && void 0 !== _b ? _b : 0,
            max: null !== (_d = null === (_c = axis.range) || void 0 === _c ? void 0 : _c.max) && void 0 !== _d ? _d : 0,
            tick: {
                tickMode: null === (_e = axis.tick) || void 0 === _e ? void 0 : _e.tickMode
            }
        }, !0);
    })), null === (_c = null === (_b = table.internalProps.layoutMap) || void 0 === _b ? void 0 : _b.updateDataStateToActiveChartInstance) || void 0 === _c || _c.call(_b, chartInstance), 
    "string" == typeof dataId || "number" == typeof dataId) chartInstance.getChart().setLayoutTag(!0), 
    chartInstance.updateDataSync(dataId, null != data ? data : []); else {
        const dataBatch = [];
        for (const dataIdStr in dataId) {
            const dataIdAndField = dataId[dataIdStr], series = spec.series.find((item => {
                var _a;
                return (null === (_a = null == item ? void 0 : item.data) || void 0 === _a ? void 0 : _a.id) === dataIdStr;
            }));
            dataBatch.push({
                id: dataIdStr,
                values: dataIdAndField ? null !== (_d = null == data ? void 0 : data.filter((item => item.hasOwnProperty(dataIdAndField)))) && void 0 !== _d ? _d : [] : null != data ? data : [],
                fields: null === (_e = null == series ? void 0 : series.data) || void 0 === _e ? void 0 : _e.fields
            }), chartInstance.updateFullDataSync || chartInstance.updateDataSync(dataIdStr, dataIdAndField ? null !== (_f = null == data ? void 0 : data.filter((item => item.hasOwnProperty(dataIdAndField)))) && void 0 !== _f ? _f : [] : null != data ? data : []);
        }
        chartInstance.getChart().setLayoutTag(!0), null === (_g = chartInstance.updateFullDataSync) || void 0 === _g || _g.call(chartInstance, dataBatch);
    }
    table.fireListeners("before_cache_chart_image", {
        chartInstance: chartInstance
    });
    cacheStageCanvas(chartInstance.getStage(), chart);
}

export function startRenderChartQueue(table) {
    isHandlingChartQueue = !0, chartRenderQueueList.length > 0 ? requestAnimationFrameId = vglobal.getRequestAnimationFrame()((() => {
        const chartsToRender = chartRenderQueueList.splice(0, batchRenderChartCount);
        chartRenderKeys.splice(0, batchRenderChartCount), chartsToRender.forEach((chart => {
            renderChart(chart), chart.addUpdateBoundTag();
        })), table.render(), startRenderChartQueue(table);
    })) : isHandlingChartQueue = !1;
}

const cacheCanvasSizeLimit = 2e3;

export function cacheStageCanvas(stage, chart) {
    var _a;
    const {viewWidth: viewWidth, viewHeight: viewHeight} = stage;
    if (viewWidth < cacheCanvasSizeLimit && viewHeight < cacheCanvasSizeLimit) return chart.cacheCanvas = toCanvas(stage), 
    void (chart.isShareChartSpec || (null === (_a = chart.chartInstance) || void 0 === _a || _a.release(), 
    chart.chartInstance = null, chart.setAttribute("chartInstance", null)));
    const rows = Math.ceil(viewHeight / cacheCanvasSizeLimit), columns = Math.ceil(viewWidth / cacheCanvasSizeLimit), cacheCanvas = [];
    for (let row = 0; row < rows; row++) for (let col = 0; col < columns; col++) {
        const startX = col * cacheCanvasSizeLimit, startY = row * cacheCanvasSizeLimit, endX = startX + cacheCanvasSizeLimit > viewWidth ? viewWidth : startX + cacheCanvasSizeLimit, endY = startY + cacheCanvasSizeLimit > viewHeight ? viewHeight : startY + cacheCanvasSizeLimit, width = endX - startX, height = endY - startY, bounds = new Bounds;
        bounds.setValue(startX, startY, endX, endY);
        const canvas = toCanvas(stage, !1, bounds);
        cacheCanvas.push({
            canvas: canvas,
            x: startX,
            y: startY,
            width: width,
            height: height
        });
    }
    chart.cacheCanvas = cacheCanvas;
}

function toCanvas(stage, fullImage = !0, viewBox) {
    if ("released" === stage.releaseStatus) return null;
    const c = renderToNewWindow(stage, fullImage, viewBox).getNativeHandler();
    return c.nativeCanvas ? c.nativeCanvas : null;
}

function renderToNewWindow(stage, fullImage = !0, viewBox) {
    const matrix = stage.window.getViewBoxTransform(), window = container.get(VWindow), x1 = viewBox ? -viewBox.x1 : 0, y1 = viewBox ? -viewBox.y1 : 0, x2 = viewBox ? viewBox.x2 : stage.viewWidth, y2 = viewBox ? viewBox.y2 : stage.viewHeight, width = viewBox ? viewBox.width() : stage.viewWidth, height = viewBox ? viewBox.height() : stage.viewHeight;
    return window.create({
        viewBox: {
            x1: x1,
            y1: y1,
            x2: x2,
            y2: y2
        },
        width: width * matrix.a,
        height: height * matrix.d,
        dpr: stage.window.dpr,
        canvasControled: !0,
        offscreen: !0,
        title: ""
    }), window.setViewBoxTransform(matrix.a, matrix.b, matrix.c, matrix.d, 0, 0), stage.renderTo(window), 
    window;
}
//# sourceMappingURL=chart-render-helper.js.map
