import {resize, MathBox, InputElement, scaleToFitContainer} from "../../../modules/HTMLUtils.js";
import WebGL from "../../../modules/WebGLUtils.js";
import M4 from "../../../modules/M4.js";
import Cube from "../../../geometry/Cube.js";
import Vector3D from "../../../geometry/Vector3D.js";
import SolidColor from "../../../materials/SolidColor.js";
import Diffuse from "../../../materials/Diffuse.js";
import VertexColor from "../../../materials/VertexColor.js";
import V3 from "../../../modules/V3.js";
import {TrackballCamera, registerCameraEvents} from "../../../modules/Trackballcamera.js";
import { Sphere, RectangularPrism} from "../../../geometry/Figure.js";
import GeometryPainter from "../../../geometry/GeometryPainter.js";

/** 
 * Área del paralelepípedo (usando el determinante dado por los vectores de su definición (editables)).
 * @author Melissa Méndez Servín.
 */
window.addEventListener("load", main);

var v1_vec, v2_vec, v3_vec;
function main(){
    
    var canvas = document.getElementById("gl_canvas");
    var gl = WebGL.init(canvas);
    if(!gl) return;
    let controls = document.getElementById("ui-container");
    
    let lightPosition = [2, 3, 3, 0];
    let diffuseUniforms = { u_light_position: lightPosition}; 
    
    let yellow = [255, 233, 113, 185];
    let green = [117, 204, 55, 185];
    let purple = [123, 104, 238, 185];
    let salmon = [255, 117, 101, 185];
    let blue = [135, 206, 250, 185];
    let violet = [238, 130, 238, 185];

    let cubeFigure = new Cube(1);
    cubeFigure.setColorsByFaces([yellow, green, purple, salmon, violet, blue]);
    let parallelepiped = new GeometryPainter(gl, new VertexColor(gl, WebGL, cubeFigure, true),  M4.translate(.5,.5,.5));
    
    //Plano
    let sPoint = new V3(0,0,0);
    var rect = new RectangularPrism(20,.01,20,true);
    let plane = new GeometryPainter(gl, new SolidColor(gl, WebGL, rect, [.8,.9,1,1]));    

    let v1_label = new MathBox(container, {}, "\\mathbf{v}_1");
    let v2_label = new MathBox(container, {}, "\\mathbf{v}_2");
    let v3_label = new MathBox(container, {}, "\\mathbf{v}_3");
    //Axis
    const axisColor = [.8,.8,.8,1];
    let axis = [new Vector3D(gl, WebGL, new V3(1,0,0), sPoint, .06, axisColor, lightPosition),
                new Vector3D(gl, WebGL, new V3(0,1,0), sPoint, .06, axisColor, lightPosition),
                new Vector3D(gl, WebGL, new V3(0,0,1), sPoint, .06, axisColor, lightPosition)];

    //Flechas
    let v1Arrow = new Vector3D(gl, WebGL, v1_vec, sPoint, .1, [1,.2,.3,1], lightPosition, v1_label, false);
    let v2Arrow = new Vector3D(gl, WebGL, v2_vec, sPoint, .1, [0,.7,0,1], lightPosition, v2_label, false); 
    let v3Arrow = new Vector3D(gl, WebGL, v3_vec, sPoint, .1, [0,.2,.9,1], lightPosition, v3_label, false); 
    v3Arrow.setOffsetLabelPosition(8,0);
   
    let sColor = { u_color: axisColor };
    let s = new GeometryPainter(gl, new Diffuse(gl, WebGL, new Sphere(.07, 30, 30), sColor));
    
    //Matriz
    let letA = new MathBox(controls, {top: 80, left: 30, type: 'px'}, "\\mathbf{A} = ", "katex-box katex-label");
    let det = new MathBox(controls, {top: 31, left: 286, type: 'px'}, "", "katex-box katex-label");
    let matrixA = document.getElementById("a-matrix");
    let mA = []; 
    let elems = [1,-0.5,0, 0.5,2,1, 0,0,2];
    for(var i= 0; i< 9; i++){
        var color = "";
        if(i % 3 == 0)
            color = "red";
        else if(i == 1 || i == 4 || i == 7)
            color = "green";
       
        mA.push(new InputElement(matrixA, "element input " + color, elems[i], draw));
        }
    var fov = 80;
    if(window.innerWidth < window.innerHeight)
        fov = 120;

    let zNear = .1;
    let zFar = 2000;
    let pos = M4.multiplyVector(M4.rotateY(-40), [1.2,3.5,5,1]);
    let camera = new TrackballCamera(new V3(pos[0],pos[1],pos[2]), new V3(0.1,0.1,0.1));
    camera.setZoomConfig(10,2);
    resize(canvas);

    window.addEventListener('resize', draw);
    registerCameraEvents(camera, canvas, draw);
    const position = {x:0, y:0};
 
    draw();

    function draw(){
        resize(canvas);
        scaleToFitContainer(controls, position);
        
        const {width, height} = gl.canvas;
        gl.viewport(0, 0, width, height);
        
        gl.clearColor(0, 0, 0, 0);
        gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
        gl.enable(gl.DEPTH_TEST);
        gl.disable(gl.BLEND);
        gl.disable(gl.CULL_FACE);
        //gl.depthMask(true);

        let aspect = width/height;
        var projectionMatrix = M4.perspective(90, aspect, zNear, zFar);
        var viewMatrix = camera.getMatrix();
        
        var lightPos = M4.multiplyVector(viewMatrix, lightPosition);
        diffuseUniforms.u_light_position = lightPos;
        
        for(var i=0; i< 3; i++)
            axis[i].draw(gl, viewMatrix, projectionMatrix, lightPos);

        v1_vec = new V3(mA[0].getNum(), mA[3].getNum(), mA[6].getNum());
        v2_vec = new V3(mA[1].getNum(), mA[4].getNum(), mA[7].getNum());
        v3_vec = new V3(mA[2].getNum(), mA[5].getNum(), mA[8].getNum());
        
        v1Arrow.draw(gl, viewMatrix, projectionMatrix, lightPos, v1_vec);
        v2Arrow.draw(gl, viewMatrix, projectionMatrix, lightPos, v2_vec);
        v3Arrow.draw(gl, viewMatrix, projectionMatrix, lightPos, v3_vec);
        det.setText(getDeterminant());

        let sVM = M4.multiply(viewMatrix, M4.translate(sPoint.x, sPoint.y, sPoint.z));
        plane.draw(gl, viewMatrix, projectionMatrix);
        s.draw(gl, sVM, projectionMatrix, diffuseUniforms);     
        
        let detM = M4.basisMatrix(v1_vec, v2_vec, v3_vec);
        var modelViewMatrixP = M4.multiply(viewMatrix, detM);
       
        //Transparecia
        gl.enable(gl.CULL_FACE);
        gl.enable(gl.BLEND);
        gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
        //gl.depthMask(false);
        gl.cullFace(gl.FRONT);
        parallelepiped.draw(gl, modelViewMatrixP, projectionMatrix);
        gl.cullFace(gl.BACK);
        parallelepiped.draw(gl, modelViewMatrixP, projectionMatrix);

        //matrix.setText(getMatrix());
        //det.setText(getDeterminant())
    }
}
function getDeterminant(){
    let det11 = v1_vec.x * ((v2_vec.y * v3_vec.z) - (v3_vec.y * v2_vec.z));
    let det12 = -1 * v2_vec.x * ((v1_vec.y * v3_vec.z) - (v3_vec.y * v1_vec.z));
    let det13 = v3_vec.x * ((v1_vec.y * v2_vec.z) - (v2_vec.y * v1_vec.z));
    return "\\text{det}(\\mathbf{A}) = " + (det11 + det12 + det13);
}
function getMatrix(){
    return "\\mathbf{A} = \\begin{bmatrix}" +
            "\\color{#FF0000}" + v1_vec.x + "&" + "\\color{#008000}" + v2_vec.x + "&" + "\\color{#4169E1}" + v3_vec.x + "\\kern{.7em}" + "\\\\" +
            "\\color{#FF0000}" + v1_vec.y + "&" + "\\color{#008000}" + v2_vec.y + "&" + "\\color{#4169E1}" + v3_vec.y + "\\kern{.7em}" + "\\\\" +
            "\\color{#FF0000}" + v1_vec.z + "&" + "\\color{#008000}" + v2_vec.z + "&" + "\\color{#4169E1}" + v3_vec.z + "\\kern{.7em}" +
            "\\end{bmatrix}";
}