"use strict";

import * as Utils from "../../modules/HTMLUtils.js";
import WebGL from "../../modules/WebGLUtils.js";
import M4 from "../../modules/M4.js";
import Diffuse from "../../materials/Diffuse.js";
import { Cone, Sphere } from "../../geometry/Figure.js";
import Vector3D from "../../geometry/Vector3D.js";
import GeometryPainter from "../../geometry/GeometryPainter.js";
import {TrackballCamera, registerCameraEvents} from "../../modules/Trackballcamera.js";
import V3 from "../../modules/V3.js";

/**
 * Transformación de la normal usando una matriz no ortogonal.
 * Comparación entre la transformación correcta e incorrecta de los vectores normales 
 * de una pirámide.
 * @author Melissa Méndez Servín.
 */
window.addEventListener("load", main);

function main(){
    var canvas = document.getElementById("gl_canvas");
    var gl = WebGL.init(canvas);
    if(!gl) return;
    
    let pyramidFigure = new Cone(1.2,1.5,3, false);
    
    let lightPosition = [0, -.5, 1, 0];
    let yellowUniforms = {u_color: [1,1,0,1]};
    let greenUniforms = {u_color: [.5,.7,.5,1]};
    let diffuseMaterial = new Diffuse(gl, WebGL, pyramidFigure, yellowUniforms);
    
    let vertices = pyramidFigure.vertices;
    let nv = vertices.length;
    let triangle = [ vertices[0], vertices[1], vertices[2],
                     vertices[3], vertices[4], vertices[5],
                     vertices[nv-3], vertices[nv-2], vertices[nv-1]];
    let center_x = ( vertices[0] + vertices[3] + vertices[nv-3])/3;
    let center_y = ( vertices[1] + vertices[4] + vertices[nv-2])/3;
    let center_z = ( vertices[2] + vertices[5] + vertices[nv-1])/3;
    let triangleCenter = [center_x, center_y, center_z, 1];
    
    let yellowPyramid = new GeometryPainter(gl, diffuseMaterial);
    let rightTransformation;
    let rightInverse;
    
    let greenPyramid = new GeometryPainter(gl, new Diffuse(gl, WebGL, pyramidFigure, greenUniforms));  
    let leftTransformation;

    var v0 = new V3(triangle[0], triangle[1], triangle[2]);
    var v1 = new V3(triangle[3], triangle[4], triangle[5]);
    var v2 = new V3(triangle[6], triangle[7], triangle[8]);
    let n =  v2.sub(v0).cross(v1.sub(v0)).normalize();
    let normal =  n.toArray(0);
    
    let normalOne = new Vector3D(gl, WebGL, n, null, .1, [.5,.7,.5,1], lightPosition); 
    let normalTwo = new Vector3D(gl, WebGL, n, null, .1, [1,1,0,1], lightPosition); 
    
    var fov = 80;
    let zNear = 1;
    let zFar = 200;
    let pos = M4.multiplyVector(M4.rotateY(-15), [0,.9,4,1]);
    
    let camera = new TrackballCamera(
        new V3(pos[0],pos[1],pos[2]),
        new V3(0,.9,0)
    );
    
    Utils.resize(canvas);
    
    gl.enable(gl.CULL_FACE);
    gl.enable(gl.DEPTH_TEST);
    gl.clearColor(0, 0, 0, 0);

    //registerCameraEvents(camera, canvas, draw);
    let viewMatrix = camera.getMatrix();
    var lightPos = M4.multiplyVector(viewMatrix, lightPosition);
    yellowUniforms.u_light_position = lightPos;
    greenUniforms.u_light_position = lightPos;
        
    var time = 0; //Contador de tiempo para hacer la espera
    const wait_time = 1.5; //tiempo de espera
    var t = 0;
    var c = 0; //Contador auxiliar 

    draw();

    function draw(){        
        Utils.resize(canvas);
        var {width, height} = gl.canvas;

        gl.viewport(0, 0, width, height);
        gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
             
        let aspect = width/height;
        var projectionMatrix = M4.perspective(fov, aspect, zNear, zFar);

        let scale = M4.scale(1-.4*t, 1+ 1.3*t, 1);
        
        leftTransformation = M4.multiply(M4.translate(-2,0,0), M4.multiply(M4.rotateY(60), scale));
        leftTransformation = M4.multiply(leftTransformation, M4.translate(0,0.5,0));
        rightTransformation = M4.multiply(M4.translate(2,0,-.5), M4.multiply(M4.rotateY(14), scale));
        rightTransformation = M4.multiply(rightTransformation, M4.translate(0,0.5,0));
        let modelViewLeftMatrix = M4.multiply(viewMatrix, leftTransformation);
        let modelViewRightMatrix = M4.multiply(viewMatrix, rightTransformation);
        
        greenUniforms.u_VMN_matrix = modelViewLeftMatrix;
        greenPyramid.draw(gl, modelViewLeftMatrix, projectionMatrix, greenUniforms);  
        yellowUniforms.u_VMN_matrix = M4.transpose(M4.inverse(modelViewRightMatrix));
        yellowPyramid.draw(gl, modelViewRightMatrix, projectionMatrix, yellowUniforms); 
        
        //El punto centríco de la cara
        let leftNormalCenter = M4.multiplyVector(leftTransformation, triangleCenter);      
        let rightNormalCenter = M4.multiplyVector(rightTransformation, triangleCenter);      
        let ncl = new V3(leftNormalCenter[0], leftNormalCenter[1], leftNormalCenter[2]);
        let ncr = new V3(rightNormalCenter[0], rightNormalCenter[1], rightNormalCenter[2]);
        //La normal de la cara
        rightInverse = M4.transpose(M4.inverse(rightTransformation));
        let leftNormal = M4.multiplyVector( leftTransformation, normal);      
        let rightNormal = M4.multiplyVector(rightInverse, normal);      
        let nl = new V3(leftNormal[0], leftNormal[1], leftNormal[2]);
        let nr = new V3(rightNormal[0], rightNormal[1], rightNormal[2]);
       
        normalOne.draw(gl, viewMatrix, projectionMatrix, lightPos, nl.normalize(), ncl); 
        normalTwo.draw(gl, viewMatrix, projectionMatrix, lightPos, nr.normalize(), ncr);
        if(t == 1 && time <= wait_time){
            time += 0.05;
        }
        else{
            time = 0;
            //Actualizamos t 
            c = (c + 5) % 1005; // Cálculo con enteros para evitar problemas de precisión con decimales de js 
            t = c / 1000;
        }
        requestAnimationFrame(draw);
    
    }
}