import Scene from "../views/Scene";
import PanelCtrl from "../ctrls/panelCtrl";
import { ModuleTypes } from "../types/sceneTypes";
import VirtualJoystick from "../components/VirtualJoystick"
import GameConst from "../GameConst";

const { TouchEvent } = egret;
export default class PlayScene extends Scene{
    protected get skinKey() { return 'Play' }

    public rulePanel:eui.Panel;
    public fireBtn:eui.Button;
    public photoPanel:eui.Panel;
    public resultPanel:eui.Panel;
    // public VJ:eui.Component;
    

    private vj:VirtualJoystick = new VirtualJoystick(125,GameConst.stage.stageHeight-230);

    public BABYLON:any = window['BABYLON'];
    public nipplejs:any = window['nipplejs'];
    public joystickL:any;
    public joystickR:any;
    public canvasWebgl:any;
    public scene:any;
    public camera:any;
    public light:any;
    public ground:any;
    public fireCollisionArr:any[] = [];
    public tankP:any;
    public tank:any;
    private tankArr:any[] = [];
    private bulletPool:any[] = [];
    private bulletCount:number = 0;
    private isFireEnable:boolean = false;
    private tankSpeed:number = 0.15;
    private gravity:number = -0.98;
    private moveForward:boolean = false;
    private moveBackward:boolean = false;
    private rotateLeft:boolean = false;
    private rotateRight:boolean = false;
    private tankDownHits:any[] = [];
    private pipeline:any;
    private glowLayer:any;
    

    constructor(){
        super()
        this.show();
    }


    show(){

        //开启虚拟摇杆
        this.vj.start();

        this.vj.addEventListener("vj_start",this.onVJStart, this);
        this.vj.addEventListener("vj_end", this.onVJEnd, this);

        let container = document.getElementById("egretContainer");
        let w = document.documentElement.clientWidth || document.body.clientWidth;
        let h = document.documentElement.clientHeight || document.body.clientHeight;
        document.querySelectorAll("canvas")[0].style.position = "absolute";
        document.querySelectorAll("canvas")[0].setAttribute("touch-action","none");
        this.canvasWebgl = document.createElement("canvas");
        this.canvasWebgl.width = w;
        this.canvasWebgl.height = h;
        container.appendChild(this.canvasWebgl);

        let engine = new this.BABYLON.Engine(this.canvasWebgl, true);
        engine.getRenderingCanvas=function(){
            return document.querySelectorAll("canvas")[0]
        };

        this.scene = new this.BABYLON.Scene(engine);
        this.scene.ambientColor = this.BABYLON.Color3.FromInts(10, 30, 10);
        // this.scene.clearColor = this.BABYLON.Color3.FromInts(127, 165, 13);
        this.scene.gravity = new this.BABYLON.Vector3(0, -0.9, 0);
        this.scene.collisionsEnabled = true;

        this.light = new this.BABYLON.DirectionalLight("dir01", new this.BABYLON.Vector3(0, -1, -0.3), this.scene);
        this.light.position = new this.BABYLON.Vector3(20, 60, 30);

        this.camera = new this.BABYLON.FreeCamera("Camera", new this.BABYLON.Vector3(0, 50, -50), this.scene);
        // this.camera.attachControl(document.querySelectorAll("canvas")[0], false);

        this.glowLayer = new BABYLON.GlowLayer("glow", this.scene);
        this.glowLayer.intensity = 2;
        
        // this.scene.activeCamera = this.camera;
        BABYLON.SceneLoader.ImportMesh("", "./resource/model/", "tank.obj", this.scene, (newMeshes) => {
            
            this.tank = this.BABYLON.Mesh.CreateBox('tank', 2, this.scene);
            this.tankP = this.BABYLON.Mesh.CreateBox('tank', 2, this.scene);
            this.tankP.parent = this.tank;
            this.tankP.visibility = 0;
            this.tank.visibility = 0;
            
            this.tank.ellipsoid = new this.BABYLON.Vector3(1,1,1);
            this.tank.ellipsoidOffset = new this.BABYLON.Vector3(0, 0.0, 0);
            //finalPosition = position - vec3(0, ellipsoid.y, 0) + ellipsoidOffset
            this.tank.position.y = 5;
            this.tank.checkCollisions = true;
            this.tank.applyGravity = true;
            

            this.camera.parent = this.tank;
            this.camera.setTarget(newMeshes[0].position.add(new this.BABYLON.Vector3(0,15,0)))
            newMeshes.forEach((mesh)=>{
                mesh.position.y = -0.8;
                this.tankArr.push(mesh);
                mesh.parent = this.tankP;
            })


            this.tank.position = new this.BABYLON.Vector3(-35,2,-35)
            this.tank.lookAt(new this.BABYLON.Vector3(-50,0,-50))
            this.tank.downRay = new this.BABYLON.Ray();
            let rayHelper = new BABYLON.RayHelper(this.tank.downRay);
            let localMeshDirection = new BABYLON.Vector3(0, -1, 0);
            let localMeshOrigin = new BABYLON.Vector3(0, 2, 0);
            let length = 10;
            rayHelper.attachToMesh(this.tank, localMeshDirection, localMeshOrigin, length);
            // rayHelper.show(this.scene, this.BABYLON.Color3.Red);

            this.tank.forwardRay = new this.BABYLON.Ray();
            let rayHelper2 = new BABYLON.RayHelper(this.tank.forwardRay);
            let localMeshDirection2 = new BABYLON.Vector3(0, 0, 1);
            let localMeshOrigin2 = new BABYLON.Vector3(0, 0, 0);
            let length2 = 100;
            rayHelper2.attachToMesh(this.tank, localMeshDirection2, localMeshOrigin2, length2);
            // rayHelper2.show(this.scene, this.BABYLON.Color3.White);

            this.childrenCreated();
        })

        // 生成子弹
        BABYLON.SceneLoader.ImportMesh("", "./resource/model/", "bullet.obj", this.scene, (newMeshes) => {
            newMeshes[0].material['opacityTexture'] = null;
            newMeshes[0].material.backFaceCulling = false;
            newMeshes[0].isVisible = false;
            newMeshes[0].position.y = this.ground.getHeightAtCoordinates(0, 0); 
            let count = 5;
            for (let index = 0; index < count; index++) {
                let newInstance =  newMeshes[0]['createInstance']("i" + index);
                let scale = 1.5
                newInstance.scaling.addInPlace(new BABYLON.Vector3(scale, scale, scale));
                newInstance.checkCollisions = true;
                this.bulletPool.push(newInstance)
            }

            this.isFireEnable = true;
        })
        
        
        this.tankSpeed = 0.15;
        this.gravity = -0.001;
        
        // Fog
        this.scene.fogMode = BABYLON.Scene.FOGMODE_EXP;
        this.scene.fogDensity = 0.01;
        this.scene.fogColor = this.scene.clearColor;

        // 创建地形
        this.createGround();

        let inputManager = this.camera.inputs;

        this.addEventListener(egret.Event.ENTER_FRAME,this.onEnterFrame,this);
    }

    private onEnterFrame(){
        this.scene.render();
        

        if(this.tank){
            this.tankDownHits = this.tank.downRay.intersectsMeshes([this.ground]);
            
            // 坦克复制法线
            if(this.tankDownHits.length>0){
                // console.log(this.tankDownHits[0].getNormal())
                let pickedFaceNormal = this.tankDownHits[0].getNormal();
                if(Math.abs(this.tankP.rotation.x - pickedFaceNormal.x) > 0.1){
                    let tw = egret.Tween.get(this.tankP.rotation);
                    tw.to({x:pickedFaceNormal.x},200);
                }
                
            }

            // 坦克旋转
            if(this.rotateLeft){
                this.tank.rotation.y-=0.02;
            }else if(this.rotateRight){
                this.tank.rotation.y+=0.02;
            }

            // 坦克前进后退
            if(this.moveForward){
                let forwards = new BABYLON.Vector3(this.tank.forward.x*this.tankSpeed,-0.98*this.tankSpeed,this.tank.forward.z*this.tankSpeed);
                forwards.negate();
                this.tank.moveWithCollisions(forwards);
            }else if(this.moveBackward){
                let backwards = new BABYLON.Vector3(-this.tank.forward.x*this.tankSpeed*0.5,-0.98*this.tankSpeed,-this.tank.forward.z*this.tankSpeed*0.5);
                backwards.negate();
                this.tank.moveWithCollisions(backwards);
            }
        }
        
        // 子弹的移动
        this.bulletPool.forEach(bullet=>{
            if(bullet.forwards){
                this.moveByVector(bullet, bullet.forwards, 2, true);

                // console.log(bullet.position.y)
                if( !bullet.isBoomed && bullet.position.y <= 0.5 ){
                    let sphere = this.BABYLON.Mesh.CreateSphere('boom', 16, 1, this.scene);
                    sphere.material = new this.BABYLON.StandardMaterial('boom', this.scene);
                    sphere.material.emissiveTexture = new BABYLON.Texture("./resource/assets/playScene/boom.jpg", this.scene);
                    sphere.material.emissiveColor = new BABYLON.Color3(1, 1, 1);
                    sphere.material["diffuseColor"]=new BABYLON.Color3(0,0,0)
                    sphere.material.disableLighting = true;
                    sphere.position.copyFrom(bullet.position);
                    let tw = egret.Tween.get( sphere.scaling );
                    tw.to( {x:10, y:10, z:10}, 200 ).wait(50).call(()=>{
                        let tw2 = egret.Tween.get( sphere.material );
                        tw2.to({ alpha:0 }, 80);    
                    });
                    bullet.hitPoint = null;
                    bullet.isVisible = false;
                    bullet.isBoomed = true;
                }

                if( !bullet.isBoomed && bullet.hitPoint ){
                    let dx = bullet.position.x - bullet.hitPoint.x;
                    let dy = bullet.position.y - bullet.hitPoint.y;
                    let dz = bullet.position.z - bullet.hitPoint.z;
                    let dist = Math.sqrt(dx*dx + dy*dy + dz*dz); 
                    
                    if(dist < 10){
                        let sphere = this.BABYLON.Mesh.CreateSphere('boom', 16, 1, this.scene);
                    sphere.material = new this.BABYLON.StandardMaterial('boom', this.scene);
                    sphere.material.emissiveTexture = new BABYLON.Texture("./resource/assets/playScene/boom.jpg", this.scene);
                    sphere.material.emissiveColor = new BABYLON.Color3(1, 1, 1);
                    sphere.material["diffuseColor"]=new BABYLON.Color3(0,0,0)
                    sphere.material.disableLighting = true;
                    sphere.position.copyFrom(bullet.position);
                    let tw = egret.Tween.get( sphere.scaling );
                    tw.to( {x:10, y:10, z:10}, 200 ).wait(50).call(()=>{
                        let tw2 = egret.Tween.get( sphere.material );
                        tw2.to({ alpha:0 }, 80);    
                    });
                        bullet.isBoomed = true;
                        bullet.isVisible = false;
                        bullet.hitPoint = null;
                    }
                }
                
            }
        })

        
    }
    
    private vecToLocal(vector, mesh){
        var m = mesh.getWorldMatrix();
        var v = BABYLON.Vector3.TransformCoordinates(vector, m);
		return v;		 
    }

    private createGround(){
        
        this.ground = BABYLON.Mesh.CreateGroundFromHeightMap("ground", "./resource/assets/playScene/heightMap.png", 100, 100, 100, 0, 4, this.scene, false);
        let groundMaterial = new BABYLON.StandardMaterial("ground", this.scene);
        groundMaterial.diffuseTexture = new BABYLON.Texture("./resource/assets/playScene/ground2.jpg", this.scene);

        // groundMaterial.diffuseTexture.uScale = 6;
        // groundMaterial.diffuseTexture.vScale = 6;
        groundMaterial.specularColor = new BABYLON.Color3(0, 0, 0);
        // groundMaterial.emissiveColor = new BABYLON.Color3(0.3, 0.3, 0.3);
        this.ground.material = groundMaterial;
        this.ground.receiveShadows = true;
        this.ground.checkCollisions = true;
        this.fireCollisionArr.push(this.ground);

        this.ground.onReady = () => {
            this.ground.optimize(100);

            // Shadows
            let shadowGenerator = new this.BABYLON.ShadowGenerator(1024, this.light);
            
            // 树
            BABYLON.SceneLoader.ImportMesh("", "./resource/model/", "Tree.obj", this.scene, (newMeshes) => {
                this.createFixedMeshes(newMeshes[0], 20, shadowGenerator, false, true);
            })
            // 岩石1
            BABYLON.SceneLoader.ImportMesh("", "./resource/model/", "Rocks01.obj", this.scene, (newMeshes) => {
                this.createFixedMeshes(newMeshes[0], 5, shadowGenerator, true, true);
            })
            // 岩石2
            BABYLON.SceneLoader.ImportMesh("", "./resource/model/", "Rocks02.obj", this.scene, (newMeshes) => {
                this.createFixedMeshes(newMeshes[0], 1, shadowGenerator, true, true);
            })

            //  骨头
            BABYLON.SceneLoader.ImportMesh("", "./resource/model/", "Bone.obj", this.scene, (newMeshes) => {
                this.createFixedMeshes(newMeshes[0], 3, shadowGenerator);
            })
        }


        // 不可见的边界
        let border0 = BABYLON.Mesh.CreateBox("border0", 1, this.scene);
        border0.scaling = new BABYLON.Vector3(10, 10, 110);
        border0.position.x = -50.0;
        border0.checkCollisions = true;
        // border0.isVisible = false;

        let border1 = BABYLON.Mesh.CreateBox("border1", 1, this.scene);
        border1.scaling = new BABYLON.Vector3(10, 10, 110);
        border1.position.x = 50.0;
        border1.checkCollisions = true;
        // border1.isVisible = false;

        let border2 = BABYLON.Mesh.CreateBox("border2", 1, this.scene);
        border2.scaling = new BABYLON.Vector3(110, 10, 10);
        border2.position.z = 50.0;
        border2.checkCollisions = true;
        // border2.isVisible = false;

        let border3 = BABYLON.Mesh.CreateBox("border3", 1, this.scene);
        border3.scaling = new BABYLON.Vector3(110, 10, 10);
        border3.position.z = -50.0;
        border3.checkCollisions = true;

        this.fireCollisionArr.push(border0)
        this.fireCollisionArr.push(border1)
        this.fireCollisionArr.push(border2)
        this.fireCollisionArr.push(border3)
    }

    private createFixedMeshes(mesh:any,number:number,shadowGenerator?:any,isCollision?:boolean,isFireCollision?:boolean){
        if(!mesh || !number){
            return
        }
        mesh.material['opacityTexture'] = null;
        mesh.material.backFaceCulling = false;
        mesh.isVisible = false;
        mesh.position.y = this.ground.getHeightAtCoordinates(0, 0); 
        if(shadowGenerator){
            shadowGenerator.getShadowMap().renderList.push(mesh);
        }
        
        let range = 40;
        let count = number;
        for (let index = 0; index < count; index++) {
            let newInstance = mesh['createInstance']("i" + index);
            let x = range / 2 - Math.random() * range;
            let z = range / 2 - Math.random() * range;

            let y = this.ground.getHeightAtCoordinates(x, z); 

            newInstance.position = new BABYLON.Vector3(x, y, z);

            newInstance.rotate(BABYLON.Axis.Y, Math.random() * Math.PI * 2, BABYLON.Space.WORLD);

            let scale = 0.5 + Math.random() * 2;
            newInstance.scaling.addInPlace(new BABYLON.Vector3(scale, scale, scale));

            if(shadowGenerator){
                shadowGenerator.getShadowMap().renderList.push(newInstance);
            }

            if(isCollision){
                newInstance.checkCollisions = true;
            }

            if(isFireCollision){
                this.fireCollisionArr.push(newInstance);
            }
            
            
        }
        if(shadowGenerator){
            shadowGenerator.getShadowMap().refreshRate = 0; // We need to compute it just once
            shadowGenerator.usePoissonSampling = true;
        }
        
    }

    //摇杆启动，人物开始根据摇杆移动
    private onVJStart(){
        // 绑定相应滚轮事件
        this.vj.addEventListener("vj_move", this.onVJMove, this);
    }
    private onVJMove(e){
        let angle = e.data;
        if( angle >= 337.5 || angle <= 22.5 ){
            this.moveForward = false;
            this.moveBackward = false;
            this.rotateLeft = false;
            this.rotateRight = true;
        }else if( angle > 22.5 && angle <= 67.5 ){
            this.moveForward = false;
            this.moveBackward = true;
            this.rotateLeft = false;
            this.rotateRight = true;
        }else if( angle > 67.5 && angle <= 112.5 ){
            this.moveForward = false;
            this.moveBackward = true;
            this.rotateLeft = false;
            this.rotateRight = false;
        }else if( angle > 112.5 && angle <= 157.5 ){
            this.moveForward = false;
            this.moveBackward = true;
            this.rotateLeft = true;
            this.rotateRight = false;
        }else if( angle > 157.5 && angle <= 202.5 ){
            this.moveForward = false;
            this.moveBackward = false;
            this.rotateLeft = true;
            this.rotateRight = false;
        }else if( angle > 202.5 && angle <= 247.5 ){
            this.moveForward = true;
            this.moveBackward = false;
            this.rotateLeft = true;
            this.rotateRight = false;
        }else if( angle > 247.5 && angle <= 292.5 ){
            this.moveForward = true;
            this.moveBackward = false;
            this.rotateLeft = false;
            this.rotateRight = false;
        }else if( angle > 292.5 && angle <= 337.5 ){
            this.moveForward = true;
            this.moveBackward = false;
            this.rotateLeft = false;
            this.rotateRight = true;
        }
    }
    //停止摇杆，人物停止移动
    private onVJEnd(){
        this.moveForward = false;
        this.moveBackward = false;
        this.rotateLeft = false;
        this.rotateRight = false;
        this.vj.removeEventListener("vj_move", this.onVJMove, this);
    }


    initEvents() {
        this.fireBtn.addEventListener( egret.TouchEvent.TOUCH_BEGIN, this.onTouchBegin_fireBtn, this);
        this.fireBtn.addEventListener( egret.TouchEvent.TOUCH_END, this.onTouchEnd_fireBtn, this);
        this.fireBtn.addEventListener( egret.TouchEvent.TOUCH_TAP, this.onClick_fireBtn, this);
    }

    removeEvents() {
        this.fireBtn.removeEventListener( egret.TouchEvent.TOUCH_BEGIN, this.onTouchBegin_fireBtn, this);
        this.fireBtn.removeEventListener( egret.TouchEvent.TOUCH_END, this.onTouchEnd_fireBtn, this);
        this.fireBtn.removeEventListener( egret.TouchEvent.TOUCH_TAP, this.onClick_fireBtn, this);
    }

    private onTouchBegin_fireBtn(e){
        // this.camera.detachControl(document.querySelectorAll("canvas")[0]);
    }

    private onTouchEnd_fireBtn(e){
        // this.camera.attachControl(document.querySelectorAll("canvas")[0],false);
    }

    private onClick_fireBtn(e){
        this.fire();
    }


    /**
     * 开火
     */
    private fire(){
        console.log('Boom')
        if(!this.tank || !this.isFireEnable) return;
        if(this.bulletPool.length > 0){
            this.bulletPool[this.bulletCount].rotation.copyFrom(this.tank.rotation);
            this.bulletPool[this.bulletCount].position.copyFrom(this.tank.position);
            this.bulletPool[this.bulletCount].forwards = new BABYLON.Vector3(this.tank.forward.x*this.tankSpeed*8,-0.98*this.tankSpeed,this.tank.forward.z*this.tankSpeed*8)
            this.bulletPool[this.bulletCount].position.y += 2;
            this.bulletPool[this.bulletCount].isBoomed = false;
            this.bulletPool[this.bulletCount].isVisible = true;
            if(this.tank.forwardRay.intersectsMeshes(this.fireCollisionArr).length > 0){
                this.bulletPool[this.bulletCount].hitTarget = this.tank.forwardRay.intersectsMeshes(this.fireCollisionArr)[0];
                this.bulletPool[this.bulletCount].hitPoint = this.tank.forwardRay.intersectsMeshes(this.fireCollisionArr)[0].pickedPoint;
                console.log(this.bulletPool[this.bulletCount].hitPoint);
            }
            // this.bulletPool[0].forwards.negate();
            if(this.bulletCount >= 2){
                this.bulletCount = 0;
            }else{
                // this.bulletCount++;
            }
        }
    }

    /** 
     * 让物体朝传入方向移动
     * 放在onEnterFrame里或者render里
    */
    public moveByVector(mesh:any, forward:any, speed?:number, isGravity?:boolean){
        let _speed:number = 1;
        let _gravity = 0
        if(speed){
            _speed = speed;
        }
        if(isGravity){
            _gravity = this.gravity;
        }
        mesh.position.x += forward.x * _speed;
        mesh.position.y += forward.y * _speed + _gravity;
        mesh.position.z += forward.z * _speed;
    }

}