import {getDisconnectedVertices, getNormalsFromIndices, getNormalsFromVertices} from "../geometry/Figure.js";

/**
 * Programa de sombreado CubeMapping.
 * @author Melissa Méndez Servín.
 */
export default class CubeMapping{
    constructor(gl, WebGL, figure, cube_map_info, draw_callback){

        var vsh = `#version 300 es
                    uniform mat4 u_PVM_matrix;
                    uniform mat4 u_VM_matrix;
                    uniform mat4 u_VMN_matrix;
                    
                    in vec4 a_position;
                    in vec3 a_normal;
                
                    out vec3 v_normal; 
                    out vec3 v_position; 

                    void main(){
                    
                        v_position = normalize((u_VM_matrix * a_position).xyz);
                        v_normal = normalize((u_VMN_matrix * vec4(a_normal, 0)).xyz);
                        gl_Position = u_PVM_matrix * a_position;

                    }`;
        var fsh = `#version 300 es
                    precision highp float;
                
                    uniform samplerCube u_cube_map;
                    uniform mat4 u_VMN_matrix;
                    uniform vec3 u_light_direction;

                    in vec3 v_position;
                    in vec3 v_normal;
                    
                    out vec4 glColor;
                
                    void main(){
                        vec3 N = normalize(v_normal);
                        vec3 V = normalize(v_position); 
                        vec3 R = reflect(V, N);
                        vec3 T = vec3(u_VMN_matrix * vec4(R, 1.0));
                        vec3 diffuse_color = texture(u_cube_map, T).rgb;
                       
                        vec3 L = normalize(u_light_direction - v_position);
                        float cos_angle = max(dot(N, L), 0.0);

                        vec3 contribution = vec3(vec3(0.5) * diffuse_color + (vec3(0.77) * diffuse_color * cos_angle));
                            
                        if(cos_angle > 0.0){
                            V = normalize(-v_position); 
                            float specular = 0.0;
                            R = reflect(-L,N);
                            float spec_angle = max(dot(R,V),0.0);
                            specular = pow(spec_angle,  76.8);
                            
                           // contribution +=  vec3(0.7) * specular;
                        }

                        glColor = vec4(contribution, 1.0);
                    }`; 

        if (WebGL.programs["CM"])
            this.program = WebGL.programs["CM"];
        else
            this.program = WebGL.createProgram(gl, vsh, fsh, "CM");
            
        this.vertices = (figure.byIndices || figure.getNormals) ?  figure.getVertices() : getDisconnectedVertices(figure.getVertices(), figure.getFaces());
        if(figure.getNormals)
            this.normals = figure.getNormals();
        else
            this.normals = (figure.byIndices) ? getNormalsFromIndices(figure.getFaces(), this.vertices) : getNormalsFromVertices(this.vertices);
        
        let attributes = {  position: { numComponents: 3, 
                                                 data: this.vertices},
                              normal: { numComponents: 3, 
                                                 data: this.normals}
                         };
        
        if(figure.byIndices){
            let vaoAndIndices = WebGL.setVAOAndAttributes(gl, this.program, attributes, figure.getFaces());
            this.vao = vaoAndIndices.vao;
            this.indexBuffer = vaoAndIndices.indexBuffer;
            this.numIndices = figure.numIndices;
        }else{
            this.vao = WebGL.setVAOAndAttributes(gl, this.program, attributes);  
            this.numElements = this.vertices.length/3;
        }
        this.setUniforms = WebGL.setUniforms(gl, this.program);
        if(cube_map_info){
            let srcTextures = [];
            cube_map_info.array.forEach(element => {
                srcTextures.push(element.url);
            });
            this.texture = WebGL.loadImages(gl, srcTextures, createTextures);
    
            function createTextures(images){
                WebGL.createCubeMap(gl, images, cube_map_info, draw_callback, config.filters);
            }
        }
        this.uniforms = { u_light_direction: [0,3,1]};
    }
}