var EMPTY_ARRAY_BUFFER = new ArrayBuffer(0);

/**
 * 用于创建webGL buffer，顶点和索引专用
 * @class
 * @memberof glCore
 * @param gl {WebGLRenderingContext} The current WebGL rendering context
 * @param type {gl.ARRAY_BUFFER | gl.ELEMENT_ARRAY_BUFFER} @mat
 * @param data {ArrayBuffer| SharedArrayBuffer|ArrayBufferView} an array of data
 * @param drawType {gl.STATIC_DRAW|gl.DYNAMIC_DRAW|gl.STREAM_DRAW}
 */
export class GLBuffer {
	/**
	 * 当前上下文
	 * @member {WebGLRenderingContext}
	 */
	gl: any;
	/**
	 * The WebGL buffer, created upon instantiation
	 * @member {WebGLBuffer}
	 */
	buffer: any;
	/**
	 * buffer类型
	 * 顶点或索引
	 * @member {gl.ARRAY_BUFFER|gl.ELEMENT_ARRAY_BUFFER}
	 */
	type: any;

	/**
	 * The draw type of the buffer
	 * 绘制类型
	 * gl.STATIC_DRAW: 缓冲区的内容可能经常使用，而不会经常更改
	 * gl.DYNAMIC_DRAW: 缓冲区的内容可能经常被使用，并且经常更改
	 * gl.STREAM_DRAW: 缓冲区的内容可能不会经常使用,且不会经常更改
	 * @member {gl.STATIC_DRAW|gl.DYNAMIC_DRAW|gl.STREAM_DRAW}
	 */
	drawType: any;

	/**
	 * The data in the buffer, as a typed array
	 * 用来表示通用的、固定长度的原始二进制数据缓冲区。ArrayBuffer 不能直接操作，
	 * 而是要通过类型数组对象或 DataView 对象来操作，
	 * 它们会将缓冲区中的数据表示为特定的格式，并通过这些格式来读写缓冲区的内容。
	 * @member {ArrayBuffer| SharedArrayBuffer|ArrayBufferView}
	 */
	data;

	/**
	 * 更新ID
	 */
	_updateID: number;
	constructor(gl, type?, data?, drawType?) {

		this.gl = gl;

		this.buffer = gl.createBuffer();

		this.type = type || gl.ARRAY_BUFFER;

		this.drawType = drawType || gl.STATIC_DRAW;

		this.data = EMPTY_ARRAY_BUFFER;

		if (data) {
			this.upload(data);
		}

		this._updateID = 0;
	};

	/**
	 * 上传数据
	 * Uploads the buffer to the GPU
	 * @param data {ArrayBuffer| SharedArrayBuffer|ArrayBufferView} an array of data to upload
	 * @param offset {Number} if only a subset of the data should be uploaded, this is the amount of data to subtract
	 * @param dontBind {Boolean} whether to bind the buffer before uploading it  是否不绑定buffer
	 */
	public upload(data, offset?:number, dontBind?:boolean) {
		// todo - needed?
		if (!dontBind) this.bind();

		var gl = this.gl;

		data = data || this.data;
		offset = offset || 0;

		if (this.data.byteLength >= data.byteLength) {
			gl.bufferSubData(this.type, offset, data);
		}
		else {
			gl.bufferData(this.type, data, this.drawType);
		}

		this.data = data;
	};

	/**
	 * Binds the buffer
	 * 状态机接下来使用的buffer
	 * 
	 */
	public bind() {
		var gl = this.gl;
		gl.bindBuffer(this.type, this.buffer);
	};
	/**
	 * Destroys the buffer
	 *
	 */
	public destroy = function () {
		this.gl.deleteBuffer(this.buffer);
	};
	/**
	 * 创建顶点缓存
	 * @param gl 
	 * @param data 
	 * @param drawType 
	 */
	public static createVertexBuffer(gl, data?, drawType?) {
		return new GLBuffer(gl, gl.ARRAY_BUFFER, data, drawType);
	};

	/**
	 * 创建索引缓存
	 * @param gl 
	 * @param data 
	 * @param drawType 
	 */
	public static createIndexBuffer(gl, data?, drawType?) {
		return new GLBuffer(gl, gl.ELEMENT_ARRAY_BUFFER, data, drawType);
	};

	public static create(gl, type, data, drawType) {
		return new GLBuffer(gl, type, data, drawType);
	};


}


