import framebuffer from '../framebuffer.js';
import sampler2D from '../sampler2D.js';
import {math, vector3, matrix4} from '../math.js';
import samplerCube from '../samplerCube.js';
import shader from '../shader.js';
import material from '../material.js';
import entity from '../entity.js';


class depth {
	
	constructor(  ) {
		this.lightPosition = [0, 4, 0.01];
		this.degrees = 130;
	}
	
	setViewport( viewport ){
		
		this.viewport = viewport;
		this.gl = viewport.gl;
	}
	
	prepare() {
		
		this.near = .635;
		this.far = 400;
	//	
		
		this.width = this.viewport.width;
		this.height = this.viewport.height;
		
		this.targetSampler = new sampler2D();
		this.targetSampler.type = this.gl.FLOAT;
		
		this.framebuffer = new framebuffer();
		this.framebuffer.setViewport( this.viewport );
		this.framebuffer.width = this.width;
		this.framebuffer.height = this.height;
		
		this.framebuffer.addSampler( this.targetSampler );
		this.framebuffer.create();
		
		//depth shader
		this.depthShader = new shader();
		this.depthShader.definePragma("VARIANCE", (this.shadowType == "VARIANCE") ? 1 : 0 );
		this.depthShader.createFromFile("shaders/depth.shader");
		this.depthShader.setUniform("far", this.far );
		this.depthShader.setUniform("near", this.near );
		
		
		var shadowCamera = this.createShadowCam( this.lightPosition , [0, -1, 0], [0, 1, 0]  );
		
		this.shadowCameras = [];
		this.shadowCameras.push( shadowCamera );
		
		// Material
		var groundMaterial = new material();

		// Properties
		groundMaterial.diffuseColor = [179/256,199/256,217/256];
		groundMaterial.alpha = 1;
		groundMaterial.reflection = 0.2;
		groundMaterial.roughness = 0.2;
		groundMaterial.metalic = 0.2;
		groundMaterial.uvMultiplier = 6;

		
		
		if(this.showFrustum) {
			// Cube mesh
			//var shadowCamera = this.viewport.system.createShadowCam( [0, 10, 1], [0, -1, 0], [0, 1, 0] )
			var frustumMesh = this.viewport.linePrimitives.drawFrustum( shadowCamera.projection, shadowCamera.view );

			frustumMesh.addMaterial(groundMaterial);

			// Cube Entity
			var cubeEntity = new entity( );
			cubeEntity.addMesh( frustumMesh );
			cubeEntity.name = "wireframe cube";
			cubeEntity.transform.position = [0, 0, 0];
			cubeEntity.transform.update();
			
			this.viewport.scene.addEntity( cubeEntity );
		
		}
		
		
		

	}
	
		createShadowCam( eye, target, up ) {
		var width = 2048;
		var height = 2048;
		

		var shadowCamera = {};

		shadowCamera.view 			= matrix4.lookAt( eye, target, up );
		//if(this.lightType == "skyLight")
		//	shadowCamera.projection 	= matrix4.orthographic(-10, 10, -10, 10, this.near, this.far);
		
		//if(this.lightType == "pointLight")
			shadowCamera.projection 	= matrix4.perspective(math.degToRad(this.degrees), width / height, this.near, this.far);
		
		
		console.log(shadowCamera.projection);
		this.composition    = 		matrix4.composition(shadowCamera.view, shadowCamera.projection);
		this.viewProjection = 		matrix4.mul(shadowCamera.view, shadowCamera.projection);
		shadowCamera.far 	= 		this.far;
		
		
		
		//if( face ) {
		//	shadowCamera.framebuffer.target 	= this.gl.TEXTURE_CUBE_MAP;
		//	shadowCamera.framebuffer.face 		= face;
		//	shadowCamera.framebuffer.attachment = this.gl.DEPTH_ATTACHMENT;
			
		//} else {
			
			//shadowCamera.framebuffer.target = this.gl.TEXTURE_2D;
			
		this.targetSampler = new sampler2D();
		//this.targetSampler.type = this.gl.FLOAT;
		//this.targetSampler.filter = this.gl.LINEAR;
		//this.targetSampler.internalFormat = this.gl.RGBA32F;
		
		this.targetSampler.internalformat = this.gl.RGB;
		this.targetSampler.format 		 = this.gl.RGB;
		this.targetSampler.type 		 = this.gl.FLOAT;
		
		this.framebuffer = new framebuffer();
		this.framebuffer.setViewport( this.viewport );
		this.framebuffer.width = this.width;
		this.framebuffer.height = this.height;

		
		this.framebuffer.addSampler( this.targetSampler );
		this.framebuffer.create();
		
		
		/*
		
		this.ambientOcclusionFramebuffer = new framebuffer();
		this.ambientOcclusionFramebuffer.width = this.width;
		this.ambientOcclusionFramebuffer.height = this.height;
		
		var ambientOcclusionSampler = new sampler2D();
		ambientOcclusionSampler.type = this.gl.FLOAT;
		
		this.ambientOcclusionFramebuffer.addSampler( ambientOcclusionSampler );
		this.ambientOcclusionFramebuffer.create();
		*/
		//shadowCamera.filter = this.gl.LINEAR;
		
		return shadowCamera;
	}
	
	getCamera(){
		return this.shadowCameras[0];
		
	}
	
	render() {
		console.log("render depth");
	//this.gl.enableVertexAttribArray(0);
		this.gl.disableVertexAttribArray(1);
		this.gl.disableVertexAttribArray(2);
		this.gl.disableVertexAttribArray(3);
		this.gl.disableVertexAttribArray(4);
		this.gl.disableVertexAttribArray(5);
		//this.gl.disableVertexAttribArray(6);
		//this.gl.disableVertexAttribArray(7);
			
		var shader = this.depthShader;
		
		//var shadowCamera = this.shadowCameras[0];
			
		for(var c = 0; c<this.shadowCameras.length; c++) {
			var shadowCamera = this.shadowCameras[c];
			//var framebuffer = shadowCamera.framebuffer.glFramebuffer;

			//render shadow
			
			if(this.renderToViewport)
				this.gl.bindFramebuffer( this.gl.FRAMEBUFFER, null );
			else
				this.gl.bindFramebuffer( this.gl.FRAMEBUFFER, this.framebuffer.glFramebuffer );
			//this.gl.bindFramebuffer( this.gl.FRAMEBUFFER,null );

			this.gl.clearColor( 0, 0, 0, 1 );
			this.gl.clear(this.gl.COLOR_BUFFER_BIT | this.gl.DEPTH_BUFFER_BIT);
			this.gl.viewport(0, 0, this.width, this.height);
			
			this.gl.enable( this.gl.DEPTH_TEST );
			this.gl.disable(this.gl.CULL_FACE);
			//this.gl.cullFace( this.gl.FRONT );
			
			var scene = this.viewport.scene;
			var entitys = scene.getEntitys();
			
			for(var e = 0;e<entitys.length;e++) {

				var entity = entitys[e];
				
				if(entity.type == "Actor") {
				
					var mesh = entity.mesh;
					var material = mesh.material;
					
					//if(material.alpha == 1.0) {
						
						
					var shader   = this.depthShader;
					
					var world = entity.getUpdatedWorldMatrix();
					//var viewProjection = this.viewport.mainCamera.worldViewProjection;
					
					
					
					var viewProjection = this.viewProjection;
					//var camera = this.viewport.mainCamera;
					//var viewProjection = camera.worldViewProjection;
					
					shader.setUniform("viewProjection", matrix4.mul(world, viewProjection)  );
					shader.setUniform("world", world );
					//shader.setUniform("diffuseColor", material.diffuseColor);
					shader.setUniform("near", this.near);
					shader.setUniform("far", this.far);
					//if(material.displacementMaps.length > 0) 
					//	shader.setUniform("view",  this.viewport.mainCamera.view );
					mesh.setViewport(this.viewport );
					mesh.createBuffers( );
					
					material.setViewport( this.viewport );
					material.updateShader(  );
					
					
					shader.update( this.viewport );
					
					//shader.update();
					
					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);

					
					if(mesh.draw_type == this.gl.TRIANGLES) {
					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.CULL_FACE);
		this.gl.cullFace( this.gl.BACK );
		this.gl.enableVertexAttribArray(1);
		this.gl.enableVertexAttribArray(2);
		this.gl.enableVertexAttribArray(3);
		this.gl.enableVertexAttribArray(4);
		//this.gl.enableVertexAttribArray(5);

	}
	

	createShadows( ) {

		var lightPos 		= [0, 15, 0];
		var shadowSampler 	= new samplerCube(this);
		
		shadowSampler.internalformat = this.gl.RGB;
		shadowSampler.format 		 = this.gl.RGB;
		shadowSampler.type 			 = this.gl.FLOAT;
		shadowSampler.width			 = 1024;
		shadowSampler.height		 = 1024;
		
		
			/*
		var shadowCamera = this.createShadowCam(lightPos, kepler.vector3.add(lightPos, [1, 0, 0]), [0, -1, 0], this.gl.TEXTURE_CUBE_MAP_POSITIVE_X, shadowSampler);
		this.shadowCameras.push(shadowCamera);

		var shadowCamera = this.createShadowCam(lightPos, kepler.vector3.add(lightPos, [-1, 0, 0]), [0, -1, 0], this.gl.TEXTURE_CUBE_MAP_NEGATIVE_X, shadowSampler);
		this.shadowCameras.push(shadowCamera);

		var shadowCamera = this.createShadowCam(lightPos, kepler.vector3.add(lightPos, [0, 1, 0]), [0, 0, 1], this.gl.TEXTURE_CUBE_MAP_POSITIVE_Y, shadowSampler);
		this.shadowCameras.push(shadowCamera);
		
		var shadowCamera = this.createShadowCam(lightPos, kepler.vector3.add(lightPos, [0, -1, 0]), [0, 0, -1], this.gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, shadowSampler);
		this.shadowCameras.push(shadowCamera);
		
		var shadowCamera = this.createShadowCam(lightPos, kepler.vector3.add(lightPos, [0, 0, 1]), [0, -1, 0], this.gl.TEXTURE_CUBE_MAP_POSITIVE_Z, shadowSampler);
		this.shadowCameras.push(shadowCamera);
		
		var shadowCamera = this.createShadowCam(lightPos, kepler.vector3.add(lightPos, [0, 0, -1]), [0, -1, 0], this.gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, shadowSampler);
		this.shadowCameras.push(shadowCamera);
		*/
		

		
		
		//this.depthShader.update();
		
		
		var shadowSampler 	= new sampler2D();
		
		shadowSampler.internalformat = this.gl.RGB;
		shadowSampler.format 		 = this.gl.RGB;
		shadowSampler.type 			 = this.gl.FLOAT;
		shadowSampler.width			 = 1024;
		shadowSampler.height		 = 1024;
		//shadowSampler.bind(this.depthShader);
		
		

		
		

		//this.depthShader.setUniform("far", shadowCamera.far );
		
		
		/*
		this.shadowShader = new shader();
		this.shadowShader.createFromFile("https://community.tensorui.com/assets/shaders/shadow.shader");
		this.shadowShader.setUniform("viewProjection", this.quadViewProjection );
		this.shadowShader.setUniform("shadowSampler", shadowSampler );
		this.shadowShader.setUniform("far", shadowCamera.far );
		this.shadowShader.setUniform("lightViewProjection", shadowCamera.viewProjection );
		this.shadowShader.setUniform("lightPosition", lightPos );
		*/

	}
}

export {depth as default};