import * as MU from "../../../modules/MathUtils.js";
import {resize, Button, MathBox} from "../../../modules/HTMLUtils.js";
import WebGL from "../../../modules/WebGLUtils.js";
import M3 from "../../../modules/M3.js";
import V2 from "../../../modules/V2.js";
import Grid from "../../../geometry/Grid.js";
import Figure2D from "../../../geometry/Figure2D.js";
import Vector2D from "../../../geometry/Vector2D.js";
import { MouseVector, registerMouseEvents2DVec } from "../../../modules/MouseEvents.js";

/**
 * Suma de dos vectores base estándar
 * @author Melissa Méndez Servín.
 */
window.addEventListener("load", main);

var step = 0;
function main(){
    document.body.style.backgroundColor = "#f3f5f5";
    var canvas = document.getElementById("gl_canvas");
    var gl = WebGL.init(canvas);
    if(!gl) return;
    
    resize(canvas);

    let controls = document.getElementById("ui-container");
    controls.className = "right-bottom-bttns-box";

    //HTML CONTROLS
    let buttons = [ new Button(controls, upadateStep(-1), "Prev", "", true),
                    new Button(controls, reset, "Reset"),
                    new Button(controls, upadateStep(1), "Sig")];

    const {width, height} = gl.canvas;
    var unit = 29;  
    var grid = new Grid(gl, unit, true);
    //Colores
    const uColor = [19, 41, 61, 255]; 
    const vColor = [255, 0, 0, 255];
    const uOpaqueColor = [80, 114, 167, 255];
    const vOpaqueColor = [250, 128, 114, 255];
    const sumColor = [46, 139, 87, 255];
    const opaqueColor = [97, 100, 112, 200]; 
    const sizeVec = 2.8;
    //Punto inicial
    let sPoint  = new V2(0,0);
    //Vector U
    let uVector  = new V2(Math.floor(.15*width/unit), Math.floor(.3*height/unit));
    let uVector2D = new Vector2D(gl, WebGL, sPoint, uVector, unit, sizeVec, uColor);
    // Vector V
    let vVector  = new V2(Math.floor(.3*width/unit), Math.floor(.1*height/unit));
    let vVector2D = new Vector2D(gl, WebGL, sPoint, vVector, unit, sizeVec, vColor);
    // Vector U+V
    let addVector = uVector.add(vVector);
    let uAddVVector2D = new Vector2D(gl, WebGL, sPoint, addVector, unit, sizeVec, sumColor);
    // Vector U PRIME
    let uPrimeVector2D = new Vector2D(gl, WebGL, vVector, uVector, unit, sizeVec, uColor);
    // Vector V PRIME
    let vPrimeVector2D = new Vector2D(gl, WebGL, uVector, vVector, unit, sizeVec, vColor);

    //Etiquetas vectores
    let uLabel = new MathBox(container, {}, "\\mathbf{u}", "math-label");
    let vLabel = new MathBox(container, {},"\\mathbf{v}", "math-label");
    let vPrimeLabel = new MathBox(container, {}, "\\mathbf{v}", "math-label");
    let uPrimeLabel = new MathBox(container, {}, "\\mathbf{u}", "math-label");
    let uAddVLabel = new MathBox(container, {},"\\mathbf{u+v}", "math-label");

    //Etiqueta valores
    let uValueLabel = new MathBox(container, { bottom: 15, left: 5});
    let vValueLabel = new MathBox(container, { bottom: 10, left: 5});
    let addValueLabel = new MathBox(container, { bottom: 5, left: 5});

    const radiusRegion = 0.45;
    //Circunferencia para señalar el área/región para mover la flecha
    var cparams = { center: sPoint, r: radiusRegion, thickness: 0.15, numPoints: 10};
    let uCRegion = new Figure2D(gl, WebGL, 'circumference', unit, opaqueColor, cparams);
    let vCRegion = new Figure2D(gl, WebGL, 'circumference', unit, opaqueColor, cparams);

    //Constructor auxiliar para  el manejador de eventos con el ratón
    let uMV = new MouseVector(gl, radiusRegion, unit, uVector);
    let vMV = new MouseVector(gl, radiusRegion, unit, vVector);
    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.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER);
        
        var projectionMatrix = M3.projection(-width/2, width/2, height/2, -height/2);
        grid.draw(gl);
        
        //Vectores
        var u = uMV.vector;
        var v = vMV.vector;
        var uAddV = u.add(v);
        //Verificamos la posición del mouse para mostrar o no la región
        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 diff = {t: 0, l:-45};
        let labelPos = MU.getVectorLabelPosition(u, projectionMatrix, width, height, unit, diff);
        uLabel.setPosition(labelPos);
        
        labelPos = MU.getVectorLabelPosition(v, projectionMatrix, width, height, unit, diff);
        vLabel.setPosition(labelPos);
       
        uPrimeLabel.hideLabel();
        vPrimeLabel.hideLabel();
        uAddVLabel.hideLabel();
        addValueLabel.setText("");

        if((step > 0 && step < 3) || step == 6){ // V PRIME
            diff = {t: -50, l:-45};
            labelPos = MU.getVectorLabelPosition(uAddV, projectionMatrix, width, height, unit, diff, .7);
            vPrimeLabel.setPosition(labelPos);
            vPrimeVector2D.draw(gl, projectionMatrix, null, v, u);
        }
        if(step > 3){ // U PRIME
            diff = {t: 0, l:-10};
            labelPos = MU.getVectorLabelPosition(uAddV, projectionMatrix, width, height, unit, diff, .7);
            uPrimeLabel.setPosition(labelPos);
            uPrimeVector2D.draw(gl, projectionMatrix, null, u, v);
        }
        if(step == 2 || step >= 5){ // U+V
            diff = {t: 0, l:-45};
            labelPos = MU.getVectorLabelPosition(uAddV, projectionMatrix, width, height, unit, diff);
            uAddVLabel.setPosition(labelPos);
            uAddVVector2D.draw(gl, projectionMatrix, null, uAddV);
            addValueLabel.setText("\\mathbf{u + v} = (" + uAddV.x.toFixed(2) + ', ' +  uAddV.y.toFixed(2) + ")");

        }
        var uCurrentColor = (step < 4) ? uColor : uOpaqueColor; 
        var vCurrentColor = (step == 0) ? vColor : vOpaqueColor; 
        uVector2D.draw(gl, projectionMatrix, uCurrentColor, u);
        vVector2D.draw(gl, projectionMatrix, vCurrentColor, v);
    
        uValueLabel.setText("\\mathbf{u} = (" + u.x.toFixed(2) + ', ' +  u.y.toFixed(2) + ")");
        vValueLabel.setText("\\mathbf{v} = (" + v.x.toFixed(2) + ', ' +  v.y.toFixed(2) + ")");
        
    }

    function upadateStep(button){
        return function(){
            if (step + button < 0 || step + button > 6)
                return;
            step += button;
            buttons[0].updateState(step, 1, 6);
            buttons[2].updateState(step, 0, 5);
            draw(); 
        }
    }
    function reset(){
        step = 0;
        buttons[0].updateState(step, 1, 6);
        buttons[2].updateState(step, 0, 5);
        draw();
    }
}