import { HashObject } from "../../2d/HashObject";
import { WebglRenderer } from "../../2d/renderers/WebglRenderer";
import { GLShader } from "../../glCore";
import { RenderSideType } from "./BaseMaterial";

// precision mediump float;
// precision mediump int;

//
// uniform mat4 uViewMatrix;
// uniform mat4 uProjectionMatrix;
// uniform mat4 uModelMatrix;

export const defaultVertexShader3d =
    `attribute vec3 aPosition;
uniform mat4 uViewMatrix;
uniform mat4 uProjectionMatrix;
uniform mat4 uModelMatrix;
void main() {
    gl_Position = uProjectionMatrix * uViewMatrix * uModelMatrix * vec4( aPosition, 1.0 );
}`;
export const defaultFragmentShader3d =
    `void main() {
    gl_FragColor = vec4( 1.0, 0.0, 0.0, 1.0 );
}`

/**
 * 不考虑宏定义，否则自行修改getShader及缓存方式
 * 这三个必备，除非自己不需要几何的矩阵信息
 * uniform mat4 uViewMatrix;
 * uniform mat4 uProjectionMatrix;
 * uniform mat4 uModelMatrix;
 */
export class ShaderMaterial extends HashObject {
    /**
     * 是否用线框形式绘制
     */
    wireframe: boolean = false;
    /**
     * 材质渲染面
     */
    side: RenderSideType = RenderSideType.FrontSide;
    /**
     * key就是渲染器唯一id
     */
    protected shaders: { [key: string]: GLShader } = {};
    /**
     * 标记下。
     * 本来想直接用_instanceType判断，但是后续考虑到SpriteMaterial，SkyMaterial都会继承这个，会重写_instanceType
     */
    get isShaderMaterial(): boolean {
        return true;
    };
    constructor(
        protected vertexShader = defaultVertexShader3d,
        protected fragmentShader = defaultFragmentShader3d,
        public uniforms: { [key: string]: { type: UniformType, value: any } } = {}
    ) {
        super();
        this.vertexShader = vertexShader || defaultVertexShader3d;
        this.fragmentShader = fragmentShader || defaultFragmentShader3d;
        this._instanceType = "ShaderMaterial";
    }
    /**
     * 自定义着色器不考虑缓存了，自己注意，
     * 多个完全一样的自定义材质，用同一个就行了
     * @param renderer 
     */
    getShader(renderer: WebglRenderer): GLShader {
        const id = renderer.CONTEXT_UID;
        if (!this.shaders[id]) {
            //生成
            this.shaders[id] = new GLShader(
                renderer.gl,
                this.vertexShader,
                this.fragmentShader
            );
            this.shaders[id]["_glShaderKey"] = `customShader${"id" + id}${"instanceId" + this.instanceId}`;
        };
        return this.shaders[id];
    }

    destroy() {
        for (let id in this.shaders) {
            this.shaders[id].destroy();
            delete this.shaders[id];
        }
        this.shaders = null;
        this.vertexShader = null;
        this.fragmentShader = null
    }
}

export enum UniformType {
    float = "f",
    /**
     * 纹理对象
     */
    texture = "t",
    /**
     * 十六进制数字
     */
    color = "c",
    /**
     * v2对象
     */
    vector2 = "v2",
    /**
     * v3对象
     */
    vector3 = "v3",
    /**
     * v4对象
     */
    vector4 = "v4",
    /**
     * m4对象
     */
    matrix4 = "m4",
    /**
     * m3对象
     */
    matrix3 = "m3",
}