import { compileShader, linkProgram } from "./shader";
let shader;
let vbo;
let uvbo;
let texturesByUrl = {};
export function disposeDrawPlane() {
    shader = undefined;
    vbo = undefined;
    uvbo = undefined;
    texturesByUrl = {};
}
function generate(gl) {
    if (vbo)
        return vbo;
    vbo = gl.createBuffer();
    if (!vbo)
        throw new Error("Unable to create buffer object");
    let coords = [
        0, 0, 0, 0.1, 0, 0,
        0, 0, 0, 0, 0.1, 0,
        0, 0, 0, 0, 0, 0.1
    ];
    gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(coords), gl.STATIC_DRAW);
    gl.bindBuffer(gl.ARRAY_BUFFER, null);
    return vbo;
}
function generateColor(gl) {
    if (uvbo)
        return uvbo;
    uvbo = gl.createBuffer();
    if (!uvbo)
        throw new Error("Unable to create buffer object");
    let coords = [
        1, 0, 0, 1, 1, 0, 0, 1,
        0, 1, 0, 1, 0, 1, 0, 1,
        0, 0, 1, 1, 0, 0, 1, 1
    ];
    gl.bindBuffer(gl.ARRAY_BUFFER, uvbo);
    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(coords), gl.STATIC_DRAW);
    gl.bindBuffer(gl.ARRAY_BUFFER, null);
    return uvbo;
}
export function drawAxis(gl, projectionMatrix, cameraMatrix, targetMatrix) {
    let shader = getShader(gl);
    let v = generate(gl);
    let uvbo = generateColor(gl);
    gl.disable(gl.DEPTH_TEST);
    gl.useProgram(shader.prog);
    gl.uniformMatrix4fv(shader.unif_proj, false, projectionMatrix);
    gl.uniformMatrix4fv(shader.unif_camera, false, cameraMatrix);
    gl.uniformMatrix4fv(shader.unif_matrix, false, targetMatrix);
    gl.bindBuffer(gl.ARRAY_BUFFER, v);
    gl.activeTexture(gl.TEXTURE0);
    gl.bindTexture(gl.TEXTURE_2D, null);
    gl.vertexAttribPointer(shader.attr_position, 3, gl.FLOAT, false, 3 * 4, 0);
    gl.enableVertexAttribArray(shader.attr_position);
    gl.bindBuffer(gl.ARRAY_BUFFER, uvbo);
    gl.vertexAttribPointer(shader.attr_color, 4, gl.FLOAT, false, 4 * 4, 0);
    gl.enableVertexAttribArray(shader.attr_color);
    gl.lineWidth(2);
    gl.drawArrays(gl.LINES, 0, 6);
    gl.disableVertexAttribArray(shader.attr_position);
    gl.disableVertexAttribArray(shader.attr_color);
    gl.bindBuffer(gl.ARRAY_BUFFER, null);
}
function generateLocalMatrix() {
    let position = [0, 0, -5];
    return new Float32Array([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, position[0], position[1], position[2], 1]);
}
let vertexShaderSrc = `
#ifndef GL_ES
#define highp
#define mediump
#define lowp
#endif

uniform mat4 projMatrix;
uniform mat4 cameraMatrix;
uniform mat4 modelViewMatrix;
attribute vec4 position;
attribute vec4 color;

varying highp vec4 vColor;

void main()
{
    gl_Position = projMatrix * cameraMatrix * modelViewMatrix * position;
    vColor = color;
}`;
let fragmentShaderSrc = `
#define highp mediump
#ifdef GL_ES
    // define default precision for float, vec, mat.
    precision highp float;
#else
#define highp
#define mediump
#define lowp
#endif

varying highp vec4 vColor;

void main()
{
    gl_FragColor = vColor;
}`;
function getShader(gl) {
    if (shader)
        return shader;
    let prog = gl.createProgram();
    if (!prog)
        throw new Error("Unable to create program");
    let vertexShader = compileShader(gl, gl.VERTEX_SHADER, vertexShaderSrc);
    let fragmentShader = compileShader(gl, gl.FRAGMENT_SHADER, fragmentShaderSrc);
    gl.attachShader(prog, vertexShader);
    gl.attachShader(prog, fragmentShader);
    linkProgram(gl, prog);
    let unif_proj = gl.getUniformLocation(prog, "projMatrix");
    if (!unif_proj)
        throw new Error("Unable to get uniform location projMatrix");
    let unif_matrix = gl.getUniformLocation(prog, "modelViewMatrix");
    if (!unif_matrix)
        throw new Error("Unable to get uniform location modelViewMatrix");
    let unif_camera = gl.getUniformLocation(prog, "cameraMatrix");
    if (!unif_camera)
        throw new Error("Unable to get uniform location cameraMatrix");
    shader = {
        prog,
        unif_matrix,
        unif_proj,
        unif_camera,
        attr_position: gl.getAttribLocation(prog, "position"),
        attr_color: gl.getAttribLocation(prog, "color")
    };
    return shader;
}
