import { props } from "../props";
import { getBlocks, resetCounter } from "./blockGen";
import { createBallItem } from "./factory/createBall";
import createCircle from "./factory/createCircle";
import createRegTriangle from "./factory/createRegTriangle";
import createSpecialRegTriangle from "./factory/createSpecialRegTriangle";
import createSpeialCircle from "./factory/createSpeialCircle";
import createSquare from "./factory/createSquare";
import { ACELE_DELAY, BALL_D, LADDER_NUMS, LEFT_GROUND, RIGHT_GROUND } from "./gameconsts";
import { Ball } from "./physics/Ball";
import Body from "./physics/Body";
import { Circle } from "./physics/Circle";
import { degToRad, radToDeg } from "./physics/Const";
import { RegTriangle } from "./physics/RegTriangle";
import Pool from "./Pool";
import { getBounce, getLadderGap, getLadderHPosition, getLadderPosition, isSpecialBody, isSpecialCircle, playSound, SoundType, getTextureByName } from "./utils";
import Effect from "./Effect";
import { Tween } from "./tween/Tween";

export default class PlayScene extends engine.Container {
    initEvents() {
        this.addEventListener(engine.Event.ENTER_FRAME, this.onEnterFrame, this);
        this.addEventListener(engine.MouseEvent.MOUSE_DOWN, this.onTouchBegin, this);
    }

    protected removeEvents() {
        this.removeEventListener(engine.MouseEvent.MOUSE_DOWN, this.onTouchBegin, this);
        this.removeEventListener(engine.Event.ENTER_FRAME, this.onEnterFrame, this);
    }

    /** 重力因子，默认1 */
    private gravity = 1;
    /** 物理时间缩放因子 */
    private timeSpeed = 1;

    /** 初始的球数 */
    private INIT_BALL_NUMS = window['INIT_BALL_NUMS'];
    /** 当前的球列表 */
    private balls: Ball[] = [];
    /** 对象池 */
    pool = new Pool();
    /** 砖块列表 */
    blocks: Body[] = [];
    /** 发射参考线 */
    line: engine.Sprite;
    shooter: engine.Sprite;

    /** 发射的球的数量，在碰到增加道具的时候数值应该增加 */
    private ballCountAll;
    /** 球的发射速度，默认30 */
    private velAmount = 25;
    /** 球的投射角度 */
    private directionAngle = 0;
    /** false代表正在发射，无法再次发射。所有的球回收后置为true 。默认true*/
    canShootTag = true;
    /** 已经回收的球的数量，只有全部回收了才可以继续发射。发射后置为0.默认0. */
    ballCount: number;


    //游戏数据
    data:any = {
        score:0,
        currentBallNums:5,

    };
    constructor(){
        super();
        // console.log("playscene--constructor");
        // this.pausegame();
        this.INIT_BALL_NUMS = window['INIT_BALL_NUMS'] = 1;
        this.initEvents();
        this.once(engine.Event.ADDED_TO_STAGE, this.initScene, this);
    }
    reset(){
        const blocks = this.blocks.filter(block=>!isSpecialBody(block)||block.type=="specialCircle");
        for(const block of blocks){
            this.removeEle(block,this.blocks);
            block.view.parent&&block.view.parent.removeChild(block.view);
            this.pool.recover(block.type,block);
        }
    }
    start(){
        this.gamescore = 0;
        this.currentBallNums = props.countDown;
        this.startGame();
    }
    pausegame(){
        this['pause'] = true;
    }
    resumegame(){
        this['pause'] = false;
    }
    get currentBallNums(){
        return this.data.currentBallNums;
    }
    set currentBallNums(num){
        this.data.currentBallNums = num;
        this.ballNums.text = num;
    }
    get gamescore(){
        return this.data.score;
    }
    set gamescore(num){
        this.data.score = num;
        this.score.text = num;

        engine.globalEvent.dispatchEvent('game-score-update', {
            score: num,
        });
    }
    initScene(){
        // console.log("initScene");
        // console.log(this.stage.width,this.stage.height);
        this.initUI();

        // this.startGame();

        engine.Tween.get(this['ele1'], { loop: true }).set({ rotation: 0 }).to({ rotation: -360 }, 3000);
        engine.Tween.get(this['ele2'], { loop: true }).set({ rotation: 0 }).to({ rotation: 360 }, 3000);

        createSpecialRegTriangle(this, 60, 250, 200, 55, 'specialRegTriangleTop');//2只鸡
        createSpecialRegTriangle(this, 750 - 60, 250, 200, -55, 'specialRegTriangleTop');//2只鸡
        createSpecialRegTriangle(this, 150, 90, 500, 4, 'specialRegTriangleTop');//顶部两根棍子 
        createSpecialRegTriangle(this, 750 - 150, 90, 500, -4, 'specialRegTriangleTop');//顶部两根棍子
        createSpecialRegTriangle(this, 230, 250, 40, 0, 'specialRegTriangleTop');//2个发射筒
        createSpecialRegTriangle(this, 750 - 230 + 5, 250, 40, 0, 'specialRegTriangleTop');//2个发射筒
        createSpecialRegTriangle(this, 170, 1271, 400, 52);//2块斜面地面
        createSpecialRegTriangle(this, 750 - 170, 1271, 400, -52);//2块斜面地面

        createSpecialRegTriangle(this, 232, 1351 - 3 - 5 - 3, 400, 30);//2块斜面地面2
        createSpecialRegTriangle(this, 750 - 232, 1351 - 3 - 5 - 3, 400, -30);//2块斜面地面2

        this.removeEventListener(engine.Event.ADDED_TO_STAGE,this.initScene,this);
    }

    score:engine.Label;
    ground:engine.Sprite;
    door:engine.Sprite;
    ele1:engine.Sprite;
    ele2:engine.Sprite;
    ballNums:engine.Label;
    initUI(){
        // console.log("initUI");
        this.score = new engine.Label();
        this.score.x = 118;
        this.score.y = 13;
        this.score.size = 24;
        this.score.fillColor = 0xffffff;
        this.addChild(this.score);

        this.ground = this.createSprite("地",0,1130);
        this.ground.visible = true;
        this.addChild(this.ground);

        this.door = this.createSprite("door",0,68);
        this.addChild(this.door);

        this.ele1 = this.createSprite("风扇",56,1130,20,21);
        this.addChild(this.ele1);

        this.ele2 = this.createSprite("风扇",698,1130,20,21);
        this.addChild(this.ele2);

        var ele1_t = this.createSprite("风扇1",54,1078);
        this.addChild(ele1_t);
        var ele2_t = this.createSprite("风扇1",693,1078);
        this.addChild(ele2_t);

        this.shooter = this.createSprite("炮",375,222,40,40);
        this.addChild(this.shooter);

        this.ballNums = new engine.Label();
        this.ballNums.x = 333;
        this.ballNums.y = 203;
        this.ballNums.width = 85;
        this.ballNums.height = 43;
        this.ballNums.textAlign = engine.TEXT_ALIGN.CENTER;
        this.ballNums.verticalAlign = engine.VERTICAL_ALIGN.MIDDLE;

        this.ballNums.size = 38;
        this.ballNums.fillColor = 0x00ff00;
        this.addChild(this.ballNums);

        this.line = this.createSprite("shootline",375,222,5,-74);
        this.addChild(this.line);

    }

    createSprite(tname:string,x,y,anchorx=0,anchory=0){
        var sp = new engine.Image(getTextureByName(tname));
        
        sp.x = x-anchorx;
        sp.y = y-anchory;

        sp.anchorX = anchorx;
        sp.anchorY = anchory;
        return sp;
    }
    //原来部分挂载在window下的变量
    setWindowData(){
        window['numsP'] = 0.5;
        window['INIT_BALL_NUMS']=1;

    }
    private startGame() {
        this.setWindowData();

        this['pause'] = false;
        this.reviveTag = 0;

        resetCounter();
        this.gamescore = 0;
        this.ballCountAll = this.INIT_BALL_NUMS
        this.currentBallNums = this.ballCountAll;


        this.balls.forEach(ball => ball.view.parent && ball.view.parent.removeChild(ball));
        this.balls = new Array();
        for (let i = 0; i < this.INIT_BALL_NUMS; i++) {
            const ball = createBallItem()
            this.addChild(ball.view);
            ball.view.y = this.shooter.y + 90+this.shooter.anchorY-ball.view.anchorY;
            ball.view.x = this.shooter.x+this.shooter.anchorX-ball.view.anchorX;
            ball.view.visible = false;
            this.balls.push(ball);
        }
        this.onShootEnd();

        // this['guide'].visible = localStorage.getItem('guide') !== '1';
        // this['guide'].once(engine.MouseEvent.MOUSE_DOWN, this.onGuildeTap, this);
    }

    onGuildeTap() {
        this['guide'].visible = false;
        localStorage.setItem('guide', '1');
    }

    private genBlocks() {
        const { blocksInfo, specialBallPosition } = getBlocks(this.ballCountAll);
        if (specialBallPosition > -1) {
            createSpeialCircle(this, getLadderHPosition(specialBallPosition), getLadderPosition(LADDER_NUMS - 1), 0);
        }

        for (const block of blocksInfo) {
            const { position, type, nums } = block;
            
            if (type == 1) {
                createSquare(this, getLadderHPosition(position), getLadderPosition(LADDER_NUMS - 1), nums);
            }
            else if (type == 2) {
                createRegTriangle(this, getLadderHPosition(position), getLadderPosition(LADDER_NUMS - 1), nums);
            }
            else {
                createCircle(this, getLadderHPosition(position), getLadderPosition(LADDER_NUMS - 1), nums);
            }
        }
    }

    onTouchMove(e: engine.MouseEvent) {
        const detaX = e.localX - 375;
        const detaY = e.localY - 0;
        if (detaY != 0) {
            let angle = Math.atan(detaX / detaY);
            if (angle > Math.PI / 180 * 75)
                angle = Math.PI / 180 * 75;
            if (angle < -Math.PI / 180 * 75)
                angle = -Math.PI / 180 * 75;
            this.line.rotation = this.shooter.rotation = -angle * radToDeg;
            this.directionAngle = angle;
            this.updateLine();
        }
    }

    updateLine() {
        this.line.scaleY = (1 - Math.abs(this.line.rotation) / 90 * 0.5);
    }

    onTouchEnd(e: engine.MouseEvent) {
        if (this['pause']) return;
        this.removeEventListener(engine.MouseEvent.MOUSE_MOVE, this.onTouchMove, this);
        this.canShootTag = false;
        this.ballCount = 0;
        this.ballShoot();
    }

    onTouchBegin(e: engine.MouseEvent) {
        if (this['pause']) return;
        if (!this.canShootTag) return;
        this.line.visible = true;
        //连线起始点到手指
        this.addEventListener(engine.MouseEvent.MOUSE_MOVE, this.onTouchMove, this);
        this.once(engine.MouseEvent.MOUSE_UP, this.onTouchEnd, this);

        const detaX = e.localX - 375;
        const detaY = e.localY - 0;

        if (detaY != 0) {
            let angle = Math.atan(detaX / detaY);
            if (angle > Math.PI / 180 * 75)
                angle = Math.PI / 180 * 75;
            if (angle < -Math.PI / 180 * 75)
                angle = -Math.PI / 180 * 75;
            this.line.rotation = this.shooter.rotation = -angle * radToDeg;
            this.directionAngle = angle;
            this.updateLine();
        }
    }

    // tslint:disable-next-line:cyclomatic-complexity
    private onEnterFrame() {//物理循环计算
        Tween.flush();
        for (const ball of this.balls) {
            if (ball.collideStatus == 3) { //回收阶段（不应用重力，不应用检测，以最快速度回到初始位置）
                //回收用Tween  onComplete后加，collideStatus=1；
            } else {
                //计算次数
                for (let s = 0; s < this.timeSpeed; s++) {
                    if (ball.collideStatus == 2) {//重力计算
                        ball.velocity.y += this.gravity;
                    }
                    ball.view.x += ball.velocity.x;
                    ball.view.y += ball.velocity.y;

                    // console.log("移动",ball.velocity.x,ball.velocity.y,ball.collideStatus);
                    //两壁碰撞检测，防左右墙壁穿透

                    if (ball.view.x < LEFT_GROUND) {
                        ball.velocity.x *= -1 * getBounce();
                        ball.view.x = LEFT_GROUND;//位置矫正
                        ball.collideStatus = 2;
                    } else if (ball.view.x+ball.view.width > RIGHT_GROUND) {
                        ball.velocity.x *= -1 * getBounce();
                        ball.view.x = RIGHT_GROUND-ball.view.width;//位置矫正
                        ball.collideStatus = 2;
                    }

                    if (ball.view.y > 1200) {
                        ball.velocity.x = 0;
                        ball.velocity.y = this.velAmount;
                        if (Math.random() > 0.5) {
                            ball.view.y = 300;
                            ball.view.x = 230-BALL_D/2;
                        } else {
                            ball.view.y = 300;
                            ball.view.x = 750 - 230 + 5 - BALL_D/2;
                        }
                    }

                    for (let j = this.blocks.length - 1; j >= 0; j--) {
                        const block: Body = this.blocks[j];
                        const normal = block.collideBall(ball);//对每个球和砖块进行碰撞检测
                        // console.log("碰撞检测",normal);
                        if (normal) {
                            //碰撞类型检测
                            if (block instanceof Circle) {//如果是圆形，那么要判断是否是特殊球
                                ball.velocity.symmetricFromNormalVector(normal);
                                ball.velocity.x *= getBounce();
                                ball.velocity.y *= getBounce();
                                ball.collideStatus = 2;
                                // if (block.type == 'specialCircle')
                                    // console.log('special circle')
                                // else
                                    // console.log('normal Circle')
                            }
                            else if (block instanceof RegTriangle) {
                                if (block.type == 'specialRegTriangle') {
                                    ball.collideStatus = 3;
                                    this.recoverPath(ball);
                                } else {
                                    ball.velocity.symmetricFromNormalVector(normal);
                                    ball.velocity.x *= getBounce();
                                    ball.velocity.y *= getBounce();
                                    ball.collideStatus = 2;
                                }
                            } else {
                                ball.velocity.symmetricFromNormalVector(normal);
                                ball.velocity.x *= getBounce();
                                ball.velocity.y *= getBounce();
                                ball.collideStatus = 2;
                            }

                            if (isSpecialBody(block)) {
                                //如果是其他特殊的，不处理
                                if (isSpecialCircle(block)) {//如果是特殊的圆，那么创建一个新的球，移除特殊圆
                                    this.ballCountAll++;
                                    playSound(SoundType.good);
                                    const newball = createBallItem()
                                    this.addChild(newball.view);
                                    newball.view.y = ball.view.y = block.y;
                                    newball.view.x = ball.view.x = block.x;
                                    newball.collideStatus = 2;
                                    this.balls.push(newball);
                                    ball.velocity.x = 5;
                                    newball.velocity.x = -5;
                                    ball.velocity.y = newball.velocity.y = -20;
                                    this.removeEle(block, this.blocks);
                                    this.removeChild(block.view);
                                    this.pool.recover(block.type, block);
                                }
                            } else {
                                this.shake(block);
                                this.gamescore+=props.addscore;
                                block.num = block.num - 1;
                                playSound(SoundType.bounce);
                                if (block.num <= 0) {
                                    new Effect(block, this);
                                    //回收加动效
                                    engine.Tween.removeTweens(block.view);
                                    block.view.alpha = 1;
                                    this.removeEle(block, this.blocks);
                                    this.removeChild(block.view);
                                    this.pool.recover(block.type, block);
                                }
                            }

                        }
                    }
                }

                // if(ball.view.visible){
                //     console.log("移动",ball.view.x,ball.view.y,
                //     ball.velocity.x,ball.velocity.y,
                //     ball.collideStatus);
                // }
                
            }
        }
    }


    private removeEle(e, arr) {
        const index = arr.indexOf(e);
        if (index >= 0) {
            arr.splice(index, 1)
        }
    }

    private shake(block) {
        // console.log("playScene震动1---------",block.view.bg.x,block.view.bg.y);
        var startx = -block.view.bg.anchorX;
        var starty = -block.view.bg.anchorY;

        block.view.bg.x = startx-2;
        block.view.bg.y = starty-2;
        // console.log("playScene震动2---------",block.view.bg.x,block.view.bg.y);
        Tween.to(block.view.bg, 1, {
            x: startx+2,
            y: starty+2,
            yoyo: 3,
            useFrame: true,
            onComplete: () => {
                block.view.bg.x = startx;
                block.view.bg.y = starty;
                // console.log("playScene震动3---------",block.view.bg.x,block.view.bg.y);
            }

        })
    }

    //回收路径
    private recoverPath(ball) {
        let time, targX;
        //右边
        if (ball.view.x > 375) {
            const detaX = (RIGHT_GROUND - ball.view.x) / 20;
            time = detaX < 1 ? 1 : detaX;
            targX = RIGHT_GROUND;// + BALL_D;
        }
        //左边
        else {
            const detaX = (ball.view.x - LEFT_GROUND) / 20;
            time = detaX < 1 ? 1 : detaX;
            targX = LEFT_GROUND - BALL_D;
        }
        ball.view.alpha = 0.80;
        Tween.to(ball.view, time, {
            x: targX,
            y: 1155,
            useFrame: true,
            onComplete: () => {
                ball.view.x = targX;
                playSound(SoundType.recover);
                Tween.to(ball.view, 20, {
                    y: 313.4 - 100,
                    useFrame: true,
                    onComplete: () => {
                        const middlex = 375;
                        const p0 = { x: ball.view.x, y: ball.view.y };
                        const p1 = { x: (ball.view.x + middlex) / 2, y: ball.view.y - 500 };
                        const p2 = { x: middlex, y: ball.view.y };
                        Tween.to(ball.view, 20, {
                            useFrame: true,
                            __xx__: 100,
                            onUpdate: (value) => {
                                ball.view.x = (1 - value) * (1 - value) * p0.x + 2 * value * (1 - value) * p1.x + value * value * p2.x;
                                ball.view.y = (1 - value) * (1 - value) * p0.y + 2 * value * (1 - value) * p1.y + value * value * p2.y;
                            },
                            onComplete: () => {
                                this.currentBallNums++;
                                
                                this.ballCount++;
                                ball.view.visible = false;
                                ball.view.alpha = 1;
                                if (this.ballCount == this.ballCountAll) {
                                    this.canShootTag = true;
                                    this.onShootEnd();
                                }
                            }
                        })
                        // ball.view.visible = false;
                        // Tween.to(ball.view, 15, {
                        //     x: this.line.x,
                        //     useFrame: true,
                        //     onComplete: () => {
                        //         this.data.currentBallNums++;
                        //         this.ballCount++;

                        //         if (this.ballCount == this.ballCountAll) {
                        //             this.canShootTag = true;
                        //             this.onShootEnd();
                        //         }
                        //     }
                        // })
                    }
                })
            }
        })
    }

    /**
     * 发射球
     */
    private ballShoot() {
        this.onShootBegin();
        //切分速度向量
        const speedX = this.velAmount * Math.sin(this.directionAngle);
        const speedY = this.velAmount * Math.cos(this.directionAngle);
        
        let count = 0;
        const timer = setInterval(() => {
            count++;
            playSound(SoundType.shoot);
            
            this.currentBallNums--;

            if (this.data.currentBallNums < 0)
                this.currentBallNums = 0;
            if (count == this.ballCountAll) {
                clearInterval(timer);
                this['aceleTimer'] = setTimeout(() => {
                    this.timeSpeed = 3;
                    this['aceleTimer'] = 0;
                }, ACELE_DELAY);
            }
            this.balls[count - 1].collideStatus = 1;
            this.balls[count - 1].velocity.x = speedX;
            this.balls[count - 1].velocity.y = speedY;

            const r = 90;
            const rad = (this.shooter.rotation * degToRad);
            this.balls[count - 1].view.x = this.shooter.x - Math.sin(rad) * r+this.shooter.anchorX-this.balls[count - 1].view.anchorX;
            this.balls[count - 1].view.y = this.shooter.y + Math.cos(rad) * r+this.shooter.anchorY-this.balls[count - 1].view.anchorY;

            this.balls[count - 1].view.visible = true;
        }, 100)
    }

    onShootBegin() {
        this.line.visible = false;
    }

    onShootEnd() {
        if (this['aceleTimer']) clearTimeout(this['aceleTimer']);
        this.timeSpeed = 1;
        this.line.visible = false;
        
        this.currentBallNums = this.ballCountAll;

        const blocks = this.blocks.filter(block => isSpecialCircle(block) || !isSpecialBody(block));
        let failed = false;
        blocks.forEach(block => {
            // if (block.ladderNums >= 1) {
            if (block.ladderNums >= 9) {
                failed = true;
            }
        });

        if (failed) {
            this.checkGameOver();
        } else {
            blocks.forEach(block => {
                block.y -= getLadderGap();
                block.ladderNums++;
                if (block.ladderNums >= 9) {
                    engine.Tween.get(block.view, { loop: true })
                        .to({ alpha: 0 }, 1000 / 6)
                        .to({ alpha: 1 }, 1000 / 6)
                    // .to({ rotation: block.view.rotation + 15 }, 1000 / 6)
                    // .to({ rotation: block.view.rotation }, 1000 / 6)
                    // Tween.to(block.view, 10, { useFrame: true, yoyo: true, rotation: block.view.rotation+ })
                }
            });

            this.genBlocks();
        }
    }

    reviveTag = 0;
    checkGameOver() {
        this['pause'] = true;
        const num = window['revivePlugId'];

        // if (this.reviveTag || userCredits < costCredits) { //已经复活过了或者钱不够直接死
            this.gameOver();
        // } 
        // else {
        //     const panel = PanelCtrl.instance.show(ModuleTypes.RELIVE_PANEL);
        //     panel.once('onSure', () => {
        //         this.relive();
        //         this.reviveTag = 1;
        //     }, this);
        //     panel.once('onCancel', () => {
        //         this.gameOver();
        //     }, this);
        // }
    }

    relive() {
        this['pause'] = false;

        const blocks = this.blocks.filter(block => (isSpecialCircle(block) || !isSpecialBody(block)) && block.ladderNums >= 5);
        for (const block of blocks) {
            this.gamescore += block.num;
            this.removeEle(block, this.blocks);
            block.view.parent && this.removeChild(block.view);
            engine.Tween.removeTweens(block.view);
            block.view.alpha = 1;
            this.pool.recover(block.type, block);
        }
    }

    gameOver() {
        console.log("游戏结束");
        engine.globalEvent.dispatchEvent('game-over', {
            
        });
        // Loading.instace.show();
        // submit((success) => {
        //     Loading.instace.hide();
        //     if (!success) return;
        //     let panel: Panel;
        //     const getOrderStatus = DataManager.ins.getCustomOrderStatusData
        //     if (getOrderStatus.lottery) {
        //         panel = PanelCtrl.instance.show(ModuleTypes.PRIZE_PANEL)
        //     } else {
        //         panel = PanelCtrl.instance.show(ModuleTypes.NO_PRIZE_PANEL)
        //     }
        // }, this.data.score)
    }

    get skinKey() { return 'Play' }

    destroy() {
        super.destroy();
    }
}