'use strict';

var ratio = 1, width = 1, height = 1, frames = 0;
var canvas, gl, positionAttributeLocation, positionBuffer, matBuffer, vpBuffer, sizeBuffer, distBuffer, fgBuffer;

function createShader(gl, type, source) {
    var shader = gl.createShader(type);
    gl.shaderSource(shader, source);
    gl.compileShader(shader);
    var success = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
    if (success) {
        return shader;
    }

    console.log(gl.getShaderInfoLog(shader));
    gl.deleteShader(shader);
}

function createProgram(gl, vertexShader, fragmentShader) {
    var program = gl.createProgram();
    gl.attachShader(program, vertexShader);
    gl.attachShader(program, fragmentShader);
    gl.linkProgram(program);
    var success = gl.getProgramParameter(program, gl.LINK_STATUS);
    if (success) {
        return program;
    }

    console.log(gl.getProgramInfoLog(program));
    gl.deleteProgram(program);
}

function main() {
    // Get A WebGL context
    canvas = document.querySelector("#c");
    gl = canvas.getContext("webgl");
    if (!gl) {
        return;
    }

    var vertexShaderSource = document.querySelector("#vertex-shader-2d").text;
    var fragmentShaderSource = document.querySelector("#fragment-shader-2d").text;

    var vertexShader = createShader(gl, gl.VERTEX_SHADER, vertexShaderSource);
    var fragmentShader = createShader(gl, gl.FRAGMENT_SHADER, fragmentShaderSource);

    var program = createProgram(gl, vertexShader, fragmentShader);

    //clean this msss
    positionAttributeLocation = gl.getAttribLocation(program, "a_position");
    matBuffer = gl.getUniformLocation(program, "mat_thing");
    sizeBuffer = gl.getUniformLocation(program, "size_thing");
    distBuffer = gl.getUniformLocation(program, "dist_thing");
    fgBuffer = gl.getUniformLocation(program, "is_fg");
    vpBuffer = gl.getUniformLocation(program, "mvp_thing");

    positionBuffer = gl.createBuffer();

    gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);

    gl.useProgram(program);

    gl.enable(gl.DEPTH_TEST);

    gl.depthFunc(gl.LEQUAL);
}

function renderThing() {
    twgl.resizeCanvasToDisplaySize(gl.canvas);

    width = gl.canvas.width;
    height = gl.canvas.height;

    gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);

    gl.clearColor(0, 0, 0, 0);
    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

    ratio = gl.canvas.width / gl.canvas.height;
    var ratioA = Math.max(ratio, 1);
    var ratioB = ratioA / ratio;


    // Tell the attribute how to get data out of positionBuffer (ARRAY_BUFFER)
    var size = 3;          // 2 components per iteration
    var type = gl.FLOAT;   // the data is 32bit floats
    var normalize = false; // don't normalize the data
    var stride = 0;        // 0 = move forward size * sizeof(type) each iteration to get the next position
    var offset = 0;        // start at the beginning of the buffer
    gl.vertexAttribPointer(
        positionAttributeLocation, size, type, normalize, stride, offset);

    var positions = [
        -1, -1, -1,
        -1, 1, -1,
        1, 1, -1,
        -1, -1, -1,
        1, -1, -1,
        1, 1, -1
    ];
    gl.enableVertexAttribArray(positionAttributeLocation);

    gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);

    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW);

    gl.uniformMatrix4fv(vpBuffer, false, new Float32Array([
        1024, 0, 0, 0,
        0, 1024, 0, 0,
        0, 0, 1024 / 4, 0,
        0, 0, 0, 1
    ]));

    gl.uniformMatrix4fv(matBuffer, false, new Float32Array(MDN.perspectiveMatrix(Math.PI * 100 / 180, ratio, 0.01, 1000)));

    gl.uniform1f(sizeBuffer, -Math.log(nothingness));

    let am = (nGain + getBonus) / (nGain + getBonus + nothingness);
    am = am ** (0.3);
    gl.uniform1f(distBuffer, 0.1 + 1.2 * am);
    gl.uniform1i(fgBuffer, false);

    var primitiveType = gl.TRIANGLES;
    var offset = 0;
    var count = 6;
    gl.drawArrays(primitiveType, offset, count);

    let sizes = (nGain + 1) / (nothingness + 1) * 1000000 / (cubePos.length + 30);
    sizes = Math.pow(sizes, 0.3);
    if (sizes > 10) sizes = 10;
    if (sizes < 3) sizes = 3;

    positions = MDN.createCubeData(1, 1, 1);
    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW);

    for (let ii in cubePos) {
        let cubie = cubePos[ii];
        let vp = MDN.rotateYMatrix(Math.log(nothingness + 1) * cubie[2] / 10);

        let bonus = 1 + counts.doNothing / (ii * .02 + 2);
        bonus = bonus ** (1 / 3)

        vp = MDN.multiplyMatrices(MDN.rotateXMatrix(frames * 0.01),vp);
        vp = MDN.multiplyMatrices(MDN.scaleMatrix(sizes * bonus, sizes * bonus, sizes * bonus), vp)
        vp = MDN.multiplyMatrices(MDN.translateMatrix(cubie[0], cubie[1], cubie[2]), vp)

        gl.uniformMatrix4fv(vpBuffer, false, new Float32Array(vp));

        gl.uniform1i(fgBuffer, true);
        count = positions.length / 3;
        gl.drawArrays(primitiveType, offset, count);
    }

    requestAnimationFrame(renderThing);
}

main();
requestAnimationFrame(renderThing)