const QUAD_VERTICES = new Float32Array([
  -1, -1,
  3, -1,
  -1, 3,
]);

function createGL(canvas) {
  const gl = canvas.getContext("webgl2", {
    alpha: false,
    antialias: false,
    depth: false,
    preserveDrawingBuffer: false,
    premultipliedAlpha: false,
    stencil: false,
  });

  if (!gl) {
    throw new Error("WebGL2 is required.");
  }

  const vao = gl.createVertexArray();
  const vbo = gl.createBuffer();
  gl.bindVertexArray(vao);
  gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
  gl.bufferData(gl.ARRAY_BUFFER, QUAD_VERTICES, gl.STATIC_DRAW);
  gl.enableVertexAttribArray(0);
  gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0);
  gl.bindVertexArray(null);

  gl.disable(gl.DEPTH_TEST);
  gl.disable(gl.BLEND);

  return { gl, vao };
}

function createProgram(gl, fragmentSource, label = "shader", lineOffset = 0) {
  const vertexShader = compileShader(gl, gl.VERTEX_SHADER, vertexSource(), `${label} vertex`, 0);
  const fragmentShader = compileShader(gl, gl.FRAGMENT_SHADER, fragmentSource, label, lineOffset);
  const program = gl.createProgram();
  gl.attachShader(program, vertexShader);
  gl.attachShader(program, fragmentShader);
  gl.bindAttribLocation(program, 0, "position");
  gl.linkProgram(program);

  if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
    const log = gl.getProgramInfoLog(program) || "Unknown link error";
    gl.deleteProgram(program);
    gl.deleteShader(vertexShader);
    gl.deleteShader(fragmentShader);
    throw new Error(`${label} link failed:\n${log}`);
  }

  gl.deleteShader(vertexShader);
  gl.deleteShader(fragmentShader);
  return program;
}

function drawFullscreen(gl, vao) {
  gl.bindVertexArray(vao);
  gl.drawArrays(gl.TRIANGLES, 0, 3);
  gl.bindVertexArray(null);
}

function setCanvasSize(canvas, gl, width, height) {
  if (canvas.width !== width || canvas.height !== height) {
    canvas.width = width;
    canvas.height = height;
  }
  gl.viewport(0, 0, width, height);
  return { width, height, pixelRatio: 1 };
}

function compileShader(gl, type, source, label, lineOffset) {
  const shader = gl.createShader(type);
  gl.shaderSource(shader, source);
  gl.compileShader(shader);
  if (gl.getShaderParameter(shader, gl.COMPILE_STATUS)) return shader;

  const log = gl.getShaderInfoLog(shader) || "Unknown compile error";
  gl.deleteShader(shader);
  throw new Error(`${label} compile failed:\n${rewriteShaderLog(log, lineOffset)}`);
}

function rewriteShaderLog(log, lineOffset) {
  return log.replace(/ERROR:\s*0:(\d+):/g, (_, line) => {
    const mapped = Math.max(1, Number(line) - lineOffset);
    return `ERROR: shader:${mapped}:`;
  });
}

function vertexSource() {
  return `#version 300 es
layout(location = 0) in vec2 position;
void main() {
  gl_Position = vec4(position, 0.0, 1.0);
}
`;
}

