{% extends "base.html" %}

{% block title %}Browser Random Generation{% endblock %}

{% block content %}
<div class="max-w-scree grid grid-cols-1 items-center divide-y">
  <div class="flex flex-col justify-center pt-6 text-center">
    <p class="text-2xl" id="browser-name">Detected Browser: Something</p>
    <p class="mt-2 text-gray-600 dark:text-gray-400">This visualization demonstrates the strength and uniformity of your
      browser's random number generator.</p>
  </div>
  <div class="flex justify-center pt-6">
    <canvas id="randNumCanvas" width="1000" height="1000"></canvas>
  </div>
</div>
{% endblock %}

{% block js %}
<script>
  "use strict";

  var vertexShaderSource = `#version 300 es

// an attribute is an input (in) to a vertex shader.
// It will receive data from a buffer
in vec2 a_position;

// Used to pass in the resolution of the canvas
uniform vec2 u_resolution;

// all shaders have a main function
void main() {

  // convert the position from pixels to 0.0 to 1.0
  vec2 zeroToOne = a_position / u_resolution;

  // convert from 0->1 to 0->2
  vec2 zeroToTwo = zeroToOne * 2.0;

  // convert from 0->2 to -1->+1 (clipspace)
  vec2 clipSpace = zeroToTwo - 1.0;

  gl_Position = vec4(clipSpace * vec2(1, -1), 0, 1);
}
`;

  var fragmentShaderSource = `#version 300 es

precision highp float;

uniform vec4 u_color;

// we need to declare an output for the fragment shader
out vec4 outColor;

void main() {
  outColor = u_color;
}
`;

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

    // Use our boilerplate utils to compile the shaders and link into a program
    var program = webglUtils.createProgramFromSources(gl,
      [vertexShaderSource, fragmentShaderSource]);

    // look up where the vertex data needs to go.
    var positionAttributeLocation = gl.getAttribLocation(program, "a_position");

    // look up uniform locations
    var resolutionUniformLocation = gl.getUniformLocation(program, "u_resolution");
    var colorLocation = gl.getUniformLocation(program, "u_color");

    // Create a buffer
    var positionBuffer = gl.createBuffer();

    // Create a vertex array object (attribute state)
    var vao = gl.createVertexArray();

    // and make it the one we're currently working with
    gl.bindVertexArray(vao);

    // Turn on the attribute
    gl.enableVertexAttribArray(positionAttributeLocation);

    // Bind it to ARRAY_BUFFER (think of it as ARRAY_BUFFER = positionBuffer)
    gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);

    // Tell the attribute how to get data out of positionBuffer (ARRAY_BUFFER)
    var size = 2;          // 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);

    webglUtils.resizeCanvasToDisplaySize(gl.canvas);

    // Tell WebGL how to convert from clip space to pixels
    gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);

    // Clear the canvas
    gl.clearColor(0, 0, 0, 0);
    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

    // Tell it to use our program (pair of shaders)
    gl.useProgram(program);

    // Bind the attribute/buffer set we want.
    gl.bindVertexArray(vao);

    // Pass in the canvas resolution so we can convert from
    // pixels to clipspace in the shader
    gl.uniform2f(resolutionUniformLocation, gl.canvas.width, gl.canvas.height);
    //const array = new Uint16Array(30_000);
    //const randNum = self.crypto.getRandomValues(array);
    // draw 50 random rectangles in random colors
    var primitiveType = gl.TRIANGLES;
    var offset = 0;
    var count = 6;
    var counter = 0;
    var array2D = [];
    var y_cnt = 0;
    var x_cnt = 0;
    for (var size = 0; size < 1000; ++size) {
      array2D[size] = self.crypto.getRandomValues(new Uint16Array(1000));
    }
    for (var y = 0; y < 2000; y = y + 2) {
      for (var x = 0; x < 2000; x = x + 2) {
        setRectangle(gl, x, y, 2, 2);
        gl.uniform4f(colorLocation, 0.0, 0.0, 0.0, normalizeUint16(array2D[y / 2][x / 2]));
        gl.drawArrays(primitiveType, offset, count);
        counter++;
      }
    }
  }

  // Returns a random integer from 0 to range - 1.
  function randomInt(range) {
    return Math.floor(Math.random() * range);
  }

  function normalizeUint16(val) {
    return val / 65535;

  }

  // Fill the buffer with the values that define a rectangle.
  function setRectangle(gl, x, y, width, height) {
    var x1 = x;
    var x2 = x + width;
    var y1 = y;
    var y2 = y + height;
    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
      x1, y1,
      x2, y1,
      x1, y2,
      x1, y2,
      x2, y1,
      x2, y2,
    ]), gl.STATIC_DRAW);
  }

  main();

</script>
<script>
  // Function to detect the browser name
  function detectBrowser() {
    var userAgent = navigator.userAgent;
    if (userAgent.indexOf("Edg") > -1) {
      return "Microsoft Edge";
    } else if (userAgent.indexOf("Chrome") > -1) {
      return "Chrome";
    } else if (userAgent.indexOf("Firefox") > -1) {
      return "Firefox";
    } else if (userAgent.indexOf("Safari") > -1) {
      return "Safari";
    } else if (userAgent.indexOf("Opera") > -1) {
      return "Opera";
    } else if (userAgent.indexOf("Trident") > -1 || userAgent.indexOf("MSIE") > -1) {
      return "Internet Explorer";
    }

    return "Unknown";
  }

  // Get the browser name and display it
  var browserName = detectBrowser();
  document.getElementById("browser-name").innerText = "Detected Browser: " + browserName;
</script>

{% endblock %}