"use strict";

import {resize, Slider, Color, TextBox, DarkMode} from "../../modules/HTMLUtils.js";
import WebGL from "../../modules/WebGLUtils.js";
import M4 from "../../modules/M4.js";
import Phong from "../../materials/Phong.js";
import BlinnPhong from "../../materials/Blinn-Phong.js";
import {Sphere} from "../../geometry/Figure.js";
import GeometryPainter from "../../geometry/GeometryPainter.js";
import {TrackballCamera, registerCameraEvents} from "../../modules/Trackballcamera.js";
import V3 from "../../modules/V3.js";

/**
 * Comparación del Modelo de Iluminación de Blinn-Phong vs Modelo de Iluminación de Phong,
 * utilizando como base la misma esfera con las mismas propiedades de iluminació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;
    
    let sphereFigure = new Sphere(.85, 30,30);
    let lightPosition = [23, 45, 2, 0];
    let material = { ka: 0.3, kd: 1, ks: 1, shininess: 20};
    let light = { position: lightPosition, la: [0.423, 0.352, 0.466], ld: [0.650, 0.517, 0.741],
                  ls: [1.0, 1.0, 1.0]};
    let diffuseUniforms = { u_light: light, u_material: material}; 
    let phong_figure = new GeometryPainter(gl, new Phong(gl, WebGL, sphereFigure, diffuseUniforms), M4.translate(0,-.2,0));
    let blinn_figure = new GeometryPainter(gl, new BlinnPhong(gl, WebGL, sphereFigure, diffuseUniforms), M4.translate(0,-.2,0));
   
    var fov = 90;
    if(window.innerWidth < window.innerHeight)
        fov = 120;

    let zNear = 1;
    let zFar = 100;
    var pos = new V3(0,1.4,2.7);
    let camera = new TrackballCamera(pos);
   
    let container = document.getElementById("container");
    let PLabel = new TextBox(container, { left: 2, top: 18}, "Modelo de Phong.");
    let BPLabel = new TextBox(container, { left: 55, top: 18}, "Modelo de Blinn-Phong.");

    let controls = document.getElementById("ui-container");
    controls.className = "big-bottom-box";

    /* Luz Especular */
    var ks_slider = new Slider(controls, "k<sub>S</sub>", 0, 1, upadeteK(2), material.ks, 0.01, ["#4994D0"], "", true);
    var specular_color = new Color(controls, "L<sub>S</sub>", setColor(2), "#FFFFFF");
    var shininess_slider = new Slider(controls, "α", .1, 300, upadeteShininess,  material.shininess, 0.1, ["#4994D0"], "", true);

    let darkMode = new DarkMode(draw, [controls]);

    gl.enable(gl.DEPTH_TEST);
    gl.enable(gl.CULL_FACE);
    gl.enable(gl.SCISSOR_TEST);

    window.addEventListener('resize', draw);
    registerCameraEvents(camera, canvas, draw);
    
    draw();
    
    function draw(){        
        resize(canvas);

        const {width, height} = gl.canvas;
        const leftWidth = width / 2 | 0;
        const rightWidth = width - leftWidth;
        
        //dibuja vista izquierda
        gl.viewport(0, 0, leftWidth, height);
        gl.scissor(0, 0, leftWidth, height);
        darkMode.check(gl);
        gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
             
        var projectionMatrix = M4.perspective(fov, leftWidth/height, zNear, zFar);

        let viewMatrix = camera.getMatrix();
        var lightPos = M4.multiplyVector(viewMatrix, lightPosition);
        
        diffuseUniforms = { u_light: light, u_material: material}; 
        diffuseUniforms.u_light.position = lightPos;
 
        phong_figure.draw(gl, viewMatrix, projectionMatrix, diffuseUniforms); 
    
        //dibuja vista derecha
        gl.viewport(leftWidth, 0, rightWidth, height);
        gl.scissor(leftWidth, 0, rightWidth, height);
        darkMode.check(gl);
        gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
        
        blinn_figure.draw(gl, viewMatrix, projectionMatrix, diffuseUniforms); 

    }

    function upadeteShininess(value){
        material.shininess = value;
        draw();
    }
    function upadeteK(index){
        return function(value){
            switch(index){
                case 0:
                    material.ka = value;
                    break;
                case 1:
                    material.kd = value;
                    break;
                case 2:
                    material.ks = value;
                    break;
            }
            draw();
        }
    }
    function setColor(index){
        return function(value){
            switch(index){
                case 0:
                    light.la = value;
                    break;
                case 1:
                    light.ld = value;
                    break;
                case 2:
                    light.ls = value;
                    break;
            }
            draw();
        }
    }
    function upadeteLPos(index){
        return function(value){
            lightPosition[index] = value;
            draw();
        }
    }
}