"use strict";

import {resize, Slider, Color, addLabel, resizeAndCenterX, DarkMode, TextBox, Select} from "../../modules/HTMLUtils.js";
import WebGL from "../../modules/WebGLUtils.js";
import M4 from "../../modules/M4.js";
import Spotlight from "../../materials/Spotlight.js";
import {Sphere, Cube, RectangularPrism} from "../../geometry/Figure.js";
import GeometryPainter from "../../geometry/GeometryPainter.js";
import {TrackballCamera, registerCameraEvents} from "../../modules/Trackballcamera.js";
import V3 from "../../modules/V3.js";
import Teapot from "../../geometry/Teapot.js";
import Bunny from "../../geometry/Bunny.js";
import Light from "../../geometry/Light.js";

/**
 * Fuente de luz de reflector o spotlight.
 * @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(1, 30,30);
    let cubeFigure = new Cube(1.35);
    let teapotFigure = new Teapot();
    let bunnyFigure = new Bunny();
    
    let height = -1.4;
    let lightPosition = [0, 5.05, -6.37, 0];
    let lightDirection = [0, -1, 0, 0];
    let material = { ka: [0.1745, 0.01175, 0.01175], kd: [0.61424, 0.04136, 0.04136], ks: [0.727811, 0.626959, 0.626959], 
                     shininess: 0.6*128};
    let material_plane = { ka: [0.105882, 0.058824, 0.113725], kd: [0.427451, 0.470588, 0.541176], ks: [0.333333, 0.333333, 0.521569], 
                    shininess: 9.84615*128};
    let light = { position: lightPosition, direction: lightDirection, la: [.3, .3, .3], ld: [1,1,1], ls: [1.0, 1.0, 1.0],
                  quadratic : 0.01, linear: 0.0, constant: 0.03, cut_off: cos(36), fall_off: 5};
    let uniforms = { u_light: light, u_material: material};  
    let translate = M4.translate(0,.5,0);
    let figures = { 
        tetera: new GeometryPainter(gl, new Spotlight(gl, WebGL, teapotFigure, uniforms), M4.multiply(M4.scale(.9,.9,.9), translate)),
        cubo: new GeometryPainter(gl, new Spotlight(gl, WebGL, cubeFigure, uniforms), translate) ,
        esfera : new GeometryPainter(gl, new Spotlight(gl, WebGL, sphereFigure, uniforms), M4.translate(0,.75,0)),
        conejo: new GeometryPainter(gl, new Spotlight(gl, WebGL, bunnyFigure, uniforms), translate)};

    let selectedFigure = figures.tetera;  
    
    //Piso 
    var rect = new RectangularPrism(25,.5,25,true);
    let plane = new GeometryPainter(gl, new Spotlight(gl, WebGL, rect, uniforms), M4.translate(0,height,-7)); 

    var fov = 105;
    let zNear = .1;
    let zFar = 100;
    var pos = new V3(0,1.2,2.7);
    let camera = new TrackballCamera(pos);
    
    let light_controls = document.getElementById("ui-container-up");
    addLabel(light_controls, "Posición");
    var light_pos_x = new Slider(light_controls, "x", -5, 5, upadeteLPos(0), lightPosition[0], 0.01, ["#4994D0"]);
    var light_pos_y = new Slider(light_controls, "y", height, 10, upadeteLPos(1), lightPosition[1], 0.01, ["#4994D0"]);
    var light_pos_z = new Slider(light_controls, "z", -15, 5, upadeteLPos(2), lightPosition[2], 0.01, ["#4994D0"]);
    
    addLabel(light_controls, "Dirección");
    var light_dir_x = new Slider(light_controls, "x", -5, 5, upadeteLDir(0), lightDirection[0], 0.01, ["#4994D0"]);
    var light_dir_y = new Slider(light_controls, "y", -5, 5, upadeteLDir(1), lightDirection[1], 1, ["#4994D0"]);
    var light_dir_z = new Slider(light_controls, "z", -5, 5, upadeteLDir(2), lightDirection[2], 0.01, ["#4994D0"]);

    let controls = document.getElementById("ui-container-center");
    controls.setAttribute("obscure-mode", true);
    var theta_slider = new Slider(controls, "θ", 0, 180, upadeteCutOff, 90, 1, ["#4994D0"], "");
    var f_slider = new Slider(controls, "f", 0, 100, upadeteFallOff, light.fall_off, 0.01, ["#4994D0"], "");

    var diffuse_color = new Color(controls, "L<sub>D</sub>", setColor, "#FFFFFF");

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

    let ccLabel = new TextBox(container, { left: 5, top: 16}, "", "author-small");

    /* Selects */
    let right_controls = document.getElementById("right-options");
    let selectFigure = new Select(right_controls, "figures", setFigure, figures);
    //Luz
    let bulb = new Light(gl, WebGL, lightPosition);

    let modelViewMatrix;

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

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

    function draw(){        
        resize(canvas);
        resizeAndCenterX(light_controls, {});
        resizeAndCenterX(controls, {bottom:5});
        var {width, height} = gl.canvas;
        
        darkMode.check(gl);

        gl.viewport(0, 0, width, height);
        gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

        let aspect = width/height;
        var projectionMatrix = M4.perspective(fov, aspect, zNear, zFar);

        let viewMatrix = camera.getMatrix();
        var lightPos = M4.multiplyVector(viewMatrix, lightPosition);
        var lightDir = M4.multiplyVector(viewMatrix, lightDirection);
        
        bulb.draw(gl, viewMatrix, projectionMatrix, lightPosition, [light.ld[0], light.ld[1], light.ld[2], 1]);

        uniforms = { u_light: light, u_material: material_plane}; 
        uniforms.u_light.position = lightPos;
        uniforms.u_light.direction = lightDir;

        plane.draw(gl, viewMatrix, projectionMatrix, uniforms);
        
        uniforms.u_material = material;
        for(var i = 0; i < 9; i++){
            if(i < 3)
                modelViewMatrix = M4.multiply(viewMatrix, M4.translate(-i*3 + 3, -1, -6));
            else if (i < 6)
                modelViewMatrix = M4.multiply(viewMatrix, M4.translate((3-i)*3 + 3, -1, -3));
            else
                modelViewMatrix = M4.multiply(viewMatrix, M4.translate((6-i)*3 + 3, -1, 0));

            selectedFigure.draw(gl, modelViewMatrix, projectionMatrix, uniforms);       
        }
    }
    function setColor(value){
        light.ld = value;
        draw();
    }
    function setFigure(value){
        if(value == 'conejo'){
            ccLabel.setText( "<i>Bunny</i>. Modelo obtenido de <i>Stanford <br> University Computer Graphics Laboratory</i>.");
        }else
            ccLabel.setText("");
        selectedFigure = figures[value];
        draw();
    }
    function upadeteCutOff(value){
        light.cut_off = cos(value);
        draw();
    }
    function cos(degree){
        return Math.cos(degree * Math.PI/180) + 1 - 1;
    }

    function upadeteFallOff(value){
        light.fall_off = value;
        draw();
    }
    function upadeteLPos(index){
        return function(value){
            lightPosition[index] = value;
            draw();
        }
    }
    function upadeteLDir(index){
        return function(value){
            lightDirection[index] = value;
            draw();
        }
    }
    function upadeteC(index){
        return function(value){
            switch(index){
                case 0:
                    light.quadratic = value;
                    break;
                case 1:
                    light.linear = value;
                    break;
                case 2:
                    light.constant = value;
                    break;
            }
            draw();
        }
    }
}