window.addEventListener("load", async function(evt) {
  const canvas = document.getElementById("the_canvas");
  const gl = canvas.getContext("webgl2");
  if (!gl) throw "WebGL no soportado";

  window.addEventListener("resize", resize);
  function resize() {
    let container = document.getElementById("contenedor");
    let scaleToFitX = window.innerWidth/container.offsetWidth;
    let scaleToFitY = window.innerHeight/container.offsetHeight;

    container.style.transformOrigin = "0 0";
    container.style.position = "absolute";
    container.style.margin = container.style.padding = 0;

    container.style.left = (scaleToFitX < scaleToFitY) ? "0" : "50%";
    container.style.top  = (scaleToFitX < scaleToFitY) ? "50%" : "0";
    container.style.transform = `translate3d(0px, 0px, 0px) scale(${Math.min(scaleToFitX, scaleToFitY)}) translate(-${container.style.left}, -${container.style.top})`;
  }

  resize();

  ////////////////////////////////////////////////////
  let geo_initial_transform = [
    identity(),
    identity(),
    identity(),
    identity(),
    identity(),
    identity(),
  ];

  let geometry = [
    new OBJGeometry(
      gl, 
      await loadText("Geometry/cabeza0.obj"),
      await loadText("Geometry/cabeza.mtl"),
      new PhongWireframeMaterial(gl, [0.1, 0.1, 0.1], [1, 0, 0], [0, 0, 0], 0.1, [1,1,1,1] ),
      geo_initial_transform[0]
    ),
    new OBJGeometry(
      gl, 
      await loadText("Geometry/cabeza1.obj"),
      await loadText("Geometry/cabeza.mtl"),
      new PhongWireframeMaterial(gl, [0.1, 0.1, 0.1], [1, 0, 0], [0, 0, 0], 0.1, [1,1,1,1] ),
      geo_initial_transform[1]
    ),
    new OBJGeometry(
      gl, 
      await loadText("Geometry/cabeza2.obj"),
      await loadText("Geometry/cabeza.mtl"),
      new PhongWireframeMaterial(gl, [0.1, 0.1, 0.1], [1, 0, 0], [0, 0, 0], 0.1, [1,1,1,1] ),
      geo_initial_transform[2]
    ),

    new OBJGeometry(
      gl, 
      await loadText("Geometry/cabeza3.obj"),
      await loadText("Geometry/cabeza.mtl"),
      new PhongWireframeMaterial(gl, [0.1, 0.1, 0.1], [1, 0, 0], [0, 0, 0], 0.1, [1,1,1,1] ),
      geo_initial_transform[3]
    ),
    new OBJGeometry(
      gl, 
      await loadText("Geometry/cabeza4.obj"),
      await loadText("Geometry/cabeza.mtl"),
      new PhongWireframeMaterial(gl, [0.1, 0.1, 0.1], [1, 0, 0], [0, 0, 0], 0.1, [1,1,1,1] ),
      geo_initial_transform[4]
    ),
    new OBJGeometry(
      gl, 
      await loadText("Geometry/cabeza5.obj"),
      await loadText("Geometry/cabeza.mtl"),
      new PhongWireframeMaterial(gl, [0.1, 0.1, 0.1], [1, 0, 0], [0, 0, 0], 0.1, [1,1,1,1] ),
      geo_initial_transform[5]
    ),
  ];

  let camera = new Camera(
    { x:0, y:0, z:9 }, // posición
    { x:0, y:0, z:0 }, // centro de interés
    { x:0, y:1, z:0 }, // vector hacia arriba
  );
  let viewMatrix;

  let area_width = gl.canvas.width/3;
  let area_height = gl.canvas.height/2;
  let projectionMatrix = perspective(45*Math.PI/180, area_width/area_height, 0.1, 2000);

  let light = new LuzPuntual(
    { x: 3, y: 3, z: 5 }, // posición
    [ 0.1, 0.1, 0.1 ],    // component ambiental
    [ 1, 1, 1 ],          // componente difuso
    [ 1, 1, 1 ]           // componente especular
  );

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

  let geo_rotation_transform = identity();

  /**
   */
  function draw() {
    gl.enable(gl.DEPTH_TEST);

    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

    viewMatrix = camera.getMatrix();

    // se actualiza la posición de la luz
    light.update(viewMatrix);

    for (let i=0; i<geometry.length; i++) {
      geometry[i].transform = multiply(
        geo_initial_transform[i],
        geo_rotation_transform
      );
    }

    gl.viewport(0, area_height, area_width, area_height);
    geometry[0].draw(gl, projectionMatrix, viewMatrix, light);

    gl.viewport(area_width, area_height, area_width, area_height);
    geometry[1].draw(gl, projectionMatrix, viewMatrix, light);

    gl.viewport(2*area_width, area_height, area_width, area_height);
    geometry[2].draw(gl, projectionMatrix, viewMatrix, light);

    gl.viewport(0, 0, area_width, area_height);
    geometry[3].draw(gl, projectionMatrix, viewMatrix, light);

    gl.viewport(area_width, 0, area_width, area_height);
    geometry[4].draw(gl, projectionMatrix, viewMatrix, light);

    gl.viewport(2*area_width, 0, area_width, area_height);
    geometry[5].draw(gl, projectionMatrix, viewMatrix, light);
  }

  draw();


  let theta_x = theta_y = old_theta_x = old_theta_y = 0;
  let initial_mouse_position = null;
  let new_mouse_position;
  canvas.addEventListener("mousedown", (evt) => {
    initial_mouse_position = getMousePositionInElement(evt, canvas);
    window.addEventListener("mousemove", mousemove);
  });
  window.addEventListener("mouseup", (evt) => {
    if (initial_mouse_position != null) {
      old_theta_x = theta_x;
      old_theta_y = theta_y;
      window.removeEventListener("mousemove", mousemove);
    }
    initial_mouse_position = null;
  });
  let mousemove = (evt) => {
    new_mouse_position = getMousePositionInElement(evt, canvas);
    theta_x = old_theta_x + (new_mouse_position.x - initial_mouse_position.x)*Math.PI/180;
    theta_y = old_theta_y + (new_mouse_position.y - initial_mouse_position.y)*Math.PI/180;

    geo_rotation_transform = multiply(
      rotateX(theta_y),
      rotateY(theta_x)
    );

    draw();
  }

});
