"use strict";

import {Slider, resize} from "../../modules/HTMLUtils.js";
import WebGL from "../../modules/WebGLUtils.js";
import M4 from "../../modules/M4.js";
import VertexColor from "../../materials/VertexColor.js";
import SolidColor from "../../materials/SolidColor.js";
import { Cone, Plane, Sphere } from "../../geometry/Figure.js";
import { lerp } from "../../modules/MathUtils.js";
import GeometryPainter from "../../geometry/GeometryPainter.js";
import {TrackballCamera, registerCameraEvents} from "../../modules/Trackballcamera.js";
import V3 from "../../modules/V3.js";

/**
 * Modelo de color HSV.
 * @author Melissa Méndez Servín.
 */
window.addEventListener("load", main);

let hsv = [0,1,1];
function main(){
    var canvas = document.getElementById("gl_canvas");
    var gl = WebGL.init(canvas);
    if(!gl) return;
    
    let hexagonFigure = new Cone(1, 2, 60, true, true);
    let planeFigure = new Plane(1.25,1.25, true);
    let sphereFigure = new Sphere(0.05, 10, 10, true);
    let uniformColor = { u_color: [1,1,1,1]};
    let baseUniform = {u_color : [0,0,0,1]};

    let mainHexagonColors = [ [1, 0, 0, 1],
                              [1, 1, 0, 1],
                              [0, 1, 0, 1],
                              [0, 1, 1, 1],
                              [0, 0, 1, 1],
                              [1, 0, 1, 1]];

    let hexagonColors = [];
    let c1, c2, r, g, b, t;
    for(var i= 0; i < 6; i++){//Recorre cada color
        for(var j = 0; j<10; j++){//Interpola cada color
            c1 = mainHexagonColors[i];
            c2 = mainHexagonColors[(i+1)%6];
            t = j * 1/10;
            r = c1[0]*(1-t) + c2[0]*t;
            g = c1[1]*(1-t) + c2[1]*t;
            b = c1[2]*(1-t) + c2[2]*t;
            hexagonColors.push(r, g, b, 1,);
        }
    }
    hexagonColors.push( 1, 1, 1, 1,//color blanc
                        0, 0, 0, 1);//color negro
    hexagonFigure.colors = hexagonColors; 
    let center = new V3(-.1,-.3,0);
    let translation = M4.translate(center.x, center.y, center.z);
    let hTransform =  M4.multiply(translation, M4.rotateY(-90));
    let hexagon = new GeometryPainter(gl, new VertexColor(gl, WebGL, hexagonFigure), hTransform);
    let planeUniforms = {};
    let plane = new GeometryPainter(gl, new SolidColor(gl, WebGL, planeFigure), M4.translate(0,0,-1));
    let colorTest = new GeometryPainter(gl, new SolidColor(gl, WebGL, sphereFigure), translation);
    let baseTest = new GeometryPainter(gl, new SolidColor(gl, WebGL, sphereFigure,[0,0,0,1]), M4.multiply(translation, M4.scale(1.13,1.13,1.13)));
    let coneTip = new V3(0,-1,0);
    //HTML CONTROLS
    let controls = document.getElementById("ui-container");
    controls.className = "right-box game";
    
    let colors = [ "#778899"];
    let sliders = [ new Slider(controls, "H", 0 ,360, updateHSV(0), hsv[0], 1, colors, "º"),
                    new Slider(controls, "S", 0, 1, updateHSV(1), hsv[1], 0.01, colors),
                    new Slider(controls, "V", 0, 1, updateHSV(2), hsv[2], 0.01, colors)
                  ];
    for(var i = 0; i < 3; i++)
        sliders[i].setStyle("game-slider", "game-value");

    var fov = 65;
    let zNear = .1;
    let zFar = 2000;
    let camera = new TrackballCamera(
        new V3(0,1.3,2.8), 
        new V3(0,0,0), 
        new V3(0,1,0)
    );
    camera.setZoomConfig(5,2.2);
    
    resize(canvas);
    
    gl.enable(gl.DEPTH_TEST);
    gl.enable(gl.CULL_FACE);
    gl.enable(gl.SCISSOR_TEST);
    
    gl.clearColor(0, 0, 0, 0);

    window.addEventListener('resize', draw);
    registerCameraEvents(camera, canvas, draw);
    
    draw();

    function draw(){
        resize(canvas);
        var {width, height} = gl.canvas;
        const smallWidth = 100;
        const smallHeight = 80;
        
        //dibuja viewport grande
        gl.scissor(0, 0, width-smallWidth, height);
        gl.viewport(0, 0, width-smallWidth, height);
        gl.clearColor(0, 0, 0, 0);
        gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
            
        let aspect = (width-smallWidth)/height;
        var projectionMatrix = M4.perspective(fov, aspect, zNear, zFar);
        let viewMatrix = camera.getMatrix();
        let rgb = hsvToRGB(hsv[0], hsv[1], hsv[2]);
        
        gl.cullFace(gl.BACK);
        hexagon.draw(gl, viewMatrix, projectionMatrix);  
           
        let rotation = M4.rotateY(-hsv[0]);
        var radius = hsv[1] * Math.cos(-hsv[0]*2*Math.PI);
        var testTransformation = M4.multiply(rotation, M4.translate(0,1,radius));
        let upperEnd = M4.multiplyVector(testTransformation, [0,0,0,1]);
        let testPos = lerp(coneTip, new V3(upperEnd[0], upperEnd[1], upperEnd[2]), hsv[2]);
        testTransformation = M4.multiply(viewMatrix, M4.translate(testPos.x, testPos.y, testPos.z));
        let lightness = rgbLightness(rgb[0], rgb[1], rgb[2]);
        gl.cullFace(gl.FRONT);
        baseUniform.u_color = [lightness, lightness, lightness, 1];
        baseTest.draw(gl, testTransformation, projectionMatrix, baseUniform);
        gl.cullFace(gl.BACK);
        uniformColor.u_color = rgb;
        colorTest.draw(gl, testTransformation, projectionMatrix, uniformColor);
        
        //viewport pequeño (color)
        gl.viewport(width-1.4*smallWidth, height-2.3*smallHeight, smallWidth, smallHeight);
        gl.scissor(width-1.4*smallWidth, height-2.3*smallHeight, smallWidth, smallHeight);
        gl.clearColor(0, 0, 0, 1);
        gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
        
        planeUniforms.u_color = rgb;
        plane.draw(gl, M4.scale(aspect,1,1), projectionMatrix, planeUniforms);
    }

    function updateHSV(index){
        return function(value){
            hsv[index] = value;
            draw();
        };
    }
    function hsvToRGB(hue, saturation, value){
        if(hue == undefined) return [0,0,0,1];
        let h = hue/60;
        let c = saturation * value;
        let x = c * (1- Math.abs(h%2-1));
        let m = value - c;
        let rgb;
        if(h >= 0 && h <= 1)
            rgb = [c,x,0];
        if(h > 1 && h <= 2)
            rgb = [x,c,0];
        if(h > 2 && h <= 3)
            rgb = [0,c,x];
        if(h > 3 && h <= 4)
            rgb = [0,x,c];
        if(h > 4 && h <= 5)
            rgb = [x,0,c];
        if(h > 5 && h <= 6)
            rgb = [c,0,x];
        rgb = [rgb[0] + m, rgb[1] + m, rgb[2] + m, 1];
        return rgb;
    }
    function rgbLightness(r,g,b){
        let c_max = Math.max(r,g,b);
        let c_min = Math.max(r,g,b);
        let lightness = 1-((c_max + c_min)/2) + .2;
        return (lightness > 1) ? 1 : lightness;
    }
}