
import { compileProgram } from './shader/compileProgram';
import { extractAttributes } from './shader/extractAttributes';
import { extractUniforms } from './shader/extractUniforms';
import { setPrecision } from './shader/setPrecision';
import { generateUniformAccessObject } from './shader/generateUniformAccessObject';

/**
 * Helper class to create a webGL Shader
 * 创建webgl shader用，里面主要用到attributes和uniforms
 * @class
 * @memberof glCore
 * @param gl {WebGLRenderingContext}
 * @param vertexSrc {string|string[]} The vertex shader source as an array of strings.
 * @param fragmentSrc {string|string[]} The fragment shader source as an array of strings.
 * @param precision {string} The float precision of the shader. Options are 'lowp', 'mediump' or 'highp'.
 * @param attributeLocations {object} A key value pair showing which location eact attribute should sit eg {position:0, uvs:1}
 */
export class GLShader {
	/**
	 * The current WebGL rendering context
	 * @member {WebGLRenderingContext}
	 */
	gl: WebGLRenderingContext;
	/**
	 * The shader program
	 * @member {WebGLProgram}
	 */
	program: WebGLProgram;

	/**
	 *  The attributes of the shader as an object containing the following properties
	 * {
	 * 	type,
	 * 	size,
	 * 	location,
	 * 	pointer
	 * }
	 * @member {Object}
	 */
	attributes: any;

	uniformData: any;
	/**
	 * The uniforms of the shader as an object containing the following properties
	 * {
	 * 	gl,
	 * 	data
	 * }
	 * @member {Object}
	 */
	uniforms: any;

	constructor(
		gl:WebGLRenderingContext, 
		vertexSrc:string, 
		fragmentSrc:string, 
		precision?:string, 
		attributeLocations?) {
		this.gl = gl;

		if (precision) {
			vertexSrc = setPrecision(vertexSrc, precision);
			fragmentSrc = setPrecision(fragmentSrc, precision);
		}

		// First compile the program..
		this.program = compileProgram(gl, vertexSrc, fragmentSrc, attributeLocations);

		// next extract the attributes
		this.attributes = extractAttributes(gl, this.program);

		this.uniformData = extractUniforms(gl, this.program);

		this.uniforms = generateUniformAccessObject(gl, this.uniformData);

	};

	/**
	 * Uses this shader
	 * 状态机当前使用的shader
	 * @return {glCore.GLShader} Returns itself.
	 */
	public bind() {
		this.gl.useProgram(this.program);
		return this;
	};

	/**
	 * Destroys this shader
	 * TODO
	 */
	public destroy() {
		this.attributes = null;
		this.uniformData = null;
		this.uniforms = null;

		var gl = this.gl;
		gl.deleteProgram(this.program);
	};


}



