import ObjectRenderer from "../2d/renderers/webgl/ObjectRenderer";
import { WebglRenderer } from "../2d/renderers/WebglRenderer";
import { Camera } from "./cameras/Camera";
import { LightsConfig } from "./Scene3D";
import { GLShader, GLBuffer } from "../glCore";
import { Mesh3D } from "./Mesh3D";
import { BaseShader } from "./shaders/BaseShader";
import { LightShader } from "./shaders/LightShader";
import { hex2rgb, rgb2hex } from "../2d/utils";
import { Matrix4 } from "./math/Matrix4";
import { BLEND_MODES } from "../2d/const";
import { BatchBuffer } from "../2d/renderers/webgl/BatchBuffer";
import { BaseMaterial, RenderSideType } from "./materials/BaseMaterial";
import { getCusShader } from "./shaders/getCusShader";


//需要管理渲染的状态 resetToDefault  resetTo3D
export class D3Renderer extends ObjectRenderer {
    /**
     * 赋值的相机，需要里面的worldMatrixInverse和projectionMatrix
     */
    camera: Camera;
    /**
     * 灯光数据，用来初始化着色器和着色器传值
     */
    lightsConfig: LightsConfig;

    private curLightkey: string;
    constructor(renderer: WebglRenderer) {
        super(renderer);
    }
    onContextChange() {

    }
    start() {
        //设置3d状态机属性
        // this.renderer.state.resetTo3D();
        //自行设置状态机，原先的有太多问题
        //允许深度检测
        this.renderer.state.setDepthTest(1);
        //混色模式重新设置
        this.renderer.state.setBlendMode(BLEND_MODES.NORMAL_NPM);
        //设置逆时针为正面，下面根据材质自行设置
        //this.renderer.state.setFrontFace(0);
        //设置剔除，下面根据材质自行设置
        //this.setCullFace(1);
    }
    stop() {
        this.flush();
        //原先的视窗需要重新//讲道理应该渲染器自己搞，算了
        this.renderer._activeRenderTarget.activate();
        // this.renderer.rootRenderTarget.activate();

        this.renderer.state.setState(this.renderer.state.defaultState)
    }

    private meshes: Mesh3D[] = [];
    //继续需要的数据
    render(obj: Mesh3D) {
        if (!obj.geometry || !obj.material) return;
        var mat = obj.material;
        var geo = obj.geometry;
        //提取渲染对象及材质，分组渲染，怎么考虑同一个geometry只需要处理一次attr，
        //分组按
        // if (!this.meshes.length) {
        //     this.meshes.push(obj);
        // } else {
        for (var i = 0; i < this.meshes.length; i++) {
            if (this.meshes[i].material == mat) {//没啥软用
                this.meshes.splice(i, 0, obj)
                return
            }
        }
        // }
        this.meshes.push(obj);
    }
    flush() {
        //同一材质的模型一起处理，同一个着色器，webglRenderer里会判断，不会重复绑定
        var curShader: GLShader = null;
        var pointLightNum = this.lightsConfig.pointLights.length;
        var dirLightNum = this.lightsConfig.directionalLights.length;
        var gl: WebGLRenderingContext = this.renderer.gl;
        for (var i = 0; i < this.meshes.length; i++) {
            let mesh = this.meshes[i];//怎么判断是否要重新绑定
            let mat: BaseMaterial = mesh.material;
            let geo = mesh.geometry;

            let shader = getCusShader(this.renderer, mat, this.lightsConfig);
            if (curShader !== shader) {//同一着色器只需要传一次相机参数和光照参数（因为都是场景全局）
                curShader = shader;
                //先绑定着色器，project不设置
                this.renderer.bindShader(curShader, false);
                //相机
                curShader.uniforms["uViewMatrix"] = this.camera.worldMatrixInverse.toArray();;
                curShader.uniforms["uProjectionMatrix"] = this.camera.projectionMatrix.toArray();
                //光照
                if (mat._lightAffect) {
                    //只能给当前绑定的shader传值，否则location不存在
                    for (var j = 0; j < pointLightNum; j++) {
                        let key = "pointLights[" + j + "]";
                        curShader.uniforms[key].color = this.lightsConfig.pointLights[j].color;
                        curShader.uniforms[key].position = this.lightsConfig.pointLights[j].position;
                        curShader.uniforms[key].distance = this.lightsConfig.pointLights[j].distance;
                        curShader.uniforms[key].decay = this.lightsConfig.pointLights[j].decay;
                    }
                    for (var j = 0; j < dirLightNum; j++) {
                        let key = "directionalLights[" + j + "]";
                        curShader.uniforms[key].color = this.lightsConfig.directionalLights[j].color;
                        curShader.uniforms[key].direction = this.lightsConfig.directionalLights[j].direction;
                    }
                    curShader.uniforms.uAmbientLightColor = this.lightsConfig.ambientLightColor;
                }
            }
            //找纹理，绑定纹理，多个纹理也是一样的方法
            var location: number = this.renderer.textureManager.bindTexture(mat.map, undefined, false);
            //传入uniform
            curShader.uniforms["uMap"] = location;
            //uniform参数修改，好像目前就几个，且固定的，以后得仿three建数组
            curShader.uniforms["uMatColor"] = mat.colorArr;
            curShader.uniforms["uMatAlpha"] = mat.alpha;

            //mesh的模型矩阵
            curShader.uniforms["uModelMatrix"] = mesh._worldMatrix.toArray();
            //法线矩阵
            if (curShader.uniforms.uNormalMatrix) {
                var modelViewMatrix = new Matrix4().multiplyMatrices(this.camera.worldMatrixInverse, mesh._worldMatrix)
                var normalMatrix = modelViewMatrix.invert().transpose();
                // var normalMatrix = mesh._worldMatrix.invert().transpose();
                curShader.uniforms["uNormalMatrix"] = normalMatrix.toArray()
                // this.setShaderUniform(curShader, "uNormalMatrix", normalMatrix.toArray());
            }

            //几何属性
            var glVaoBuffer = geo._glVaoBuffer[this.renderer.CONTEXT_UID];
            if (!geo._glVaoBuffer[this.renderer.CONTEXT_UID]) {
                glVaoBuffer = geo._glVaoBuffer[this.renderer.CONTEXT_UID] = {
                    // indexBuffer: GLBuffer.createIndexBuffer(gl, null, gl.STATIC_DRAW),
                    attrBuffer: GLBuffer.createVertexBuffer(gl, null, gl.STATIC_DRAW),
                    vaos: {}
                }
                //有索引
                if (geo._indices) glVaoBuffer.indexBuffer = GLBuffer.createIndexBuffer(gl, null, gl.STATIC_DRAW);

                //计算一次，打包所有的顶点属性
                const float32View = geo._attrBuffer.float32View;
                var count = 0;
                for (var j = 0; j < geo._vertices.length / 3; j++) {
                    //顶点
                    float32View[count++] = geo._vertices[j * 3];
                    float32View[count++] = geo._vertices[j * 3 + 1];
                    float32View[count++] = geo._vertices[j * 3 + 2];
                    //@ts-ignore 颜色，以后搞成一位，现在有bug
                    // geo._attrBuffer.uint32View[count++] = rgb2hex(geo._colors.slice(j * 3, j * 3 + 3)) + (1 * 255 << 24)
                    float32View[count++] = geo._colors[j * 3];
                    float32View[count++] = geo._colors[j * 3 + 1];
                    float32View[count++] = geo._colors[j * 3 + 2];
                    // float32View[count++] = 1;
                    //uv
                    float32View[count++] = geo._uvs[j * 2];
                    float32View[count++] = geo._uvs[j * 2 + 1];
                    //法线,可能不需要法线的情况，也加上先
                    float32View[count++] = geo._normals[j * 3];
                    float32View[count++] = geo._normals[j * 3 + 1];
                    float32View[count++] = geo._normals[j * 3 + 2];

                    //如果存在mo
                    if (1) { }
                }
            }
            //@ts-ignore
            var vao = glVaoBuffer.vaos[curShader._glShaderKey];
            var attrs = curShader.attributes;
            //计算打包顶点信息
            this.packGeometry()
            if (!vao) {
                //@ts-ignore
                vao = glVaoBuffer.vaos[curShader._glShaderKey] = this.renderer.createVao()
                    //索引
                    // .addIndex(glVaoBuffer.indexBuffer)
                    //顶点
                    .addAttribute(glVaoBuffer.attrBuffer, attrs.aPosition, gl.FLOAT, false, geo._vertByteSize, 0 * 4)
                    //颜色
                    .addAttribute(glVaoBuffer.attrBuffer, attrs.aColor, gl.FLOAT, true, geo._vertByteSize, 3 * 4)
                    //uv
                    .addAttribute(glVaoBuffer.attrBuffer, attrs.aTextureCoord, gl.FLOAT, true, geo._vertByteSize, 6 * 4)
                //法线,看情况加
                if (attrs.aNormal) vao.addAttribute(glVaoBuffer.attrBuffer, attrs.aNormal, gl.FLOAT, false, geo._vertByteSize, 8 * 4);
                //索引看情况加
                if (geo._indices) vao.addIndex(glVaoBuffer.indexBuffer);
                // 首次需要绑定buffer到vao
                this.renderer.bindVao(vao);
                //需要分别绑定
                glVaoBuffer.attrBuffer.upload(geo._attrBuffer.vertices, 0, false)
                //有索引才改
                if (geo._indices) glVaoBuffer.indexBuffer.upload(geo._indices, 0, false)
            } else {
                this.renderer.bindVao(vao);
                //不修改，估计都不要变，需要修改时候
                // glVaoBuffer.attrBuffer.upload(glVaoBuffer._attrBuffer.vertices, 0, true)
                // glVaoBuffer.indexBuffer.upload(glVaoBuffer._indexBuffer, 0, true)
                //变形的数据可能传入的会改变，所以需要upload
                
            }
            //根据材质切换渲染面
            if (mat.side == RenderSideType.DoubleSide) {
                this.renderer.state.setCullFace(0)//不开启剔除
            } else {
                this.renderer.state.setCullFace(1)
                //设置剔除面
                this.renderer.state.setFrontFace(mat.side)
            }
            //绘制
            vao.draw(mat.wireframe ? gl.LINES : gl.TRIANGLES);
        }
        this.meshes.length = 0
    }

    private packGeometry() {

    }

}

interface renderObjInt {



}

WebglRenderer.registerPlugin('d3', D3Renderer);

// class FreeScroll extends FYGE.Container {
//     viewWidth;
//     viewHeight;
//     maxWidth;
//     maxHeight;
//     view
//     bg
//     constructor(viewWidth, viewHeight, maxWidth, maxHeight) {
//         super()
//         this.viewWidth = viewWidth
//         this.viewHeight = viewHeight
//         this.maxWidth = maxWidth
//         this.maxHeight = maxHeight

//         //鼠标事件捕捉用
//         this.bg = this.addChild(new FYGE.Graphics())
//             .beginFill(0x000000)
//             .drawRect(0, 0, viewWidth, viewHeight)
//             .endFill()
//         this.alpha = 0;
//         //内容视图
//         this.view = this.addChild(new FYGE.Container());
//         //x范围viewWidth-maxWidth到0，y范围viewHeight-maxHeight到0
//         this.addEventListener(FYGE.MouseEvent.MOUSE_DOWN, (e: FYGE.MouseEvent) => {
//             let offset = [e.stageX - this.view.x, e.stageY - this.view.y];
//             //加移动事件
//             this.addEventListener(FYGE.MouseEvent.MOUSE_MOVE, move, this)
//             this.addEventListener(FYGE.MouseEvent.MOUSE_UP, up, this)
//             this.addEventListener(FYGE.MouseEvent.MOUSE_OUT, up, this)
//             //移动
//             function move(me: FYGE.MouseEvent) {
//                 //赋值x
//                 this.view.x = me.stageX - offset[0];
//                 this.view.y = me.stageY - offset[1];
//                 //x有限制
//                 if (this.view.x < this.viewWidth - this.maxWidth) this.view.x = this.viewWidth - this.maxWidth;
//                 if (this.view.x > 0) this.view.x = 0;
//                 //y限制
//                 if (this.view.y < this.viewHeight - this.maxHeight) this.view.y = this.viewHeight - this.maxHeight;
//                 if (this.view.y > 0) this.view.y = 0;
//             }
//             function up() {
//                 this.removeEventListener(FYGE.MouseEvent.MOUSE_MOVE, move, this);
//                 this.removeEventListener(FYGE.MouseEvent.MOUSE_UP, up, this);
//                 this.removeEventListener(FYGE.MouseEvent.MOUSE_OUT, up, this);
//             }
//         }, this)
//     }
// }