// Returns an [x, y] point on a circle, with given origin and radius, at a given angle
// counter-clockwise from the positive horizontal axis.
function circleCoordinates(origin, radius, radians) {
    return [
        origin[0] + Math.cos(radians) * radius,
        origin[1] + Math.sin(radians) * radius
    ];
}

// Animator handles calling and stopping requestAnimationFrame and keeping track of framerate.
class Animator {
    framesCount = 0;
    totalFramesMs = 0;
    animating = false;
    renderer = null;

    start() {
        if (this.animating === false) {
            this.animating = true;
            this.framesCount = 0;
            const frameStartMs = performance.now();

            const drawFrame = () => {
                if (this.animating && this.renderer) {
                    requestAnimationFrame(drawFrame);
                    this.framesCount++;

                    const [x, y] = circleCoordinates([-70, -70], 50, this.framesCount/100);
                    this.renderer.render(x, y);

                    const frameTimeMs = performance.now() - frameStartMs;
                    this.totalFramesMs = frameTimeMs;
                }
            };
            requestAnimationFrame(drawFrame);
        }
    }

    stop() {
        this.animating = false;
    }
}

// The following three renderers draw a repeating pattern of paths.
// The approximate height and width of this repeated pattern is given by PATTERN_BOUNDS:
const PATTERN_BOUNDS = 600;
// And the spacing of the pattern (distance between repeated paths) is given by PATTERN_SPACING:
const PATTERN_SPACING = 70;

class SVGRenderer {
    constructor(svgObjectElement) {
        this.svgObjectElement = svgObjectElement;
        this.svgElArray = [];
        // Create an SVG element for every position in the pattern
        for (let xo = 0; xo < PATTERN_BOUNDS; xo += PATTERN_SPACING) {
            for (let yo = 0; yo < PATTERN_BOUNDS; yo += PATTERN_SPACING) {
                const clonedSVG = svgObjectElement.cloneNode(true);
                this.svgElArray.push(clonedSVG);
                svgObjectElement.parentElement.appendChild(clonedSVG);
            }
        }
    }

    render(x, y) {
        let i = 0;
        for (let xo = 0; xo < PATTERN_BOUNDS; xo += PATTERN_SPACING) {
            for (let yo = 0; yo < PATTERN_BOUNDS; yo += PATTERN_SPACING) {
                this.svgElArray[i].style.transform = `translate(${x + xo}px, ${y + yo}px)`;
                i++;
            }
        }
    }
}

class Path2dRenderer {
    constructor(svgData, offscreenCanvas) {
        this.data = svgData.map(([pathString, fillColor]) => [new Path2D(pathString), fillColor]);

        this.ctx = offscreenCanvas.getContext('2d');
    }

    render(x, y) {
        const ctx = this.ctx;

        ctx.clearRect(0, 0, 500, 500);

        for (let xo = 0; xo < PATTERN_BOUNDS; xo += PATTERN_SPACING) {
            for (let yo = 0; yo < PATTERN_BOUNDS; yo += PATTERN_SPACING) {
                ctx.save();
                ctx.translate(x + xo, y + yo);

                for (const [path, fillColor] of this.data) {
                    ctx.fillStyle = fillColor;
                    ctx.fill(path);
                }
                ctx.restore();
            }
        }
    }
}

class CanvasKitRenderer {
    constructor(svgData, offscreenCanvas, CanvasKit) {
        this.CanvasKit = CanvasKit;
        this.data = svgData.map(([pathString, fillColor]) => [
            CanvasKit.MakePathFromSVGString(pathString),
            CanvasKit.parseColorString(fillColor)
        ]);

        this.surface = CanvasKit.MakeWebGLCanvasSurface(offscreenCanvas, null);
        if (!this.surface) {
            throw 'Could not make canvas surface';
        }
        this.canvas = this.surface.getCanvas();

        this.paint = new CanvasKit.Paint();
        this.paint.setAntiAlias(true);
        this.paint.setStyle(CanvasKit.PaintStyle.Fill);
    }

    render(x, y) {
        const canvas = this.canvas;

        canvas.clear(this.CanvasKit.WHITE);

        for (let xo = 0; xo < PATTERN_BOUNDS; xo += PATTERN_SPACING) {
            for (let yo = 0; yo < PATTERN_BOUNDS; yo += PATTERN_SPACING) {
                canvas.save();
                canvas.translate(x + xo, y + yo);

                for (const [path, color] of this.data) {
                    this.paint.setColor(color);
                    canvas.drawPath(path, this.paint);
                }
                canvas.restore();
            }
        }
        this.surface.flush();
    }
}
