"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 SolidColor from "../../materials/SolidColor.js";
import { Cube, QuadCube } from "../../geometry/Figure.js";
import {TrackballCamera, registerCameraEvents} from "../../modules/Trackballcamera.js";
import DirectionalLight from "../../materials/DirectionalLight.js";

/**
 * Transformación de proyección de perspectiva.
 * @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 lightDirection = [0, -4, -2, 0];
    let material = { ka: [0.2,.2,.2], kd: [0.780392, 0,0], ks: [0.992157, 0.941176, 0.807843], 
                     shininess: 0.21794872*128};
    let light = { direction: lightDirection, la: [.3, .3, .3], ld: [1,1,1], ls: [1.0, 1.0, 1.0]};
    let uniforms = { u_light: light, u_material: material};  
    let cubeFigure = new Cube();
    let cube = new GeometryPainter(gl, new DirectionalLight(gl, WebGL, cubeFigure, uniforms));
    let frustrumFigure = new QuadCube(2);
    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 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 perspectiveMatrix;
    var modelViewMatrix;

    let cameraPosition = M4.multiplyVector(M4.multiply(M4.rotateY(-17), M4.rotateX(-9)), [-.7,0.2, 4.2,1]);
    let camera = new TrackballCamera(new V3(cameraPosition[0], cameraPosition[1], cameraPosition[2]));
    
    let sliders = [ 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),
                    ];
    
    window.addEventListener('resize', draw);
    
    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 | 0;     
      
        viewMatrix = camera.getMatrix();
        var lightDir = M4.multiplyVector(viewMatrix, lightDirection);
        uniforms.u_light.direction = lightDir;
        
        //Izquierda. En persepectiva
        gl.scissor(0, 0, smallWidth, height);
        gl.viewport(0, 0, smallWidth, height);
        gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
        
        
        let aspect = smallWidth/height;
        sceneProjectionMatrix = M4.perspective(90, aspect, 1, 200);
        perspectiveMatrix = M4.perspective(fov, aspect, near, far);
        
        cube.draw(gl, M4.multiply(viewMatrix, M4.translate(0,0,-1.5)), sceneProjectionMatrix);   
        var inversePerspective = M4.inverse(perspectiveMatrix);
        modelViewMatrix = M4.multiply(viewMatrix, inversePerspective);
        frustrum.drawWireframeQuad(gl, modelViewMatrix, sceneProjectionMatrix);   
        
        //Derecha. Clip Space
        gl.viewport(smallWidth, 0, smallWidth, height);
        gl.scissor(smallWidth, 0, smallWidth, height);
        gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

        cube.draw(gl,  M4.multiplyArray([viewMatrix, M4.scale(.1,.1,.1), perspectiveMatrix]), sceneProjectionMatrix);   
        frustrum.drawWireframeQuad(gl, viewMatrix, sceneProjectionMatrix);               
    }
    function updateFOV(){
        return function(value){
            fov = value;
            draw();
        };
    }
    function updateNF(index){
        return function(value){
            if(index == 0)
                near = value;
            else 
                far =value;
            draw();
        };
    }
}