import * as MU from "../../../modules/MathUtils.js";
import * as Utils 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";

/**
 * Proyección Ortogonal de un vector sobre otro.
 * @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 container = document.getElementById("container");
    Utils.resize(canvas);
   
    const unit = 55;   
    
    //Colores
    const uColor = [46, 139, 87, 255];
    const vColor = [19, 41, 61, 255]; 
    const wColor = [121, 203, 26, 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 = 2.7 * Math.floor(width/unit/7);
    let uVector  = new V2(size-.6, size+.6);
    let vVector  = new V2(2 * size, 0);
    let u = new Vector2D(gl, WebGL, sPoint, uVector, unit, 2, uColor);
    let v = new Vector2D(gl, WebGL, sPoint, vVector, unit, 2, vColor);
    let w = new Vector2D(gl, WebGL, sPoint, vVector, unit, 1.7, wColor);
    
    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);
     
    //Etiqueta vector
    let uLabel = Utils.createMathBox(container, {});
    let vLabel = Utils.createMathBox(container, {});
    let wLabel = Utils.createMathBox(container, {});
    
    //Límites de la proyección
    let projectionLimits = { l: -.18, r: .82, t: .78, b: -.22};
    //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(){
        Utils.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);
        
        //Cálculos para el vector de proyección
        var pvU = uMV.vector.projection(vMV.vector);

        //Cálculos para el arco del ángulo
        var uAngle = Math.acos(uMV.vector.normalize().dotProduct(xBasis));
        uAngle = (uMV.vector.dotProduct(yBasis) < 0) ? 2*Math.PI - uAngle : uAngle;
        var vAngle = Math.acos(vMV.vector.normalize().dotProduct(xBasis));
        vAngle = (vMV.vector.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
        arcAngle.draw(gl, M3.identity(), projectionMatrix);
     
        if(uMV.showRegion)
            uCRegion.draw(gl, M3.translate(uMV.vector.x, uMV.vector.y), projectionMatrix);
        if(vMV.showRegion)
            vCRegion.draw(gl, M3.translate(vMV.vector.x, vMV.vector.y), projectionMatrix);
 
        var norm = new V2(vMV.vector.y, -vMV.vector.x);
        norm = norm.normalize();
        var t = norm.dotProduct(uMV.vector);
        pLine.draw(gl, projectionMatrix, t, pvU, norm);
        u.draw(gl, projectionMatrix, null, uMV.vector);
        v.draw(gl, projectionMatrix, null, vMV.vector);
        w.draw(gl, projectionMatrix, null, pvU);     
        
        //Label u
        let labelPos = MU.getVectorLabelMidLPosition(projectionMatrix, width, height, unit, uMV.vector);
        Utils.setElementPosition(uLabel, labelPos);
        Utils.setMathBox(uLabel, "\\mathbf{u}");

        //Label v        
        labelPos = MU.getVectorLabelMidPosition(projectionMatrix, width, height, unit, vMV.vector);
        Utils.setElementPosition(vLabel, labelPos);
        Utils.setMathBox(vLabel, "\\mathbf{v}");
        
        //Label W
        labelPos = MU.getVectorLabelMidPosition(projectionMatrix, width, height, unit, pvU);
        Utils.setElementPosition(wLabel, labelPos);
        Utils.setMathBox(wLabel, "\\mathbf{w}");
           
    }
}