import * as MU from "../../../modules/MathUtils.js";
import {resize, createMathBox, setElementPosition} 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";

/**
 * Vectores base 2D.
 * @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");
    resize(canvas);
   
    const unit = 55;   
    
    //Colores
    const basisColor = [19, 41, 61, 255]; 
    const opaqueColor = [97, 100, 112, 200]; 
    const vecColor = [122, 111, 140, 255];
    const lineColor = [154, 146, 167, 255];
    const dotColor = [100, 100, 100, 255];

    const {width, height} = gl.canvas;
    
    let sPoint  = new V2(0,0);
    //Vectores
    let size = 2.5;
    let e1Vector  = new V2(size, 0);
    let e2Vector  = new V2(-.3 * size, .8* size);
    let vector = new V2(2, 2);
    let e1Vector2D = new Vector2D(gl, WebGL, sPoint, e1Vector, unit, 2, basisColor);
    let e2Vector2D = new Vector2D(gl, WebGL, sPoint, e2Vector, unit, 2, basisColor);
    let vVector2D = new Vector2D(gl, WebGL, sPoint, vector, unit, 1.7, vecColor);
    
    //Puntos 
    var eparams = { center: sPoint, r: 0.1, numPoints: 10};
    let ePoint = new Figure2D(gl, WebGL, 'circle', unit, basisColor, eparams);
    var xyparams = { center: sPoint, r: 0.07, numPoints: 10};
    let xPoint = new Figure2D(gl, WebGL, 'circle', unit, dotColor, xyparams);
    let yPoint = new Figure2D(gl, WebGL, 'circle', unit, dotColor, xyparams);
    
    const radiusRegion = 0.3;
    //Circunferencia para señalar el área/región para mover la flecha
    var cparams = { center: sPoint, r: radiusRegion, thickness: 0.1, numPoints: 10};
    let e1CRegion = new Figure2D(gl, WebGL, 'circumference', unit, opaqueColor, cparams);
    let e2CRegion = new Figure2D(gl, WebGL, 'circumference', unit, opaqueColor, cparams);
    let vCRegion = new Figure2D(gl, WebGL, 'circumference', unit, opaqueColor, cparams);
    
    //Lines
    let e1Line = new Line2D(gl, WebGL, new V2(-size, 0), e1Vector, width, unit, .6);
    let e2Line = new Line2D(gl, WebGL, new V2(0, -size), e2Vector, width, unit, .6);
    let xLine = new Line2D(gl, WebGL, new V2(-size, 0), e1Vector, width, unit, .6, lineColor);
    let yLine = new Line2D(gl, WebGL, new V2(0, -size), e2Vector, width, unit, .6, lineColor);
    
    //Etiqueta vector
    let e1Label = createMathBox(container, {}, "\\mathbf{e_1}");
    let e2Label = createMathBox(container, {}, "\\mathbf{e_2}");
    let vLabel = createMathBox(container, {}, "\\mathbf{v}");
    let pXLabel = createMathBox(container, {}, "\\mathit{P_x}");
    let pYLabel = createMathBox(container, {}, "\\mathit{P_y}");
    let OLabel = createMathBox(container, {}, "\\mathbf{O}");
    
    //Límites de la proyección
    let projectionLimits = { l: -.25, r: .75, t: .8, b: -.2};
    //Constructor auxiliar para  el manejador de eventos con el ratón
    let e1MV = new MouseVector(gl, radiusRegion, unit, e1Vector, projectionLimits);
    let e2MV = new MouseVector(gl, radiusRegion, unit, e2Vector, projectionLimits);
    let vMV = new MouseVector(gl, radiusRegion, unit, vector, projectionLimits);
    let mouseVectors = [ e1MV, e2MV, 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); 
        
        setElementPosition(OLabel, MU.getVectorLabelPosition(sPoint, projectionMatrix, width, height, unit, {t: -10, l:-30}));
        //Vectores
        var e1 = e1MV.vector;
        var e2 = e2MV.vector;
        var v = vMV.vector;
        
        //Verificamos la posición del mouse para mostrar o no la región
        if(e1MV.showRegion)
            e1CRegion.draw(gl, M3.translate(e1.x, e1.y), projectionMatrix);
        if(e2MV.showRegion)
            e2CRegion.draw(gl, M3.translate(e2.x, e2.y), projectionMatrix);
        if(vMV.showRegion)
            vCRegion.draw(gl, M3.translate(v.x, v.y), projectionMatrix);
        
        //Dibujamos
        //Líneas guía
        var e1SPoint = e1.scale(-size*2);
        var e2SPoint = e2.scale(-size*2);
        e1Line.draw(gl, projectionMatrix, width, e1SPoint, e1);
        e2Line.draw(gl, projectionMatrix, width, e2SPoint, e2);
        
        var intersecPointX = MU.lineIntersection(sPoint, e1, v, e2);
        var intersecPointY = MU.lineIntersection(sPoint, e2, v, e1.scale(-1));
        var signXV = (v.y < intersecPointX.y || e2.y < 0) ? -1 : 1;
        var signYV = (v.x < intersecPointY.x || e1.x < 0) ? -1 : 1;
        var distXV = signXV * intersecPointX.distance(v);
        var distYV = signYV * intersecPointY.distance(v);
        xLine.draw(gl, projectionMatrix, -distXV, v, e2);
        yLine.draw(gl, projectionMatrix, -distYV, v, e1);
        //Vectores
        e1Vector2D.draw(gl, projectionMatrix, null, e1);
        e2Vector2D.draw(gl, projectionMatrix, null, e2);
        vVector2D.draw(gl, projectionMatrix, null, v);       
        ePoint.draw(gl, M3.identity(), projectionMatrix); 
        
        xPoint.draw(gl, M3.translate(intersecPointX.x, intersecPointX.y), projectionMatrix); 
        yPoint.draw(gl, M3.translate(intersecPointY.x, intersecPointY.y), projectionMatrix); 
        //Label e1  
        var diff = {t: 0, l:-45};
        let labelPos = MU.getVectorLabelPosition(e1, projectionMatrix, width, height, unit, diff);
        setElementPosition(e1Label, labelPos);
        
        //Label e2        
        labelPos = MU.getVectorLabelPosition(e2, projectionMatrix, width, height, unit, diff);
        setElementPosition(e2Label, labelPos);
        
        //Label v
        diff = {t: 0, l: -15};
        labelPos = MU.getVectorLabelPosition(v, projectionMatrix, width, height, unit, diff);
        setElementPosition(vLabel, labelPos);
        //Label px
        diff = {t: -50, l: -25};
        labelPos = MU.getVectorLabelPosition(intersecPointX, projectionMatrix, width, height, unit, diff, 1);
        setElementPosition(pXLabel, labelPos);
        //Label py
        labelPos = MU.getVectorLabelPosition(intersecPointY, projectionMatrix, width, height, unit, diff, 1);
        setElementPosition(pYLabel, labelPos);
    }
}