import framebuffer from '../framebuffer.js';
import sampler2D from '../sampler2D.js';
import {math, vector3, matrix4} from '../math.js';

class deferred {
	
	constructor(  ) {
		this.realtime = true;
		this.render_type = "deferred";
	}
	
	setViewport( viewport ){
		
		this.viewport = viewport;
		this.gl = viewport.gl;
	}
	
	prepare() {
		
		// Framebuffer
		this.framebuffer = new framebuffer();
		this.framebuffer.setViewport( this.viewport );
		
		this.framebuffer.width = this.viewport.width;
		this.framebuffer.height = this.viewport.height;
		
		
		// Samplers
		this.diffuseSampler = new sampler2D();
		this.diffuseSampler.type = this.gl.FLOAT;
		this.diffuseSampler.internalFormat = this.gl.RGBA32F;

		this.normalSampler = new sampler2D();
		this.normalSampler.type = this.gl.FLOAT;
		this.normalSampler.internalFormat = this.gl.RGBA32F;
		
		this.infoSampler = new sampler2D();
		this.infoSampler.type = this.gl.FLOAT;
		this.infoSampler.internalFormat = this.gl.RGBA32F;


		this.tangentSampler = new sampler2D();
		this.tangentSampler.type = this.gl.FLOAT;
		this.tangentSampler.internalFormat = this.gl.RGBA32F;
		
		// Sampler
		var materialSampler = new sampler2D();

		this.framebuffer.addSampler(this.diffuseSampler);
		this.framebuffer.addSampler(this.normalSampler);
		this.framebuffer.addSampler(this.infoSampler);

		
		this.framebuffer.create();
		
	}
	
	
	render() {
		
		var camera = this.viewport.mainCamera;
		var viewProjection = camera.worldViewProjection;
		
		var mode = 0;
		
		this.gl.enableVertexAttribArray(0);

		this.gl.enableVertexAttribArray(1);

		this.gl.enableVertexAttribArray(2);

		//this.gl.enableVertexAttribArray(3);
		//this.gl.enableVertexAttribArray(4);
		
		if(this.renderToViewport)
			this.gl.bindFramebuffer( this.gl.FRAMEBUFFER, null );
		else
			this.gl.bindFramebuffer( this.gl.FRAMEBUFFER, this.framebuffer.glFramebuffer );

		if(mode == 1) {
			var sampler = this.framebuffer.samplers[0];
			
			var texture = sampler.cubeTexture;
			
			this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, this.framebuffer.framebuffers[3]);
			this.gl.framebufferRenderbuffer(this.gl.FRAMEBUFFER, this.gl.DEPTH_ATTACHMENT, this.gl.RENDERBUFFER, this.framebuffer.renderbuffers[3]);
			
			this.gl.texImage2D(face, 0, this.gl.RGBA, 1024, 1024, 0, this.gl.RGBA, this.gl.FLOAT, null);
			this.gl.framebufferTexture2D(this.gl.FRAMEBUFFER, this.gl.COLOR_ATTACHMENT0, face, texture, 0);
		}
		
		
		this.gl.clear(this.gl.COLOR_BUFFER_BIT | this.gl.DEPTH_BUFFER_BIT);
		this.gl.viewport(0, 0, this.viewport.width, this.viewport.height);

		this.gl.clearColor( 0, 0, 0, 1 );
		this.gl.enable(this.gl.DEPTH_TEST);
		this.gl.enable(this.gl.CULL_FACE);
		
		var scene = this.viewport.scene;
		var entitys = scene.getEntitys();
		
		for(var e = 0;e<entitys.length;e++) {

			var entity = entitys[e];
			
			this.gl.disableVertexAttribArray(3);
			this.gl.disableVertexAttribArray(4);
			
			if(entity.type == "Actor") {
			
				var mesh = entity.mesh;
				var material = mesh.material;

				var shader   = mesh.material.shader;
				
				shader.update( this.viewport );
				
				if(material.alpha == 1.0) {
					
					
					
					if(this.render_type == "deferred")
						shader.setUniform("render_type", 1);
					else
						shader.setUniform("render_type", 0);
		
					var world = entity.getUpdatedWorldMatrix();

					shader.setUniform("viewProjection", matrix4.mul(world, viewProjection) );
					shader.setUniform("world", world );
					//shader.setUniform("mode", mode );
					shader.setUniform("cameraPosition", this.viewport.mainCamera.eye );
					shader.setUniform("worldInverseTranspose", world   );
					
			
					
					if(material.displacementMaps.length > 0) 
						shader.setUniform("view",  this.viewport.mainCamera.view );
					

							
					
					// note: needs a smooting out mesh->material->shader update cycle only at startup right before render loop
					mesh.setViewport(this.viewport );
					mesh.createBuffers( );
					
					material.setViewport( this.viewport );
					material.updateShader(  );
					
					
					shader.update( this.viewport );

					
					var attribute = shader.getAttributeByName('position');
					this.gl.bindBuffer(this.gl.ARRAY_BUFFER, mesh.vertexPositionBuffer);
					this.gl.vertexAttribPointer(attribute, 3, this.gl.FLOAT, false, 0, 0);

					
					var attribute = shader.getAttributeByName('normal');
					this.gl.bindBuffer(this.gl.ARRAY_BUFFER, mesh.vertexNormalBuffer);
					this.gl.vertexAttribPointer(attribute, 3, this.gl.FLOAT, false, 0, 0);


					var attribute = shader.getAttributeByName('textcoord');
					
					this.gl.bindBuffer(this.gl.ARRAY_BUFFER, mesh.textureCoordBuffer);
					this.gl.vertexAttribPointer(attribute, 2, this.gl.FLOAT, false, 0, 0);



					if(material.normals.length > 0) {
						
						if(mesh.tangentBuffer) {

							this.gl.enableVertexAttribArray(3);

							this.gl.enableVertexAttribArray(4);
							
							var attribute = shader.getAttributeByName('tangent');
							this.gl.bindBuffer(this.gl.ARRAY_BUFFER, mesh.tangentBuffer);
							this.gl.vertexAttribPointer(attribute, 3, this.gl.FLOAT, false, 0, 0);
							
							
							var attribute = shader.getAttributeByName('bitangent');
							this.gl.bindBuffer(this.gl.ARRAY_BUFFER, mesh.binormalBuffer);
							this.gl.vertexAttribPointer(attribute, 3, this.gl.FLOAT, false, 0, 0);
							
						}
					}
					

					
					var texureID = 0;
					/*
					if( material.textures.length > 0 ) {
					
						var textureSampler = material.textures[0];
						var texture = textureSampler.getTexture();
						var textureUniform = shader.getUniformByName('diffuseSampler');
						
						this.gl.activeTexture( this.gl.TEXTURE0  );
						this.gl.bindTexture( this.gl.TEXTURE_2D, texture.glTexture );
						this.gl.uniform1i(textureUniform, 0);
						
						
					} else {
						//shader.setUniform("diffuseColor", material.diffuseColor);
					}
					
					if(material.normals.length > 0) {
						
						var textureSampler = material.normals[0];
						var texture = textureSampler.getTexture();
						var textureUniform = shader.getUniformByName('normalSampler');
						
						this.gl.activeTexture( this.gl.TEXTURE0 + 1);
						this.gl.bindTexture( this.gl.TEXTURE_2D, texture.glTexture );
						this.gl.uniform1i(textureUniform, 1);
						

						
						
					}
					
					if(material.roughnessMaps.length > 0) {
						
						var textureSampler = material.roughnessMaps[0];
						var texture = textureSampler.getTexture();
						if(texture) {
							//console.log("texturetexture", texture);
							var textureUniform = shader.getUniformByName('roughnessSampler');
							
							this.gl.activeTexture( this.gl.TEXTURE0 + 2);
							this.gl.bindTexture( this.gl.TEXTURE_2D, texture.glTexture );
							this.gl.uniform1i(textureUniform, 2);
						}
					}
					
					
					if(material.displacementMaps.length > 0) {
						
						var textureSampler = material.displacementMaps[0];
						var texture = textureSampler.getTexture();
						var textureUniform = shader.getUniformByName('heightSampler');
						
						this.gl.activeTexture( this.gl.TEXTURE0 + 3);
						this.gl.bindTexture( this.gl.TEXTURE_2D, texture.glTexture );
						this.gl.uniform1i(textureUniform, 3);
						
					}
					*/

					this.gl.bindBuffer( this.gl.ELEMENT_ARRAY_BUFFER, mesh.vertexIndexBuffer);
					this.gl.drawElements( mesh.draw_type, mesh.vertexIndexBuffer.numItems, this.gl.UNSIGNED_INT, 0 );  
					


				}
			}
		}
		
		this.gl.disable(this.gl.DEPTH_TEST);
		
		this.gl.disableVertexAttribArray(0);
		this.gl.disableVertexAttribArray(1);
		this.gl.disableVertexAttribArray(2);
		this.gl.disableVertexAttribArray(3);
		this.gl.disableVertexAttribArray(4);
	}
}

export {deferred as default};