import type { HTMLAttributes } from "preact/compat";
import { useEffect, useMemo, useRef } from "preact/hooks";

interface Props extends HTMLAttributes<HTMLCanvasElement> {
    dataView: DataView;
    pointer: number;
}

export const PointerCanvas = ({ dataView, pointer, ...otherProps }: Props) => {
    const canvasRef = useRef<HTMLCanvasElement>(null);
    const ctx = useMemo(() => canvasRef.current?.getContext('2d'), [canvasRef.current]);

    const imageData = useMemo(() => loadImageData(dataView, pointer), [dataView, pointer]);

    useEffect(() => {
        if (canvasRef.current) {
            canvasRef.current.width = imageData.width;
            canvasRef.current.height = imageData.height;
        }
    }, [imageData, canvasRef.current]);

    useEffect(() => {
        let raf: number;
        const frame = () => {
            if (ctx) {
                ctx.putImageData(imageData, 0, 0);
            }
            raf = requestAnimationFrame(frame);
        }
        raf = requestAnimationFrame(frame);

        return () => {
            cancelAnimationFrame(raf);
        };
    }, [ctx, imageData]);

    return <>
        <canvas ref={canvasRef} {...otherProps} />
    </>;
};

export const loadImageData = (dataView: DataView, pointer: number) => {
    const width = dataView.getUint16(pointer + 0, true);
    const height = dataView.getUint16(pointer + 2, true);

    const dataPtr = dataView.getUint32(pointer + 4, true);
    const imageBuffer = new Uint8ClampedArray(dataView.buffer, dataPtr, width * height * 4);
    const imageData = new ImageData(imageBuffer, width, height);

    return imageData;
}