"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 ortográfica.
 * @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;
    resize(canvas);
    
    var {width, height} = gl.canvas;
    const ratio = 140;
    const smallWidth = width / 1.5 | 0;
    const smallHeight = height / 1.5 | 0;   

    let boundary = { l: -smallWidth/ratio, r: smallWidth/ratio, 
                     t: smallHeight/ratio, b: -smallHeight/ratio,
                     n: -.1, f: -3
                   };

    let cubeFigure = new Cube(1,0);
    let cube = new GeometryPainter(gl, new VertexColor(gl, WebGL, cubeFigure, true));
    let prismFigure = new QuadCube(2);
    let ortho = new GeometryPainter(gl, new SolidColor(gl, WebGL, prismFigure, [0,0,0,1]));
    
    //HTML CONTROLS
    let frame = document.getElementById("frame");
    let controls = document.getElementById("ui-container");
    controls.className = "right-box";

    let viewMatrix;
    var projectionMatrix;
    var orthoProjectionMatrix;
    var cubeModelMatrix;
    var orthoModelMatrix;
    var modelViewMatrix;
    let rotationMatrix = M4.multiply(M4.rotateY(20), M4.rotateX(8));  
    let cameraPosition = M4.multiplyVector(M4.rotateY(-35), [0,0, 5,1]);
    
    let camera = new TrackballCamera(new V3(cameraPosition[0], cameraPosition[1], cameraPosition[2]));

    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, "l", -4, 0, updateOrtho(0), boundary.l.toFixed(2),.01),
                    new Slider(controls, "r", 0, 4, updateOrtho(1), boundary.r.toFixed(2),.01),
                    new Slider(controls, "t", 0, 4, updateOrtho(2), boundary.t.toFixed(2),.01),
                    new Slider(controls, "b", -4, 0, updateOrtho(3), boundary.b.toFixed(2),.01),
                    new Slider(controls, "n", -2, 2, updateOrtho(4), boundary.n.toFixed(2),.01),
                    new Slider(controls, "f", -4, 0, updateOrtho(5), boundary.f.toFixed(2),.01),
                    ];
    
    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;
        projectionMatrix = M4.perspective(90, aspect, .1, 150);
        orthoProjectionMatrix = M4.ortho(boundary.l, boundary.r, boundary.t, boundary.b, boundary.n, boundary.f);
        
        cubeModelMatrix = M4.multiply(M4.translate(translation[0], translation[1], translation[2]-1), rotationMatrix);
        modelViewMatrix = M4.multiply(viewMatrix, cubeModelMatrix);
        cube.drawSimple(gl, modelViewMatrix, projectionMatrix);   
        
        orthoModelMatrix = M4.multiply(M4.translate(0,0,0), M4.inverse(orthoProjectionMatrix));
        modelViewMatrix = M4.multiply(viewMatrix, orthoModelMatrix);
        ortho.drawWireframeQuad(gl, modelViewMatrix, projectionMatrix);   
        
        
        //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, cubeModelMatrix, orthoProjectionMatrix);   
    }

    function updateOrtho(index){
        return function(value){
            switch(index){
                case 0: 
                    boundary.l = value;
                    break;
                case 1:
                    boundary.r = value;
                    break;
                case 2: 
                    boundary.t = value;
                    break;
                case 3:
                    boundary.b = value;
                    break;
                case 4: 
                    boundary.n = value;
                    break;
                case 5:
                    boundary.f = value;
                    break;
                    
            }
            draw();
        }
        
    }
    function updateTranslation(index){
        return function(value){
            translation[index] = value;
            draw();
        };
    }
    function reset(){
        translation = [0,0,0];
        for(var i = 0; i< sliders.length; i++){
            sliders[i].updateSlider(sliders[i].initValue);
        }
        boundary = {l: -smallWidth/ratio, r: smallWidth/ratio, 
                    t: smallHeight/ratio, b: -smallHeight/ratio,
                    n: 2, f: -2};
        draw();
    }
}