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

/**
 * Coordenadas de un punto con distintos vectores base.
 * @author Melissa Méndez Servín.
 */
window.addEventListener("load", main);

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

    let controls = document.getElementById("ui-container");
    controls.className = "bottom-bttns-box";
 
    //HTML CONTROLS
    let buttons = [ new Button(controls, upadateStep(-1), "Prev", null, true),
                    new Button(controls, reset, "Reset"),
                    new Button(controls, upadateStep(1), "Sig")];

    const unit =55;   
    var basis = [{x: new V2(1,0), y: new V2(0,1)},
                 {x: new V2(1.5, 1.5), y: new V2(-1.5, 1.5)},
                 {x: new V2(1.5,-.5), y: new V2(1.5, 1.5)},
                 {x: new V2(2,0), y: new V2(0,-2)},
                 {x: new V2(-3,0), y: new V2(0,1)}];
    
    //Color de los vectores
    const colorBasis = [19, 41, 61, 255]; 
    const colorPoint = [199, 0, 57, 255];

    let sPoint  = new V2(0,0);
        
    var grid = new Grid(gl, unit, false, basis[indexBasis]);
    let currE1Vector2D = new Vector2D(gl, WebGL, null, basis[indexBasis].x, unit, 1.5, colorBasis);
    let currE2Vector2D = new Vector2D(gl, WebGL, null, basis[indexBasis].y, unit, 1.5, colorBasis);
    //Puntos de los vectores
    var cparams = { center: sPoint, r: 0.1, numPoints: 10};
    let centerPoint = new Figure2D(gl, WebGL, 'circle', unit, colorBasis, cparams);
    //Punto
    var point = new V2(-2,-1);
    var pparams = { center: point, r: 0.1, numPoints: 10};
    let pointP = new Figure2D(gl, WebGL, 'circle', unit, colorPoint, pparams);
   
    //Etiquetas 
    let basisLabel = createMathBox(container, {top:-1, right:2});
    let e1Label = createMathBox(container, {});
    let e2Label = createMathBox(container, {});
    let pLabel = createMathBox(container, {});
    
    gl.clearColor(0, 0, 0, 0);
        
    window.addEventListener('resize', draw);
    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 limits = { l: - .5 * width, r: .5 * width, t: .5 * height, b: -.5 * height};
        
        var projectionMatrix = M3.projection(limits.l, limits.r, limits.t, limits.b);
        
        grid.draw(gl, limits, basis[indexBasis]);
        //Vectores base actuales
        var e1 = basis[indexBasis].x;
        var e2 = basis[indexBasis].y;
        setMathBox(basisLabel, "\\mathbf{e}_1 = (" +  e1.x + ", " + e1.y + ") \\quad" +  
                               "\\mathbf{e}_2 = (" +  e2.x + ", " + e2.y + ")");

        //Se dibujan vectores base 
        currE1Vector2D.draw(gl, projectionMatrix, null, e1);
        currE2Vector2D.draw(gl, projectionMatrix, null, e2);
        //Se dibuja el punto céntrico
        centerPoint.draw(gl, M3.identity(), projectionMatrix);        
        pointP.draw(gl, M3.identity(), projectionMatrix);
        //Coordenadas (aproximadas) en la ventana
        var xCoord = MU.getPixelPosition( e1, projectionMatrix, width, height, unit);
        var yCoord = MU.getPixelPosition( e2, projectionMatrix, width, height, unit);

        var offsetX = (e1.x > 0) ? -15 : -33;
        let e1LabelPosition = {top : -30 + xCoord.y, 
                             left : offsetX + xCoord.x, type: 'px'};
        setElementPosition(e1Label, e1LabelPosition);
        setMathBox(e1Label, "\\mathbf{e_1}");
        
        var offsetY = (e2.y > 0) ? -38 : -25;
        let e2LabelPosition = {top : offsetY  + yCoord.y, 
                             left : -20 + yCoord.x, type: 'px'};
        setElementPosition(e2Label, e2LabelPosition);
        setMathBox(e2Label, "\\mathbf{e_2}");
        
        //Cambio de base 
        var changeOfBasis = inverse2D([ e1.x, e1.y, e2.x, e2.y]);
        var pCoords = point.multiply2DM(changeOfBasis);
        var offsetP = { t: -15, l: -50};
        var pLabelPosition = MU.getVectorLabelPosition(point, projectionMatrix, width, height, unit, offsetP, 1.2);
        setElementPosition(pLabel, pLabelPosition);
        setMathBox(pLabel, "\\mathit{P = ( " + pCoords.x.toFixed(2) + ", " + pCoords.y.toFixed(2) + ")}");
    }
    function upadateStep(button){
        return function(){
            if (indexBasis + button < 0 || indexBasis + button >= basis.length)
                return;
            indexBasis += button;
            buttons[0].updateState(indexBasis, 1, basis.length-1);
            buttons[2].updateState(indexBasis, 0, basis.length-2);
            draw(); 
        }
    }

    function reset(){
        indexBasis = 0;
        buttons[0].updateState(indexBasis, 1, basis.length-1);
        buttons[2].updateState(indexBasis, 0, basis.length-2);
        draw();
    }
/**
 *  m = [ Ax  Bx
 *        Ay  By]  =  [ Ax, Ay, Bx, By]
 * @param {*} m 
 */
    function inverse2D(m){
        var det = m[0] * m[3] - m[1] * m[2];
        return [ m[3]/det, -m[1]/det, -m[2]/det, m[0]/det];
    }
}