import submit from "../../libs/new_tw/ctrls/submit";
import Panel from "../../libs/new_wx/components/Panel";
import Scene from "../../libs/new_wx/components/Scene";
import PanelCtrl from "../../libs/new_wx/ctrls/panelCtrl";
import showAlertPanel from "../../libs/new_wx/ctrls/showAlertPanel";
import { ModuleTypes } from "../../libs/new_wx/types/sceneTypes";
import { DataManager } from "../../libs/tw/manager/DataManager";
import { Tween } from "../tween/Tween";
import { createBallItem } from "./factory/createBall";
import createCircle from "./factory/createCircle";
import createRegTriangle from "./factory/createRegTriangle";
import createSpecialRegTriangle from "./factory/createSpecialRegTriangle";
import createSquare from "./factory/createSquare";
import { BALL_D, LEFT_GROUND, RIGHT_GROUND, LADDER_START, LADDER_END, LADDER_H_NUMS, LADDER_NUMS, ACELE_DELAY } 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 { isSpecialBody, getLadderPosition, getLadderHPosition, getBounce, isSpecialCircle, getLadderGap } from "./utils";
import { getBlocks, resetCounter, getCounter } from "./blockGen";
import createSpeialCircle from "./factory/createSpeialCircle";
import { NetManager } from "../../libs/tw/manager/NetManager";
import Effect from "../Effect";
import { toggleSound, playSound, SoundType, playBg } from "../soundCtrl";
import Loading from "../../libs/new_wx/components/Loading";

export default class PlayScene extends Scene {
    initEvents() {
        this.stage.addEventListener(egret.Event.ENTER_FRAME, this.onEnterFrame, this);
        this.stage.addEventListener(egret.TouchEvent.TOUCH_BEGIN, this.onTouchBegin, this);
        this['musicOn'].addEventListener(egret.TouchEvent.TOUCH_BEGIN, this.onTouchTap_musicOn, this);
        this['musicOff'].addEventListener(egret.TouchEvent.TOUCH_BEGIN, this.onTouchTap_musicOff, this);
    }

    protected removeEvents() {
        this.stage.removeEventListener(egret.TouchEvent.TOUCH_BEGIN, this.onTouchBegin, this);
        this.stage.removeEventListener(egret.Event.ENTER_FRAME, this.onEnterFrame, this);
    }

    onTouchTap_musicOn(e: egret.TouchEvent) {//关闭
        e.stopPropagation();
        this['musicOn'].visible = !this['musicOn'].visible;
        this['musicOff'].visible = !this['musicOff'].visible;
        playSound(SoundType.click);
        toggleSound();
    }

    onTouchTap_musicOff(e: egret.TouchEvent) {//开启
        e.stopPropagation();
        toggleSound();
        this['musicOn'].visible = !this['musicOn'].visible;
        this['musicOff'].visible = !this['musicOff'].visible;
    }

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

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

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

    async start(data?) {
        super.start();
        playBg();
        this['musicOn'].visible = true;
        this['musicOff'].visible = false;
        this.startGame();

        egret.Tween.get(this['ele1'], { loop: true }).set({ rotation: 0 }).to({ rotation: -360 }, 3000);
        egret.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
    }

    private startGame() {
        this['pause'] = false;
        this.reviveTag = 0;
        NetManager.ins.getCredits(() => { });
        resetCounter();
        this.data.score = 0;
        this.ballCountAll = this.INIT_BALL_NUMS
        this.data.currentBallNums = this.ballCountAll;
        this.balls.forEach(ball => ball.view.parent && ball.view.parent.removeChild(ball));

        for (let i = 0; i < this.INIT_BALL_NUMS; i++) {
            const ball = createBallItem()
            this.addChild(ball.view);
            ball.view.y = this.shooter.y + 90;
            ball.view.x = this.shooter.x;
            ball.view.visible = false;
            this.balls.push(ball);
        }

        this.onShootEnd();

        this['guide'].visible = localStorage.getItem('guide') !== '1';
        this['guide'].once(egret.TouchEvent.TOUCH_BEGIN, this.onGuildeTap, this);
    }

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

    private genBlocks() {
        const { blocksInfo, specialBallPosition } = getBlocks(this.ballCountAll);
        console.log(blocksInfo, specialBallPosition);
        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: egret.TouchEvent) {
        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: egret.TouchEvent) {
        this.stage.removeEventListener(egret.TouchEvent.TOUCH_MOVE, this.onTouchMove, this);
        this.canShootTag = false;
        this.ballCount = 0;
        this.ballShoot()
    }

    onTouchBegin(e: egret.TouchEvent) {
        if (this['pause']) return;
        if (!this.canShootTag) return;
        this.line.visible = true;
        //连线起始点到手指
        this.stage.addEventListener(egret.TouchEvent.TOUCH_MOVE, this.onTouchMove, this);
        this.stage.once(egret.TouchEvent.TOUCH_END, 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;

                    //两壁碰撞检测，防左右墙壁穿透
                    if (ball.view.x < LEFT_GROUND) {
                        ball.velocity.x *= -1 * getBounce();
                        ball.view.x = LEFT_GROUND;//位置矫正
                        ball.collideStatus = 2;
                    } else if (ball.view.x > RIGHT_GROUND) {
                        ball.velocity.x *= -1 * getBounce();
                        ball.view.x = RIGHT_GROUND;//位置矫正
                        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;
                        } else {
                            ball.view.y = 300;
                            ball.view.x = 750 - 230 + 5;
                        }
                    }

                    for (let j = this.blocks.length - 1; j >= 0; j--) {
                        const block: Body = this.blocks[j];
                        const normal = block.collideBall(ball);//对每个球和砖块进行碰撞检测
                        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 {
                                console.log(block.type);
                                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.data.score++;
                                block.num = block.num - 1;
                                playSound(SoundType.bounce);
                                if (block.num <= 0) {
                                    new Effect(block, this);
                                    //回收加动效
                                    this.removeEle(block, this.blocks);
                                    this.removeChild(block.view);
                                    this.pool.recover(block.type, block);
                                }
                            }

                        }
                    }
                }
            }
        }
    }


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

    private shake(block) {
        block.view.bg.x = -2;
        block.view.bg.y = -2;
        Tween.to(block.view.bg, 1, {
            x: 2,
            y: 2,
            yoyo: 3,
            useFrame: true,
            onComplete: () => {

            }

        })
    }

    //回收路径
    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);
                // console.log( this.line.y - this.line.anchorOffsetY + BALL_D / 2)
                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;
                                console.log(value);
                            },
                            onComplete: () => {
                                this.data.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.data.currentBallNums--;
            if (this.data.currentBallNums < 0)
                this.data.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.balls[count - 1].view.y = this.shooter.y + Math.cos(rad) * r;
            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.data.currentBallNums = this.ballCountAll;

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

        if (failed) {
            console.log('gg');
            this.checkGameOver();
        } else {
            blocks.forEach(block => {
                block.y -= getLadderGap();
                block.ladderNums++;
            });
            this.genBlocks();
        }
    }

    reviveTag = 0;
    checkGameOver() {
        this['pause'] = true;
        const num = window['revivePlugId'];
        // console.log(DataManager.ins.getPrizeInfoList[num])
        const costCredits = DataManager.ins.getPrizeInfoList[num].creditsPrice || 0;
        const userCredits = DataManager.ins.getCreditsData.consumerCredits || 0;
        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.data.score += block.num;
            this.removeEle(block, this.blocks);
            block.view.parent && this.removeChild(block.view);
            this.pool.recover(block.type, block);
        }
    }

    gameOver() {
        Loading.instace.show();
        submit((success) => {
            Loading.instace.hide();
            if (!success) return;
            let panel: Panel;
            if (DataManager.ins.gameGetSubmitResultData.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();
    }
}