"use strict";

import {resize, Slider} from "../../modules/HTMLUtils.js";
import WebGL from "../../modules/WebGLUtils.js";
import M4 from "../../modules/M4.js";
import V3 from "../../modules/V3.js";
import {lerp, bezierCurve} from "../../modules/MathUtils.js";
import GridXZ from "../../geometry/GridXZ.js";
import Diffuse from "../../materials/Diffuse.js";
import VertexColor from "../../materials/VertexColor.js";
import Cube from "../../geometry/Cube.js";
import GeometryPainter from "../../geometry/GeometryPainter.js";
import { Cone, RectangularPrism} from "../../geometry/Figure.js";
import Vector3D from "../../geometry/Vector3D.js";
import {TrackballCamera, registerCameraEvents} from "../../modules/Trackballcamera.js";

/**
 * Transformación de la cámara (Animación).
 * @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;
    
    //Figuras
    let gridXZ = new GridXZ(gl,44);

    let cubeFigure = new Cube(.5, 1);
    let cube = new GeometryPainter(gl, new VertexColor(gl, WebGL, cubeFigure, true));
    let rectPrismFigure = new RectangularPrism(.42, .5, .6); //Base para la cámara
    let coneFigure = new Cone(.23,.4, 100); //Lente de la cámara
    
    let lightPosition = [0, 5, 0, 0];
    let cameraUniforms = {u_color: [0,1,1,1], u_light_position: lightPosition};
    
    let targetPosition = new V3(3.75,0.5, -.9); //el centro del objetivo de la cámara (objeto)
    let cameraPosition = new V3(-.8, 0.5, 3.4);  //la posición de la cámara (objeto)
    let dir = cameraPosition.sub(targetPosition).normalize();
    //Vector auxiliar para realizar el mapeo de la posición de la cámara a la dirección de -dir
    let cameraInitDir = new V3(0,1,0); 
    let dirAxis = cameraInitDir.cross(dir); //El vector ortogonal 
    let theta = Math.acos(cameraInitDir.dotProduct(dir)) +  Math.PI; //El ángulo a rotar para mapear a -dir
    let cubeTargetTranslation = M4.translate(targetPosition.x, targetPosition.y, targetPosition.z);
    let cameraPostionTranslation = M4.translate(cameraPosition.x, cameraPosition.y, cameraPosition.z);
    var alignAxis = M4.identity();
    var alignCamera = M4.identity();
    //Objetos a renderizar 
    let bodyCamera = new GeometryPainter(gl, new Diffuse(gl, WebGL, rectPrismFigure, cameraUniforms));
    let coneCamera = new GeometryPainter(gl, new Diffuse(gl, WebGL, coneFigure, cameraUniforms));                                         
    
    //Flechas de la cámara 
    let o = new V3(0,0,0);
    let up = new V3(0,1,0);
    let w = dir;
    let u = up.cross(dir).normalize();
    let v = w.cross(u);
    let wArrow = new Vector3D(gl, WebGL, w, null, .1, [1,0,0,1], lightPosition); //Vector verde (z)
    let uArrow = new Vector3D(gl, WebGL, u, null, .1, [0,0,1,1], lightPosition); //Vector azul (x)
    let vArrow = new Vector3D(gl, WebGL, v, null, .1, [0,1,0,1], lightPosition); //Vector verde (y)
    
    let axis = [ new Vector3D(gl, WebGL, new V3(1,0,0), null, .1, [0,.2,1,1], lightPosition),
                 new Vector3D(gl, WebGL, up, null, .1, [0,1,0.2,1], lightPosition),
                 new Vector3D(gl, WebGL, new V3(0,0,1), null, .1, [1,.2,0,1], lightPosition)];
    
    //HTML CONTROLS
    let controls = document.getElementById("ui-container");
    controls.className = "right-box";
    
    resize(canvas);
    
    let zNear = 1;
    let zFar = 200;

    let cameraPositions = [ new V3(0.1,2,5.2), 
                            new V3(0,2.5,4), 
                            new V3(0,2.4,3),
                            new V3(0,2.2,2.5),
                            new V3(0,2.2,2.5),
                            new V3(0,2.3,2.5)
                        ];
    let camera = new TrackballCamera(cameraPositions[1]);

    //window.addEventListener('resize', draw);
    //registerCameraEvents(camera, canvas, draw);
    
    gl.enable(gl.CULL_FACE);
    gl.enable(gl.DEPTH_TEST);
    gl.clearColor(0, 0, 0, 0);

    var time = 0; //Contador de tiempo para hacer la espera
    const wait_time = .5; //tiempo de espera
    const vel = 8;
    var t = 0;
    var r = 0;
    var c1 = 0; //Contador auxiliar 
    var c2 = 0; //Contador auxiliar 
        
    draw();

    function draw(){
        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(90, aspect, zNear, zFar);
       // console.log(camera.pos);
        let s = (t+r)/2;
        let cameraBezierPoint = bezierCurve(cameraPositions, s);
        camera.pos = cameraBezierPoint;

        var viewMatrix = camera.getMatrix();
        
        var lightPos = M4.multiplyVector(viewMatrix, lightPosition);
        cameraUniforms.u_light_position = lightPos;

        gridXZ.draw(gl, viewMatrix, projectionMatrix);
        
        //Ejes XYZ
        for(var i=0; i < 3; i++)
            axis[i].draw(gl, viewMatrix, projectionMatrix, lightPos);
        
        //Cámara
        //Para la traslación al origen
        let lerpPosition = lerp(o, cameraPosition, t);
        let lerpTranslation = M4.translate(-lerpPosition.x, -lerpPosition.y, -lerpPosition.z);
        let cameraTranslation = M4.multiply(cameraPostionTranslation, lerpTranslation);
        let axisModelViewMatrix = M4.multiply(viewMatrix, cameraTranslation);
        let rotationCamera = M4.multiply(M4.rotate(dir, 0.25 * Math.PI), M4.rotate(dirAxis,theta));
        let modelCamera = M4.multiply(rotationCamera, M4.rotateX(-90));
        modelCamera = M4.multiply(cameraTranslation, modelCamera);
        
        var coneCameraModel = M4.multiply(M4.translate(0,0,.3),M4.rotateX(270));
        let cameraModelViewMatrix = M4.multiply(viewMatrix, modelCamera);
        
        alignCamera = M4.rotateYR( -r * 0.13 * 2*Math.PI);
        alignAxis = M4.rotateYR( r * 0.13 * 2*Math.PI);

        cameraModelViewMatrix = M4.multiply(cameraModelViewMatrix, alignCamera);
        axisModelViewMatrix = M4.multiply(axisModelViewMatrix, alignAxis);
        let modelViewCameraConeMatrix = M4.multiply(cameraModelViewMatrix, coneCameraModel);
        
        bodyCamera.draw(gl, cameraModelViewMatrix, projectionMatrix, cameraUniforms);  
        coneCamera.draw(gl, modelViewCameraConeMatrix, projectionMatrix, cameraUniforms);   
        //Eje de la cámara
        wArrow.draw(gl, axisModelViewMatrix, projectionMatrix, lightPos);
        uArrow.draw(gl, axisModelViewMatrix, projectionMatrix, lightPos);
        vArrow.draw(gl, axisModelViewMatrix, projectionMatrix, lightPos);
        
        //Cubo
        let cubeTransform = M4.multiply(alignAxis, M4.multiply(lerpTranslation, cubeTargetTranslation));  
        cubeTransform = M4.multiply(viewMatrix, cubeTransform);  
        cube.drawSimple(gl, cubeTransform, projectionMatrix);  
        
        if(t == 1 && r == 1 && time <= wait_time){
            time += 0.01;
        }else{
            if( t < 1 || time >= wait_time){
                r = 0;
                time = 0;
                //Actualizamos t 
                c1 = (c1 + vel) % (1000 + vel); // Cálculo con enteros para evitar problemas de precisión con decimales de js 
                t = c1 / 1000;
                //console.log("t",t, "r",r);
            }else{
                //Actualizamos r
                c2 = (c2 + vel) % (1000 + vel); // Cálculo con enteros para evitar problemas de precisión con decimales de js 
                r = c2 / 1000;
                //console.log("r",r, "c2", c2);
            }
        }
        requestAnimationFrame(draw);
    }
}