import { Context, getParam } from "@needle-tools/engine";
import { Mesh } from "three";

export const debug = getParam("debugmaterialx");
export const debugUpdate = getParam("debugmaterialxupdate");

/**
 * =====================================
 * Unused
 */

// Patch WebGL2 methods for debugging purposes

const patchWebGL2 = () => {
    const getUniformLocation = WebGL2RenderingContext.prototype.getUniformLocation;
    const programAndNameToUniformLocation = new WeakMap<WebGLUniformLocation, { program: WebGLProgram, name: string }>();
    WebGL2RenderingContext.prototype.getUniformLocation = function (program: WebGLProgram, name: string) {
        const location = getUniformLocation.call(this, program, name);
        if (location) {
            programAndNameToUniformLocation.set(location, { program, name });
        }
        return location;
    };

    const uniform4fv = WebGL2RenderingContext.prototype.uniform4fv;
    WebGL2RenderingContext.prototype.uniform4fv = function (location: WebGLUniformLocation | null, v: Float32Array | number[]) {
        if (location) {
            const uniformName = programAndNameToUniformLocation.get(location);
            if (true) console.log("Calling uniform4fv", { location, v, name: uniformName?.name });
        }
        return uniform4fv.call(this, location, v);
    };

    const uniform3fv = WebGL2RenderingContext.prototype.uniform3fv;
    WebGL2RenderingContext.prototype.uniform3fv = function (location: WebGLUniformLocation | null, v: Float32Array | number[]) {
        if (location) {
            const uniformName = programAndNameToUniformLocation.get(location);
            if (true) console.log("Calling uniform3fv", { location, v, name: uniformName?.name });
        }
        return uniform3fv.call(this, location, v);
    };

    const uniform3iv = WebGL2RenderingContext.prototype.uniform3iv;
    WebGL2RenderingContext.prototype.uniform3iv = function (location: WebGLUniformLocation | null, v: Int32Array | number[]) {
        if (location) {
            const uniformName = programAndNameToUniformLocation.get(location);
            if (true) console.log("Calling uniform3iv", { location, v, name: uniformName?.name });
        }
        return uniform3iv.call(this, location, v);
    };

    const uniform3uiv = WebGL2RenderingContext.prototype.uniform3uiv;
    WebGL2RenderingContext.prototype.uniform3uiv = function (location: WebGLUniformLocation | null, v: Uint32Array | number[]) {
        if (location) {
            const uniformName = programAndNameToUniformLocation.get(location);
            if (true) console.log("Calling uniform3uiv", { location, v, name: uniformName?.name });
        }
        return uniform3uiv.call(this, location, v);
    };

    const uniform3f = WebGL2RenderingContext.prototype.uniform3f;
    WebGL2RenderingContext.prototype.uniform3f = function (location: WebGLUniformLocation
        | null, x: number, y: number, z: number) {
        if (location) {
            const uniformName = programAndNameToUniformLocation.get(location);
            if (uniformName?.name !== "diffuse")
                if (true) console.log("Calling uniform3f", { location, x, y, z, name: uniformName?.name });
        }
        return uniform3f.call(this, location, x, y, z);
    };
};
// patchWebGL2();


// TODO doesn't actually reset yet...
function resetShaders(ctx: Context) {
    const scene = ctx.scene;
    const gl = ctx.renderer;
    console.log(gl.properties, gl.info)
    scene.traverse(object => {
        if ((object as Mesh).isMesh) {
            const mesh = object as Mesh;
            if (Array.isArray(mesh.material)) {
                mesh.material.forEach(mat => gl.properties.remove(mat));
            }
            else {
                gl.properties.remove(mesh.material);
            }
        }
    })
    if (gl.info?.programs)
        gl.info.programs.length = 0;
}