"use strict";

import { resize, Slider, createResetButton} from "../../modules/HTMLUtils.js"; 
import WebGL from "../../modules/WebGLUtils.js";
import M4 from "../../modules/M4.js";
import V3 from "../../modules/V3.js";
import GeometryPainter from "../../geometry/GeometryPainter.js";
import Cube from "../../geometry/Cube.js";
import VertexColor from "../../materials/VertexColor.js";
import SolidColor from "../../materials/SolidColor.js";
import { QuadCube } from "../../geometry/Figure.js";
import {TrackballCamera, registerCameraEvents} from "../../modules/Trackballcamera.js";

/**
 * Transformación de proyección de perspectiva.
 * @author Melissa Méndez Servín.
 */
window.addEventListener("load", main);

var translation = [0,0,0];
function main(){
    document.body.style.backgroundColor = "white"; 
    var canvas = document.getElementById("gl_canvas");
    var gl = WebGL.init(canvas);
    if(!gl) return;
    
    let cubeFigure = new Cube(1,0);
    let cube = new GeometryPainter(gl, new VertexColor(gl, WebGL, cubeFigure, true));
    let frustrumFigure = new QuadCube(2);
    //let pyramidFigure = new QuadCone(1,2,false);
    let frustrum = new GeometryPainter(gl, new SolidColor(gl, WebGL, frustrumFigure, [0,0,0,1]));
    //let pyramid = new GeometryPainter(gl, new SolidColor(gl, WebGL, pyramidFigure, [0,0,0,1]));
    
    //HTML CONTROLS
    let frame = document.getElementById("frame");
    let controls = document.getElementById("ui-container");
    controls.className = "right-box";

    resize(canvas);

    let fov = 45;
    let near = 1;
    let far = 5;
    let viewMatrix;
    var sceneProjectionMatrix;
    var projectionMatrix;
    var cubeModelMatrix;
    var frustrumModelMatrix;
    var modelViewMatrix;

    let rotationMatrix = M4.multiply(M4.rotateY(20), M4.rotateX(8));  
    let cameraPosition = M4.multiplyVector(M4.multiply(M4.rotateY(-17), M4.rotateX(-9)), [-.7,0.2, 3.2,1]);
    let camera = new TrackballCamera(new V3(cameraPosition[0], cameraPosition[1], cameraPosition[2]));
    let viewCameraMatrix = M4.camera(new V3(0,0,2.4), new V3(0,0,0), new V3(0,1,0));

    let sliders = [ /*new Slider(controls, "Tx", -3, 3, updateTranslation(0), translation[0], .1),
                    new Slider(controls, "Ty", -3, 3, updateTranslation(1), translation[1], .1),
                    new Slider(controls, "Tz", -3, 3, updateTranslation(2), translation[2],.1), */
                    new Slider(controls, "FOV", 0, 170, updateFOV(0), fov),
                    new Slider(controls, "n", 0.1,20, updateNF(0), near, .1),
                    new Slider(controls, "f", 1,20, updateNF(1), far, .1),
                    ];
    
    createResetButton(reset);

    window.addEventListener('resize', draw);
    
    gl.enable(gl.CULL_FACE);
    gl.enable(gl.DEPTH_TEST);
    gl.enable(gl.SCISSOR_TEST);
    gl.clearColor(0, 0, 0, 0);

    registerCameraEvents(camera, canvas, draw);
    draw();

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

        const smallWidth = width / 2.5 | 0;
        const smallHeight = height / 2.5 | 0;        
        frame.style.height = smallHeight - 2 + "px";
        frame.style.width = smallWidth - 2 + "px";

        viewMatrix = camera.getMatrix();
        
        //dibuja vista grande
        gl.scissor(0, 0, width, height);
        gl.viewport(0, 0, width, height);
        gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
        
        
        let aspect = width/height;
        sceneProjectionMatrix = M4.perspective(90, aspect, .1, 60);
        projectionMatrix = M4.perspective(fov, aspect, near, far);
        
        cubeModelMatrix = M4.multiply(M4.translate(translation[0], translation[1], translation[2]), rotationMatrix);
        modelViewMatrix = M4.multiply(viewMatrix, cubeModelMatrix);
        cube.drawSimple(gl, modelViewMatrix, sceneProjectionMatrix);   
        var rotate = M4.multiply(M4.rotateZR(Math.PI/4), M4.rotateXR(Math.PI/2));
  
        frustrumModelMatrix = M4.multiply(M4.translate(0,0,2.4),  M4.inverse(projectionMatrix));
        modelViewMatrix = M4.multiply(viewMatrix, frustrumModelMatrix);
        frustrum.drawWireframeQuad(gl, modelViewMatrix, sceneProjectionMatrix);   
        
        //vista pequeña (lo que la cámara ve)
        gl.viewport(0, 0, smallWidth, smallHeight);
        gl.scissor(0, 0, smallWidth, smallHeight);
        gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
                    
        cube.drawSimple(gl, M4.multiply(viewCameraMatrix, cubeModelMatrix), projectionMatrix);   
    }
    function tan(angle){
        return Math.tan(angle*Math.PI/180) + 1 - 1;
    }
    function updateFOV(){
        return function(value){
            fov = value;
            draw();
        };
    }
    function updateNF(index){
        return function(value){
            if(index == 0)
                near = value;
            else 
                far =value;
            draw();
        };
    }
    function updateTranslation(index){
        return function(value){
            translation[index] = value;
            draw();
        };
    }
    function reset(){
        fov = 45;
        for(var i = 0; i< sliders.length; i++){
            sliders[i].updateSlider(sliders[i].initValue);
        }
        draw();
    }
}