import { asyncDelay, onHomeworkFinish, RandomInt } from "../script/util";
import { MyCocosSceneComponent } from "../script/MyCocosSceneComponent";
import Game, { FISH_OUT, GAME_STATE, Option } from "./tool/Game";
import pg from "./tool/pg";

const { ccclass, property } = cc._decorator;

export function getDegree(p1, p2) {
    let vector = p2.sub(p1);
    let degree = Math.atan(vector.y / vector.x) / Math.PI * 180;
    if (vector.x >= 0) {
        if (vector.y < 0) {
            degree += 360;
        }
    } else {
        if (vector.y > 0) {
            degree += 180;
        } else {
            degree = 180 + degree;
        }
    }
    return -(-degree + 90);//角度计算方法
}

let win: any = window;
let courseware = win.courseware;
enum GUN_STATE {
    WAIT = 1,
    SHUT_MIDDLE,
    SHUT_LEFT,
    SHUT_RIGHT
}
enum FISH_STATE {
    NORMAL = 1,
    BREAK,
    FALL,
}
enum TIPS_STATE {
    GOOD = 1,
    TRY,
    COM,
}
@ccclass
export default class SceneComponent extends MyCocosSceneComponent {

    addPreloadImage() {
        // TODO 根据自己的配置预加载图片资源
        this._imageResList.push(...this.data.questions.map(question => {
            return { url: question.image };
        }));
    }

    addPreloadAudio() {
        // TODO 根据自己的配置预加载音频资源
        this._audioResList.push({ url: this.data.questionTextAudio });
        this._audioResList.push({ url: this.data.bgAudio });
        this._audioResList.push(...this.data.questions.map(question => {
            return { url: question.audio };
        }));
    }

    addPreloadAnima() {

    }

    onLoadEnd() {
        cc.macro.ENABLE_MULTI_TOUCH = false;//禁用多指操作
        // TODO 加载完成后的逻辑写在这里, 下面的代码仅供参考
        this.initData();
        this.initView();
        this.initEvent();
    }
    protected onDestroy(): void {
        pg.event.clear();
    }

    @property(cc.Node)
    layout_game: cc.Node = null;
    @property(cc.Node)
    balloon_item: cc.Node = null;
    @property(cc.Node)
    layout_balloon: cc.Node = null;
    @property(cc.Node)
    jian_item: cc.Node = null;
    @property(cc.Node)
    gong_item: cc.Node = null;
    @property(cc.Node)
    layout_start: cc.Node = null;
    @property(cc.Node)
    layout_finish: cc.Node = null;
    @property(cc.Node)
    gong_word: cc.Node = null;

    private tryData: Array<Option>;
    private timeSecond;
    private touching;
    private viewFishs: Option[];
    private touchFishs: Option[];
    private fishs: cc.Node[];
    private list: Option[];
    initData() {
        Game.getIns().init(this.data);
        Game.getIns().reset();
        this.tryData = [];
        // 所有全局变量 默认都是null 
        this.timeSecond = 0;
    }
    private audioId: any;
    async initView() {
        cc.audioEngine.stopAllEffects();
        this.initStart();
        // this.gameStart(false);
    }
    initEvent() {
        // this.btn_laba.on(cc.Node.EventType.TOUCH_END, this.playLaba, this);
        // this.btn_record.on(cc.Node.EventType.TOUCH_END, this.onTouchRecord, this);
        // this.btn_recording.on(cc.Node.EventType.TOUCH_END, this.onTouchRecordEnd, this);
        let btn_again = cc.find("layout_finish/btn_again", this.node);
        let btn_next = cc.find("layout_finish/btn_next", this.node);
        btn_again.on(cc.Node.EventType.TOUCH_END, this.onAgain, this);
        btn_next.on(cc.Node.EventType.TOUCH_END, this.onNext, this);
        let btn_touch = cc.find("btn_touch", this.layout_game);
        btn_touch.on(cc.Node.EventType.TOUCH_END, this.onLayoutTouch, this);
        btn_touch.on(cc.Node.EventType.TOUCH_START, this.onLayoutStart, this);
        btn_touch.on(cc.Node.EventType.TOUCH_MOVE, this.onLayoutMove, this);
        cc.find("gong_touch", this.layout_game).on(cc.Node.EventType.TOUCH_END, this.onGongBullet, this);
        pg.event.on("game_start", () => {
            this.gameStart();
        });
        pg.event.on("game_time_over", () => {
            this.checkRoundEnd();
        });
        pg.event.on("mouse_06_num_game_end", () => {
            // if (Game.getIns().dispelCount <= 0) {
            //     // pg.event.emit("check_next_question");
            //     this.checkRoundEnd();
            // }
        });
        pg.event.on("bullet_reset_pos", () => {
            const gameCanvas = cc.view.getVisibleSize();
            let gameWidthX = gameCanvas.width;
            let gameHeightX = gameCanvas.height
            this.touching = false;
            this.gong_item.angle = 0;
            this.jian_item.y = -gameHeightX / 2 - 30;
        });
    }
    private resetGame() {
        cc.audioEngine.stopAllEffects();
        this.playLocalAudio("again");
        this.initData();
        pg.event.emit("mouse_06_num", Game.getIns().getRightNum());
        this.gameStart();
    }
    private onAgain() {
        this.layout_finish.active = false;
        this.resetGame();
    }
    private onNext() {
        const middleLayer = cc.find('middleLayer');
        if (middleLayer) {
            const mc = middleLayer.getComponent('middleLayer');
            // // 切换下一页
            mc.goNextPage();
        }
    }
    private onLayoutTouch(e) {
        this.gongAngle(e)
    }
    private onLayoutStart(e) {
        this.gongAngle(e)
    }
    private onLayoutMove(e) {
        this.gongAngle(e)
    }
    private gongAngle(e) {
        this.jian_item.angle = 0;
        let point = e.touch.getLocation();
        let jp = cc.v2(point.x - this.layout_balloon.width / 2, point.y - this.layout_balloon.height / 2);
        let lefP = cc.v2(0, -542);
        let angle = this.getDegree(lefP, jp);
        if (angle > 80) angle = 80;
        if (angle < -80) angle = -80;
        this.gong_item.angle = angle;
        this.jian_item.angle = angle;
    }
    private onGongBullet() {
        if (this.touching) return;
        this.touching = true;
        let angle = this.jian_item.angle;
        this.playLocalAudio("gShow");
        pg.event.emit("bullet_shoot", angle);

    }

    private gameOver() {
        Game.getIns().state = GAME_STATE.OVER;
        let data: any = {};
        data.total = Game.getIns().total;
        data.right = Game.getIns().player.right;
        data.scores = Game.getIns().player.voices;
        data.stone = Math.floor(10 * data.right / data.total);
        this.log("total: " + data.total + "      right: " + data.right + "   stone: " + data.stone);
        onHomeworkFinish(data)
    }

    gameStart(showBack = true) {
        this.touching = true;
        this.count = 0;
        this.fishs = [];
        this.viewFishs = [];
        this.lastCount = null;
        this.touchFishs = [];
        this.layout_balloon.removeAllChildren();
        this.showEnter().then(() => {
            this.showQuestion();
        });
    }


    private showEnter() {
        const gameCanvas = cc.view.getVisibleSize();
        let gameWidthX = gameCanvas.width;
        let gameHeightX = gameCanvas.height
        let question = Game.getIns().getCurrentPage();
        this.gong_word.getComponent(cc.Label).string = question.text;
        this.gong_word.scale = 2;
        this.gong_word.opacity = 0;
        this.gong_item.y = -900;
        this.jian_item.y = -900;
        return new Promise((resolve, reject) => {
            cc.tween(this.gong_item).to(0.5, { y: -gameHeightX / 2 - 30 })
                .call(() => {
                    cc.tween(this.jian_item).to(0.5, { y: -gameHeightX / 2 - 30 }).start();
                    pg.audio.playAudioByUrl(question.audio);
                    cc.tween(this.gong_word).to(0.3, { opacity: 255, scale: 1 })
                        .call(() => {
                            this.touching = false;
                            return resolve("");
                        })
                        .start();
                })
                .start();
        });
    }


    private showQuestion(show = true) {
        Game.getIns().state = GAME_STATE.RUNNING;
        let question = Game.getIns().getCurrentPage();
        let list = question.optionList.concat();
        list = JSON.parse(JSON.stringify(list));
        list.sort((A, B) => { return Math.random() < 0.5 });
        this.list = list;
    }

    private lastCount: number;
    getFishByCount(count) {
        if (count <= this.lastCount) return null;
        if (!this.list) return;
        if (this.list.length == this.touchFishs.length) {
            Game.getIns().state = GAME_STATE.OVER;
            return pg.event.emit("game_time_over");
        }
        this.lastCount = count;
        let list = this.list.filter((li) => {
            return this.viewFishs.every(v => v.id != li.id) && this.touchFishs.every(t => t.id != li.id);
        });
        if (list.length == 0) return null;
        let data = JSON.parse(JSON.stringify(list[count % list.length]));
        data.fish.isLeft = Math.random() < 0.5;
        let item_base = this.balloon_item;
        let item = cc.instantiate(item_base);
        this.updateFish(item, data);
        this.viewFishs.push(data);
        return item;
    }


    get fishLen() {
        if (!this.fishs) return 999;
        let arr = this.fishs.filter(item => {
            let data: Option = item.data;
            return data.fish.isOut == FISH_OUT.RUNNING;
        })
        this.fishs = arr;
        return this.fishs.length;
    }

    //根据两点获取距离
    private getDistance(p1, p2) {
        let temp = p1.sub(p2);
        let dis = Math.abs(temp.mag());
        return dis;
    }
    private getDistances(p1, p2) {
        //转换世界坐标查看距离
        let ps2 = p2.convertToWorldSpaceAR(cc.v2(0, 0));
        let ps1 = p1.convertToWorldSpaceAR(cc.v2(0, 0));
        let temp = ps1.sub(ps2);
        let dis = Math.abs(temp.mag());
        return dis;
    }
    private count: number;
    update(dt) {
        if (Game.getIns().state != GAME_STATE.RUNNING) return;
        // if (this.touching) return;
        if (this.fishLen < 6) this.count++;
        let fish = this.getFishByCount(this.count);
        if (fish) this.fishs.push(fish);
        this.isHitBalloon();
    }
    private isHitBalloon() {
        if (!this.touching) return;
        this.fishs.forEach((item) => {
            let dis = this.getDistances(this.jian_item, item);
            if (dis < 160 && item.data.fish.isOut == FISH_OUT.RUNNING) {
                if (item.x < 200 && item.x > -200 && item.y < -300) return;
                pg.event.emit("stop_shoot");
                cc.Tween.stopAllByTarget(item);
                let state = item.data.right ? FISH_STATE.BREAK : FISH_STATE.FALL;
                item.data.fish.isOut = FISH_OUT.OUT;
                pg.event.emit("bullet_reset_pos");
                let audio = item.data.right ? "right" : "error";
                this.playLocalAudio(audio);
                this.updataBallonState(item, state).then(() => {
                    this.touchFishs.push(item.data);
                    this.viewFishs = this.viewFishs.filter(v => v.id != item.data.id);
                    item.data.right && pg.event.emit("mouse_06_add");
                });
            }

        })
    }
    private updataBallonState(item: cc.Node, state: FISH_STATE) {
        return new Promise((resolve, reject) => {
            switch (state) {
                case FISH_STATE.NORMAL:
                    resolve('');
                    break;
                case FISH_STATE.BREAK:
                    pg.view.visible(pg.view.find(item, 'layout'), false);
                    pg.view.visible(pg.view.find(item, 'bg'), false);
                    pg.view.visible(pg.view.find(item, 'bomb'), true);
                    this.schedule(() => {
                        item.active = false;
                    }, 0.4);
                    resolve('');
                    break;
                case FISH_STATE.FALL:
                    let x = item.x;
                    cc.tween(item).to(0.1, { x: x - 10 }).to(0.1, { x: x + 10 })
                        .to(0.1, { x: x - 10 }).to(0.1, { x: x + 10 })
                        .to(0.3, { y: -1500 })
                        .call(() => {
                            item.active = false;
                            resolve('');
                        })
                        .start();
                    break;
            }
        });
    }

    private fishCount: number;
    private lastY: number;
    updateFish(item, data: Option) {
        // pg.view.touchOn(item, this.onTouchItem, this);
        if (!this.fishCount) this.fishCount = 0;
        let id = this.fishCount % 6;
        this.fishCount++;
        // let res = pg.view.find(item, 'res');

        // pg.view.visible(pg.view.find(item, 'img_normal'), true);
        // pg.view.visible(pg.view.find(item, 'img_fall'), false);
        // pg.view.visible(pg.view.find(item, 'light'), false);
        item.active = true;
        let i = Math.ceil(Math.random() * 7);
        let bg = cc.find("bg/balloon" + i, item);
        bg.active = true;
        let word_bg = cc.find("layout/word_bg", item);
        if (data.type == "txt") {
            word_bg.active = true;
            let word = cc.find("word", word_bg);
            word.getComponent(cc.Label).string = data.txt;
        } else {
            let pic = cc.find("layout/pic", item);
            pg.view.setNetImg(pic, data.picUrl, { w: 247, h: 170 });
            pic.active = true;
            if (data.txt != "") {
                word_bg.active = true;
                let word = cc.find("word", word_bg);
                word.getComponent(cc.Label).string = data.txt;
            }
        }

        let pos = [-794, -480, -160, 155, 473, 798];
        item.parent = this.layout_balloon;
        item.data = data;
        data.fish.node = item;
        //x y   起始点 和终点  进行  随机
        cc.Tween.stopAllByTarget(item);
        //左往右
        item.x = pos[id];//-1334 / 2 + Math.random() * 1334;
        item.y = -(700 + Math.random() * 400);//
        cc.tween(item).to(4 + Math.random() * 5, { y: 1000 }).call(() => {
            data.fish.isOut = FISH_OUT.OUT;
            this.viewFishs = this.viewFishs.filter(v => v.id != data.id);
        }).start();
    }








    //根据两点获取角度
    getDegree(p1, p2) {
        let vector = p2.sub(p1);
        let degree = Math.atan(vector.y / vector.x) / Math.PI * 180;
        if (vector.x >= 0) {
            if (vector.y < 0) {
                degree += 360;
            }
        } else {
            if (vector.y > 0) {
                degree += 180;
            } else {
                degree = 180 + degree;
            }
        }
        return -(-degree + 90) || 0;//角度计算方法
    }
    private checkRoundEnd() {
        Game.getIns().addPage();
        if (!Game.getIns().getCurrentPage()) {
            // this.gameOver();
            this.showFind();
        } else {
            this.playLocalAudio("next");
            this.gameStart();
        }

    }

    private showFind() {
        let layout_finish = cc.find("layout_finish", this.node);
        layout_finish.active = true;
        let finish_db = cc.find("finish_db", layout_finish);
        let btn_again = cc.find("btn_again", layout_finish);
        let btn_next = cc.find("btn_next", layout_finish);
        finish_db.active = true;
        btn_again.active = false;
        btn_next.active = false;
        finish_db.getComponent(dragonBones.ArmatureDisplay).playAnimation("newAnimation", 1);
        this.playLocalAudio("finish").then(() => {
            finish_db.active = false;
            btn_again.active = true;
            btn_next.active = true;
        });
    }

    private initStart() {
        this.layout_start.active = true;
        cc.find("layout_top/label_title", this.node).getComponent(cc.Label).string = Game.getIns().title;
        pg.event.emit("mouse_06_num", Game.getIns().getRightNum());
        let start_ske = cc.find("layout_start/start_ske", this.node);
        pg.load.loadDB(start_ske, { ske: Game.getIns().aniEnter.ske.url, tex: Game.getIns().aniEnter.tex.url, png: Game.getIns().aniEnter.png.url }).then((animationName) => {
            if (animationName && animationName != "") {
                let db = start_ske.getComponent(dragonBones.ArmatureDisplay);
                let anis = db.getAnimationNames(db.armatureName);
                db.playAnimation(anis[0], 0);
                cc.tween(start_ske).by(1, { x: -500 }).delay(1).call(() => {
                    pg.audio.playAudioByUrl(Game.getIns().startAudio).then(() => {
                        cc.tween(start_ske).delay(1).by(1, { x: 500 }).call(() => {
                            this.layout_start.active = false;
                            this.gameStart();
                        }).start();
                    });
                }).start();
            } else {
                this.layout_start.active = false;
                this.gameStart();
            }
        })
    }


    playLocalAudio(audioName) {
        const audio = cc.find(`Canvas/res/audio/${audioName}`).getComponent(cc.AudioSource);
        return new Promise((resolve, reject) => {
            const id = cc.audioEngine.playEffect(audio.clip, false);
            cc.audioEngine.setFinishCallback(id, () => { resolve(id); });
        })
    }

    async showOneFirework(pos, parentNode, nodeList) {

        for (let i = 0; i < 3; i++) {
            this.showFirework(pos, parentNode, nodeList, 200, 200, 25);
            await asyncDelay(0.1);
        }
    }

    showFirework(pos, parentNode, nodeList, width = 200, height = 500, number = 30) {
        for (let i = 0; i < number; i++) {
            const quad = this.createQuads(pos, parentNode, nodeList);
            const targetX = RandomInt(width / 2, -width / 2);
            const targetY = RandomInt(height);

            cc.tween(quad)
                .by(0.5, { x: targetX })
                .by(3, { x: targetX * 2 })
                .start();

            cc.tween(quad)
                .by(0.5, { y: targetY }, { easing: 'quadOut' })
                .to(4, { y: -parentNode.height * 2 }, { easing: 'quadIn' })
                .removeSelf()
                .start();

            cc.tween(quad)
                .delay(1)
                .to(0.5 + 1 * Math.random(), { opacity: 0 })
                .start();
        }
    }

    createQuads(pos, parentNode, nodeList) {
        const quadBase = cc.instantiate(nodeList[RandomInt(nodeList.length)]);
        // console.log('nodeList', nodeList);
        // console.log('quadBase', quadBase);
        quadBase.x = pos.x;
        quadBase.y = pos.y + 30;
        quadBase.z = pos.z;
        quadBase.angle = RandomInt(180);
        quadBase.parent = parentNode;

        const quad = quadBase.getChildByName('quad');
        quad.x = 0;
        quad.y = 0;
        quad.angle = RandomInt(180);

        const paper = quad.getChildByName('paper');
        paper.scaleX = Math.random() * 0.8 + 0.2;
        paper.scaleY = Math.random() * 0.8 + 0.2;

        quadBase.scaleX = Math.random();
        cc.tween(quadBase)
            .to((1 - quadBase.scaleX) * 0.3, { scaleX: 1 })
            .call(() => {
                const time = Math.random() * 0.2;
                cc.tween(quadBase)
                    .to(0.1 + time, { scaleX: -1 })
                    .to(0.1 + time, { scaleX: 1 })
                    .union()
                    .repeatForever()
                    .start();
            })
            .start();


        return quadBase;
    }
}


/**
 * NGT06分类气球

1. 发射过程，不是点击气球，而是点击弓，然后释放弓，按角度发射箭；
2. 弓应该是旋转的，我给过示意图；
3. 弓上的字体需要加粗，看效果图；
4. 箭的速度太慢了，看我给的视频例子，这个速度就好；
5. 箭发出应该有音效；
6. 气球爆炸的图片停留的时间太久的，停留0.5秒，一闪而过就好；
7. 气球总是扎堆，需要左右分离一些留一些距离；（不是从左侧扎堆，就是从右侧扎堆）
 */