import { asDefined, Terminator } from "@opendaw/lib-std";
import { AnimationFrame, Html } from "@opendaw/lib-dom";
export class CanvasPainter {
    #rendering;
    constructor(canvas, render) {
        this.#rendering = new CanvasRenderer(canvas, () => render(this));
    }
    requestUpdate = () => { this.#rendering.requestUpdate(); };
    get isResized() { return this.#rendering.isResized; }
    get devicePixelRatio() { return this.#rendering.devicePixelRatio; }
    get width() { return this.#rendering.width; }
    get height() { return this.#rendering.height; }
    get actualWidth() { return this.#rendering.actualWidth; }
    get actualHeight() { return this.#rendering.actualHeight; }
    get context() { return this.#rendering.context; }
    terminate() { this.#rendering.terminate(); }
}
export class CanvasUnitPainter {
    #rendering;
    #xAxis;
    #yAxis;
    constructor(canvas, xAxis, yAxis, render) {
        this.#rendering = new CanvasRenderer(canvas, () => render(this));
        this.#xAxis = xAxis;
        this.#yAxis = yAxis;
    }
    requestUpdate = () => { this.#rendering.requestUpdate(); };
    xToUnit(x) { return this.#xAxis.normToUnit(x / this.#rendering.actualWidth); }
    unitToX(value) { return this.#xAxis.unitToNorm(value) * this.#rendering.actualWidth; }
    yToUnit(y) { return this.#yAxis.normToUnit(1.0 - y / this.#rendering.actualHeight); }
    unitToY(value) { return (1.0 - this.#yAxis.unitToNorm(value)) * this.#rendering.actualHeight; }
    get context() { return this.#rendering.context; }
    get isResized() { return this.#rendering.isResized; }
    get width() { return this.#rendering.width; }
    get height() { return this.#rendering.height; }
    get actualWidth() { return this.#rendering.actualWidth; }
    get actualHeight() { return this.#rendering.actualHeight; }
    terminate() { this.#rendering.terminate(); }
}
class CanvasRenderer {
    #lifecycle = new Terminator();
    #context;
    #update;
    #width = 0;
    #height = 0;
    #devicePixelRatio = 1;
    #isResized = true;
    #needsUpdate = true;
    constructor(canvas, update) {
        this.#context = asDefined(canvas.getContext("2d"));
        this.#update = update;
        this.#lifecycle.ownAll(Html.watchResize(canvas, () => {
            this.#isResized = true;
            this.#needsUpdate = true;
        }), this.#lifecycle.own(AnimationFrame.add(() => {
            const width = canvas.clientWidth;
            const height = canvas.clientHeight;
            if (!this.#needsUpdate || width === 0 || height === 0) {
                return;
            }
            this.#isResized = width !== this.#width || height !== this.#height || devicePixelRatio !== this.#devicePixelRatio;
            this.#width = width;
            this.#height = height;
            this.#devicePixelRatio = devicePixelRatio;
            canvas.width = width * devicePixelRatio;
            canvas.height = height * devicePixelRatio;
            this.#update();
            this.#isResized = false;
            this.#needsUpdate = false;
        })));
    }
    get isResized() { return this.#isResized; }
    get devicePixelRatio() { return this.#devicePixelRatio; }
    get width() { return this.#width; }
    get height() { return this.#height; }
    get actualWidth() { return this.#width * this.#devicePixelRatio; }
    get actualHeight() { return this.#height * this.#devicePixelRatio; }
    get context() { return this.#context; }
    requestUpdate() { this.#needsUpdate = true; }
    terminate() { this.#lifecycle.terminate(); }
}
