import { createIndicesForQuads } from "./createIndicesForQuads";
import { GLBuffer, VertexArrayObject, GLShader } from "../../../glCore";
import { Rectangle } from "../../math";



/**
 * webgl矩形数据
 * 外部基本不使用，不继承HashObject
 */
export default class Quad {
    /**
     * 当前gl上下文
     */
    gl: WebGLRenderingContext;
    /**
     * 顶点数据
     */
    vertices: Float32Array;
    /**
     * uv数据
     */
    uvs: Float32Array;
    /**
     * 顶点和uv干一起
     */
    interleaved: Float32Array;
    /**
     * 索引数据
     */
    indices: Uint16Array;

    vertexBuffer: GLBuffer;
    indexBuffer: GLBuffer;
    vao: VertexArrayObject;
    /**
     * @param {WebGLRenderingContext} gl - The gl context for this quad to use.
     * @param {object} state - TODO: Description
     */
    constructor(gl: WebGLRenderingContext, state: any) {
        this.gl = gl;
        this.vertices = new Float32Array([
            -1, -1,
            1, -1,
            1, 1,
            -1, 1,
        ]);
        this.uvs = new Float32Array([
            0, 0,
            1, 0,
            1, 1,
            0, 1,
        ]);

        this.interleaved = new Float32Array(8 * 2);

        for (let i = 0; i < 4; i++) {
            this.interleaved[i * 4] = this.vertices[(i * 2)];
            this.interleaved[(i * 4) + 1] = this.vertices[(i * 2) + 1];
            this.interleaved[(i * 4) + 2] = this.uvs[i * 2];
            this.interleaved[(i * 4) + 3] = this.uvs[(i * 2) + 1];
        }

        this.indices = createIndicesForQuads(1);

        this.vertexBuffer = GLBuffer.createVertexBuffer(gl, this.interleaved, gl.STATIC_DRAW);

        this.indexBuffer = GLBuffer.createIndexBuffer(gl, this.indices, gl.STATIC_DRAW);

        this.vao = new VertexArrayObject(gl, state);
    }

    /**
     * 用shader初始化vao
     */
    initVao(shader: GLShader) {
        this.vao.clear()
            .addIndex(this.indexBuffer)
            .addAttribute(this.vertexBuffer, shader.attributes.aVertexPosition, this.gl.FLOAT, false, 4 * 4, 0)
            .addAttribute(this.vertexBuffer, shader.attributes.aTextureCoord, this.gl.FLOAT, false, 4 * 4, 2 * 4);
    }

    /**
     * Maps two Rectangle to the quad.
     * @param {Rectangle} targetTextureFrame - the first rectangle
     * @param {Rectangle} destinationFrame - the second rectangle
     * @return {Quad} Returns itself.
     */
    map(targetTextureFrame: Rectangle, destinationFrame: Rectangle): Quad {
        let x = 0; // destinationFrame.x / targetTextureFrame.width;
        let y = 0; // destinationFrame.y / targetTextureFrame.height;

        this.uvs[0] = x;
        this.uvs[1] = y;

        this.uvs[2] = x + (destinationFrame.width / targetTextureFrame.width);
        this.uvs[3] = y;

        this.uvs[4] = x + (destinationFrame.width / targetTextureFrame.width);
        this.uvs[5] = y + (destinationFrame.height / targetTextureFrame.height);

        this.uvs[6] = x;
        this.uvs[7] = y + (destinationFrame.height / targetTextureFrame.height);

        x = destinationFrame.x;
        y = destinationFrame.y;

        this.vertices[0] = x;
        this.vertices[1] = y;

        this.vertices[2] = x + destinationFrame.width;
        this.vertices[3] = y;

        this.vertices[4] = x + destinationFrame.width;
        this.vertices[5] = y + destinationFrame.height;

        this.vertices[6] = x;
        this.vertices[7] = y + destinationFrame.height;

        return this;
    }

    /**
     * 上传绑定数据
     * @return {Quad} Returns itself.
     */
    upload(): Quad {
        for (let i = 0; i < 4; i++) {
            this.interleaved[i * 4] = this.vertices[(i * 2)];
            this.interleaved[(i * 4) + 1] = this.vertices[(i * 2) + 1];
            this.interleaved[(i * 4) + 2] = this.uvs[i * 2];
            this.interleaved[(i * 4) + 3] = this.uvs[(i * 2) + 1];
        }

        this.vertexBuffer.upload(this.interleaved);

        return this;
    }

    destroy() {
        const gl = this.gl;

        gl.deleteBuffer(this.vertexBuffer);
        gl.deleteBuffer(this.indexBuffer);

        this.gl = null;
        this.vertices = null;
        this.uvs = null;
        this.interleaved = null;
        this.indices = null;

        this.vertexBuffer.destroy();
        this.indexBuffer.destroy();
        this.vao.destroy();
    }
}
