import * as MU from "../../../modules/MathUtils.js";
import {resize, createMathBox, setElementPosition, setMathBox} from "../../../modules/HTMLUtils.js";
import WebGL from "../../../modules/WebGLUtils.js";
import M3 from "../../../modules/M3.js";
import V2 from "../../../modules/V2.js";
import Line2D from "../../../geometry/Line2D.js";
import Vector2D from "../../../geometry/Vector2D.js";
import Figure2D from "../../../geometry/Figure2D.js";
import { MouseVector, registerMouseEvents2DVec } from "../../../modules/MouseEvents.js";

/**
 * Área del paralelogramo. Producto Cruz.
 * @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;
    resize(canvas);

    let container = document.getElementById("container");
   
    const unit = 55;   
    
    //Colores
    const uColor = [0, 191, 255, 355];
    const vColor = [19, 41, 61, 255]; 
    const areaColor = [173, 216, 230, 255];
    const opaqueColor = [97, 100, 112, 200]; 
    
    const {width, height} = gl.canvas;
    
    let sPoint  = new V2(0,0);
    let xBasis = new V2(1,0);
    let yBasis = new V2(0,1);
    //Vectores
    let size = Math.floor(width/unit/6);
    let uVector  = new V2(4.5 * size, 0);
    let vVector  = new V2(size, 3.5 * size);
    let uVector2D = new Vector2D(gl, WebGL, sPoint, uVector, unit, 2, uColor);
    let vVector2D = new Vector2D(gl, WebGL, sPoint, vVector, unit, 2, vColor);
    
    const radiusRegion = 0.3;
    //Circunferencia para señalar el área para mover la flecha
    var cparams = { center: sPoint, r: radiusRegion, thickness: 0.1, numPoints: 10};
    let uCRegion = new Figure2D(gl, WebGL, 'circumference', unit, opaqueColor, cparams);
    let vCRegion = new Figure2D(gl, WebGL, 'circumference', unit, opaqueColor, cparams);
    
    //Atributos del arco
    var arcparams = { center: sPoint, sAngle : 0, eAngle: .5 * Math.PI, r: 0.7, thickness: 0.06 , numPoints: 50};

    //Lines
    let pLine = new Line2D(gl, WebGL, sPoint, yBasis, size, unit, .6);
     
    //Paralelogramo
    var rparams = { sPoint: sPoint, width: 1, height: 1};
    var paralellogram = new Figure2D(gl, WebGL, 'rect', unit, areaColor, rparams);
    rparams = { sPoint: sPoint, width: .5, height: .5};
    var recAngle = new Figure2D(gl, WebGL, 'rect', unit, opaqueColor, rparams);

    //Etiqueta vector
    let uLabel = createMathBox(container, {});
    let vLabel = createMathBox(container, {});
    let uCrossVLabel = createMathBox(container, {});
    
    //Límites de la proyección
    let projectionLimits = { l: -.10, r: .9, t: .85, b: -.15};
    //Constructor auxiliar para  el manejador de eventos con el ratón
    let uMV = new MouseVector(gl, radiusRegion, unit, uVector, projectionLimits);
    let vMV = new MouseVector(gl, radiusRegion, unit, vVector, projectionLimits);
    let mouseVectors = [ uMV, vMV];  

    gl.clearColor(0, 0, 0, 0);
    //Transparecia
    gl.enable(gl.BLEND);
    gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
    
    draw();
    window.addEventListener('resize', draw);
    registerMouseEvents2DVec(canvas, mouseVectors, draw);
    
    function draw(){
        resize(canvas);
        const {width, height} = gl.canvas;
        gl.viewport(0, 0, width, height);
        
        gl.depthMask(true);
        gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER);
        
        let projectionMatrix = M3.projection(projectionLimits.l * width, 
                                             projectionLimits.r * width, 
                                             projectionLimits.t * height, 
                                             projectionLimits.b * height);
        //Vectores
        var u = uMV.vector;
        var v = vMV.vector;
        var uAddV = u.add(v);
        var pvU = v.projection(u);

        //Cálculos para el arco del ángulo
        var uAngle = Math.acos(u.normalize().dotProduct(xBasis));
        uAngle = (u.dotProduct(yBasis) < 0) ?  2*Math.PI - uAngle : uAngle;
        var vAngle = Math.acos(v.normalize().dotProduct(xBasis));
        vAngle = (v.dotProduct(yBasis) < 0) ?  2*Math.PI - vAngle : vAngle;
        if(Math.abs(uAngle - vAngle) > Math.PI){ //Si es mayor de 180º
            if(uAngle > vAngle) //Empezamos con el ángulo mayor
                uAngle -= 2*Math.PI; 
            else
                vAngle -= 2*Math.PI; 
        }
        
        arcparams.sAngle = (uAngle < vAngle) ? uAngle : vAngle;
        arcparams.eAngle = (uAngle < vAngle) ? vAngle : uAngle;
        let arcAngle  = new Figure2D(gl, WebGL, 'arc', unit, [255, 165, 0, 255], arcparams);
        
        //Dibujamos
        var pTransformation = M3.generalMatrix(u,v);
        paralellogram.draw(gl, pTransformation, projectionMatrix);
        var signX = u.x < v.x ? -1 : 1;
        var signY = v.y < u.y ? -1 : 1;
        var recAngleTransformation = M3.multiply(M3.translate(pvU.x, pvU.y), M3.rotateR(uAngle)); 
        recAngleTransformation = M3.multiply(recAngleTransformation, M3.scale(signX,signY));
        recAngle.draw(gl, recAngleTransformation, projectionMatrix);
        arcAngle.draw(gl, M3.identity(), projectionMatrix);

        if(uMV.showRegion)
            uCRegion.draw(gl, M3.translate(u.x, u.y), projectionMatrix);
        if(vMV.showRegion)
            vCRegion.draw(gl, M3.translate(v.x, v.y), projectionMatrix);
 
        var norm = new V2(u.y, -u.x);
        norm = norm.normalize();
        var t = norm.dotProduct(v);

        pLine.draw(gl, projectionMatrix, t, pvU, norm);
        uVector2D.draw(gl, projectionMatrix, null, u);
        vVector2D.draw(gl, projectionMatrix, null, v);

        //Label u
        let labelPos = MU.getVectorLabelMidPosition(projectionMatrix, width, height, unit, u);
        setElementPosition(uLabel, labelPos);
        setMathBox(uLabel, "\\mathbf{u}");

        //Label v        
        labelPos = MU.getVectorLabelMidLPosition(projectionMatrix, width, height, unit, v);
        setElementPosition(vLabel, labelPos);
        setMathBox(vLabel, "\\mathbf{v}");
        
        //Label uxv
        var diff = { t: -35, l: -35};
        labelPos = MU.getVectorLabelPosition(uAddV, projectionMatrix, width, height, unit, diff, 0.5);
        setElementPosition(uCrossVLabel, labelPos);
        setMathBox(uCrossVLabel, "\\lVert \\mathbf{u} \\times \\mathbf{v}\\rVert");
           
    }
}