/*!
 * Copyright (c) 2026 Vertex Software LLC. All rights reserved.
 */
import { loadImageBytes } from "./imageLoaders";
const REPORTING_INTERVAL_MS = 1000;
function drawImage(image, data) {
    const rect = data.viewport.calculateDrawRect(data.frame.image);
    data.canvas.clearRect(0, 0, data.canvasDimensions.width, data.canvasDimensions.height);
    data.canvas.drawImage(image.image, rect.x, rect.y, rect.width, rect.height);
}
function reportTimings(meter, callback) {
    const timings = meter.takeMeasurements();
    if (timings.length > 0) {
        callback(timings);
    }
}
export function measureCanvasRenderer(meter, renderer, logFrameRate, callback, intervalMs = REPORTING_INTERVAL_MS) {
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    let timer;
    let renderCount = 0;
    let fpsFrameCount;
    let fpsHistory = [];
    function start() {
        renderCount++;
        if (timer == null) {
            timer = setInterval(() => {
                reportTimings(meter, callback);
                if (renderCount === 0) {
                    clearTimer();
                }
            }, intervalMs);
        }
    }
    function end() {
        renderCount--;
    }
    function clearTimer() {
        if (timer != null) {
            clearInterval(timer);
            timer = undefined;
        }
    }
    /* istanbul ignore next */
    if (logFrameRate) {
        setInterval(() => {
            if (fpsFrameCount != null) {
                if (fpsHistory.length === 5) {
                    fpsHistory = [...fpsHistory.slice(1), fpsFrameCount];
                }
                else {
                    fpsHistory.push(fpsFrameCount);
                }
                const avgFps = fpsHistory.reduce((res, num) => res + num) / fpsHistory.length;
                console.debug(`Paint rate: ${fpsFrameCount}fps`);
                console.debug(`Paint rate (avg): ${avgFps}`);
                fpsFrameCount = undefined;
            }
        }, 1000);
    }
    return (data) => {
        start();
        return meter
            .measure(async () => {
            const frame = await renderer(data);
            fpsFrameCount = fpsFrameCount == null ? 1 : fpsFrameCount + 1;
            return frame;
        })
            .finally(() => end());
    };
}
export function createCanvasRenderer() {
    let accumulatedCorrelationIds = [];
    function addCorrelationIds(frame) {
        if (frame != null) {
            const frameWithCorrelationIds = frame.copy({
                correlationIds: [
                    ...frame.correlationIds,
                    ...accumulatedCorrelationIds.filter((id) => !frame.correlationIds.includes(id)),
                ],
            });
            accumulatedCorrelationIds = [];
            return frameWithCorrelationIds;
        }
        return frame;
    }
    function loadFrame() {
        let lastLoadedFrameNumber = -1;
        return async (data) => {
            if (data.frame.sequenceNumber > lastLoadedFrameNumber) {
                const image = await loadImageBytes(data.frame.image.imageBytes);
                lastLoadedFrameNumber = data.frame.sequenceNumber;
                return image;
            }
        };
    }
    function drawFrame() {
        let lastDrawnFrameNumber = -1;
        return async (data, image) => {
            var _a;
            if (image != null && data.frame.sequenceNumber > lastDrawnFrameNumber) {
                lastDrawnFrameNumber = data.frame.sequenceNumber;
                (_a = data.beforeDraw) === null || _a === void 0 ? void 0 : _a.call(data);
                drawImage(image, data);
                image.dispose();
                return data.frame;
            }
            image === null || image === void 0 ? void 0 : image.dispose();
        };
    }
    const load = loadFrame();
    const draw = drawFrame();
    return async (data) => {
        var _a, _b;
        const predicatePassing = (_b = (_a = data.predicate) === null || _a === void 0 ? void 0 : _a.call(data)) !== null && _b !== void 0 ? _b : true;
        accumulatedCorrelationIds = [
            ...accumulatedCorrelationIds,
            ...data.frame.correlationIds,
        ];
        if (predicatePassing) {
            return load(data).then((image) => draw(data, image).then(addCorrelationIds));
        }
    };
}
export function debugStencilBuffer(stencilManager, drawStencil, renderer) {
    return async (data) => {
        const frame = await renderer(data);
        if (drawStencil()) {
            const stencil = await stencilManager.fetch();
            if (stencil != null) {
                const rect = data.viewport.calculateDrawRect(stencil);
                const stencilImage = await loadImageBytes(stencil.imageBytes);
                data.canvas.globalAlpha = 0.25;
                data.canvas.drawImage(stencilImage.image, rect.x, rect.y, rect.width, rect.height);
                data.canvas.globalAlpha = 1;
                stencilImage.dispose();
            }
        }
        return frame;
    };
}
//# sourceMappingURL=canvas.js.map
