/*
 * Copyright (c), Huawei Technologies Co., Ltd. 2025-2025. All rights reserved.
 */

import shaders from '../shaders';
import { Program } from './Program';

export class EdgeProgram extends Program {
    private maxVertices: number = 500000;
    private uniformLoc: Record<string, WebGLUniformLocation | null> = {};

    initialize(): void {
        const gl = this.gl;
        this.instanceBuffer = this.createBuffer(this.maxVertices * 14 * 4);
        const { vertexShader, fragmentShader } = shaders.edge;
        this.program = this.createProgram(vertexShader, fragmentShader);
        this.uniformLoc.uScale = gl.getUniformLocation(this.program, 'uScale');
        this.uniformLoc.uTranslate = gl.getUniformLocation(this.program, 'uTranslate');
        this.uniformLoc.uResolution = gl.getUniformLocation(this.program, 'uResolution');
        this.vao = gl.createVertexArray()!;
        gl.bindVertexArray(this.vao);
        gl.bindBuffer(gl.ARRAY_BUFFER, this.instanceBuffer);
        const stride = 14 * 4;
        gl.enableVertexAttribArray(0);
        gl.vertexAttribPointer(0, 2, gl.FLOAT, false, stride, 0);
        gl.vertexAttribDivisor(0, 1);
        gl.enableVertexAttribArray(1);
        gl.vertexAttribPointer(1, 2, gl.FLOAT, false, stride, 8);
        gl.vertexAttribDivisor(1, 1);
        gl.enableVertexAttribArray(2);
        gl.vertexAttribPointer(2, 2, gl.FLOAT, false, stride, 16);
        gl.vertexAttribDivisor(2, 1);
        gl.enableVertexAttribArray(3);
        gl.vertexAttribPointer(3, 2, gl.FLOAT, false, stride, 24);
        gl.vertexAttribDivisor(3, 1);
        gl.enableVertexAttribArray(4);
        gl.vertexAttribPointer(4, 4, gl.FLOAT, false, stride, 32);
        gl.vertexAttribDivisor(4, 1);
        gl.enableVertexAttribArray(5);
        gl.vertexAttribPointer(5, 1, gl.FLOAT, false, stride, 48);
        gl.vertexAttribDivisor(5, 1);
        gl.enableVertexAttribArray(6);
        gl.vertexAttribPointer(6, 1, gl.FLOAT, false, stride, 52);
        gl.vertexAttribDivisor(6, 1);
        gl.bindVertexArray(null);
    }

    draw(params: { instanceCount: number, uniformData: Float32Array }): void {
        const gl = this.gl;
        const { instanceCount, uniformData } = params;
        gl.useProgram(this.program);
        gl.uniform2f(this.uniformLoc.uScale, uniformData[0], uniformData[1]);
        gl.uniform2f(this.uniformLoc.uTranslate, uniformData[8], uniformData[9]);
        gl.uniform2f(this.uniformLoc.uResolution, uniformData[12], uniformData[13]);
        gl.bindVertexArray(this.vao);
        gl.drawArraysInstanced(gl.TRIANGLE_STRIP, 0, 128, instanceCount);
        gl.bindVertexArray(null);
    }
}