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

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,
    FLY,
    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.audioUrl };
        }));
    }

    addPreloadAnima() {

    }

    onLoadEnd() {
        // TODO 加载完成后的逻辑写在这里, 下面的代码仅供参考
        this.initData();
        this.initView();
        this.initEvent();
        this.gameStart();
        this.showBgLightAction();
    }
    protected onDestroy(): void {
        pg.event.clear();
    }



    @property(cc.Node)
    layout_game: cc.Node = null;
    @property(cc.Node)
    btn_audio_off: cc.Node = null;
    @property(cc.Node)
    btn_audio_on: cc.Node = null;
    @property(cc.Node)
    btn_laba: cc.Node = null;
    @property(cc.Node)
    ship: cc.Node = null;
    @property(cc.Node)
    item_text: cc.Node = null;
    @property(cc.Node)
    item_text2: cc.Node = null;
    @property(cc.Node)
    item_pic: cc.Node = null;
    @property(cc.Node)
    layout_card: cc.Node = null;

    private touchData: Option;
    private tryData: Array<Option>;
    private countDown: number = 999999;
    private timeCount: number;
    private startCount = 15;
    private isPlayBgAudio: boolean;


    private count: number;
    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 = [];
        this.touchData = null;
        this.isPlayBgAudio = true;
        // 所有全局变量 默认都是null 
    }
    private audioId: any;

    async initView() {
        cc.audioEngine.stopAllEffects();


        if (Game.getIns().title) {
            cc.find("layout_info/bg_title/title", this.node).getComponent(cc.Label).string = Game.getIns().title;
        }
        // if (Game.getIns().bgAudio || Game.getIns().bgAudio != "") {
        //     this.btn_audio_on.active = true;
        // }
    }
    initEvent() {
        this.btn_audio_off.on(cc.Node.EventType.TOUCH_END, this.onAudioOff, this);
        this.btn_audio_on.on(cc.Node.EventType.TOUCH_END, this.onAudioOn, this);
        this.btn_laba.on(cc.Node.EventType.TOUCH_END, this.playLaba, this);
        // cc.find("btn_touch", this.layout_game).on(cc.Node.EventType.TOUCH_END, this.onLayoutTouch, this);
        let self = this;
        pg.event.on("game_start", () => {
            self.gameStart();
        });

        cc.find("layout_top", this.layout_game).on(cc.Node.EventType.TOUCH_END, () => {
            this.updateShipPos(360);
        }, this);
        cc.find("layout_mid", this.layout_game).on(cc.Node.EventType.TOUCH_END, () => {
            this.updateShipPos(0);
        }, this);
        cc.find("layout_bot", this.layout_game).on(cc.Node.EventType.TOUCH_END, () => {
            this.updateShipPos(-340);
        }, this);



        pg.event.on("game_time_over", () => {
            // alert("game_time_over")
            //这里的事件会发送的很早。但是我们需要等待动画执行完了之后再开始后续的内容
            Game.getIns().addPage();
            if (!Game.getIns().isOver) return pg.event.emit("game_start");
            //发送给上端最后的数据
            // alert("game_finish")
            // int  total  
            // int  right
            // int[]  scores   
            // let player = { right: Game.getIns().player.score, error: Game.getIns().player.error }
            this.gameOver();
        })
    }
    private isDeath = false;
    private updateShipPos(y = 0) {
        if (this.isDeath) return;
        if (Game.getIns().state == GAME_STATE.OVER) return;
        Game.getIns().state = GAME_STATE.RUNNING;
        cc.find("hand_ske", this.layout_game).active = false;
        cc.tween(this.ship).to(0.1, { y: y }).start();
    }
    private onAudioOn() {
        this.btn_audio_off.active = true;
        this.btn_audio_on.active = false;
        this.isPlayBgAudio = false;
        this.stopBgAudio();
    }
    private onAudioOff() {
        this.btn_audio_on.active = true;
        this.btn_audio_off.active = false;
        this.isPlayBgAudio = true;
        this.playBgAudio();
    }
    private playBgAudio() {
        if (!this.isPlayBgAudio) return;
        cc.audioEngine.resumeMusic();
    }
    private stopBgAudio() {
        cc.audioEngine.pauseMusic();
    }
    // onTouchStart() {
    //     pg.audio.playLocalAudio(cc.find(`Canvas/res/audio/btn`));
    //     pg.audio.playBgAudioByUrl(Game.getIns().bgAudio);
    //     this.showBgLightAction();
    //     pg.event.emit("game_start");
    // }
    private sendData(score) {
        return new Promise(res => {
            let upData: any = {
                word_count: this.data.word_count || 0,
                sentence_count: this.data.sentence_count || 0,
                zi_count: this.data.zi_count || 0,
                score: score,
            };
            let recordList = pg.hw.getRecord();
            if (recordList && recordList.length > 0) {
                upData.recordList = recordList
            }
            let mid = cc.find('middleLayer');
            if (!mid) return;
            const middleLayer = mid.getComponent('middleLayer');
            console.log('upload->' + JSON.stringify(upData))
            middleLayer.onHomeworkFinish(upData, () => {
                res('');
            })
        })
    }
    private gameOver() {
        Game.getIns().state = GAME_STATE.OVER;
        this.sendData(this.data.questions.length * 3).then(() => {
            let mid = cc.find('middleLayer');
            if (!mid) return;
            const middleLayer = mid.getComponent('middleLayer');
            middleLayer.saveGolds(this.data.questions.length * 3); // 保存金币数量; num 是获得金币的数量，数字类
            middleLayer.goNextPage(); //跳转到下一页
        })
        this.log("over~~~~~")
    }

    gameStart() {
        Game.getIns().state = GAME_STATE.WAIT;

        this.rNum = 0
        this.eNum = 0
        this.touching = true;
        this.count = 0;
        this.fishs = [];
        this.viewFishs = [];
        this.lastCount = null;
        this.touchFishs = [];
        this.isDeath = false;
        this.layout_card.removeAllChildren();
        this.ship.setPosition(-this.endX2, 0);
        cc.tween(this.ship).to(0.5, { x: -670 }).start();

        this.showQuestions();

    }



    private showQuestions() {
        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;
        if (data.type == "txt") {
            item = data.txt.length > 5 ? cc.instantiate(this.item_text2) : cc.instantiate(this.item_text)
            let word = cc.find("desc", item);
            word.getComponent(cc.Label).string = data.txt;
            word.active = true;
        } else if (data.type == "img") {
            item = cc.instantiate(this.item_pic);
            let pic = cc.find("img", item);
            pg.view.setNetImg(pic, data.picUrl, { w: 250, h: 220 });
            pic.active = true;
        } else if (data.type == "jl") {
            item = cc.instantiate(cc.find("items/icon_speed", this.node));
        }
        this.updateFish(item, data);
        this.viewFishs.push(data);
        return item;
    }

    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 % 3;
        this.fishCount++;
        item.active = true;
        let pos = [360, 0, -340]
        let i = Math.ceil(Math.random() * 7);

        item.parent = this.layout_card;
        item.data = data;
        data.fish.node = item;
        //x y   起始点 和终点  进行  随机
        cc.Tween.stopAllByTarget(item);
        //左往右
        item.y = pos[id];// -1300 / 2 + Math.random() * 1300;
        item.x = 1400;//
        cc.tween(item).to(6, { x: -1400 }).call(() => {
            data.fish.isOut = FISH_OUT.OUT;
            this.viewFishs = this.viewFishs.filter(v => v.id != data.id);
        }).start();
    }

    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 updateTime = 2;
    update(dt) {
        if (Game.getIns().state != GAME_STATE.RUNNING) return;
        this.isHitBalloon();
        this.updateTime += dt;
        if (this.updateTime < 2.3) return;
        this.updateTime = 0;
        // if (this.touching) return;
        if (this.fishLen < 5) this.count++;
        let fish = this.getFishByCount(this.count);
        if (fish) this.fishs.push(fish);
    }
    private rNum;
    private eNum;
    private isHitBalloon() {
        if (Game.getIns().state != GAME_STATE.RUNNING) return;
        if (!this.touching) return;
        this.fishs.forEach((item) => {
            if (Game.getIns().state != GAME_STATE.RUNNING) return;
            let dis = this.getDistances(this.ship, item);
            if (dis < 200 && item.data.fish.isOut == FISH_OUT.RUNNING) {
                if (item.y != this.ship.y) return;
                cc.Tween.stopAllByTarget(item);

                let state;
                if (item.data.type == "jl") {
                    state = FISH_STATE.FLY;
                    this.playLocalAudio("jiaonang");
                }
                else {
                    state = item.data.right ? FISH_STATE.BREAK : FISH_STATE.FALL;
                    let audio = item.data.right ? "right" : "error";
                    this.playLocalAudio(audio);
                }
                item.data.fish.isOut = FISH_OUT.OUT;
                this.updataBallonState(item, state).then(() => {
                    this.touchFishs.push(item.data);
                    this.viewFishs = this.viewFishs.filter(v => v.id != item.data.id);
                    if (item.data.right) this.rNum++;
                    else this.eNum++;
                    // if (this.eNum >= 2) {
                    //     Game.getIns().state = GAME_STATE.OVER;
                    //     Game.getIns().player.addError();
                    //     return pg.event.emit("game_time_over");

                    // }
                    if (this.rNum >= Game.getIns().getCurrentPage().rNum) {
                        Game.getIns().player.addRight();
                        Game.getIns().state = GAME_STATE.OVER;
                        cc.tween(this.ship).to(0.5, { x: this.endX2 }).delay(1).call(() => {
                            let fire_ske = cc.find("fire_ske", this.ship);
                            fire_ske.active = false;
                            return pg.event.emit("game_time_over");
                        }).start();
                    }
                });
            }

        })
    }
    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:
                    let right_ske = cc.find("right_ske", item);
                    right_ske.active = true;
                    pg.view.playDBAnimation(right_ske, "newAnimation", 1);
                    this.schedule(() => {
                        item.active = false;
                        resolve('');
                    }, 0.5);
                    pg.audio.playAudioByUrl(item.data.audioUrl);
                    break;
                case FISH_STATE.FALL:
                    this.isDeath = true;
                    item.active = false;
                    cc.tween(this.ship).to(0.1, { angle: -35 }).to(1, { x: this.ship.x + 200, y: -900 }).delay(2).call(() => {
                        this.ship.angle = 0;
                        this.ship.setPosition(-1400, 0);
                        cc.tween(this.ship).to(0.5, { x: -670 }).call(() => { this.isDeath = false; }).start();
                    }).start();

                    break;
                case FISH_STATE.FLY:
                    let fire_ske = cc.find("fire_ske", this.ship);
                    fire_ske.active = true;
                    this.playLocalAudio("huoyan").then(() => {
                        fire_ske.active = false;
                    });
                    this.showBgLightAction(true);
                    fire_ske.getComponent(dragonBones.ArmatureDisplay).playAnimation("newAnimation", 5);
                    this.schedule(() => {
                        item.active = false;
                        resolve('');
                    }, 0.5);
                    break;
            }
        });
    }


    private onTouchItem(e) {
        if (Game.getIns().state == GAME_STATE.OVER) return;
        if (this.touching) return;
        // cc.Tween.stopAllByTarget(e.target);
        this.touching = true;
        let point = e.target.getPosition();// e.touch.getLocation();
        // let jp = cc.v2(point.x - this.layout_balloon.width / 2, point.y - this.layout_balloon.height / 2);
        // let jp = cc.v2(point.x - this.layout_balloon.width / 2, point.y - this.layout_balloon.height / 2);
        let lefP = cc.v2(-2, -345);
        let angle = this.getDegree(lefP, point);
        this.playLocalAudio("jiguang");
        pg.event.emit("bullet_shoot", angle);
    }

    //根据两点获取角度
    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 nextQuestion() {
        Game.getIns().addPage();
        if (Game.getIns().getCurrentPage()) {
            this.showQuestions();
        } else {
            this.gameOver();
        }
    }




    private intervalId;
    private playLaba() {
        // if (!this.touchData || this.touchData.audioUrl == "") {
        //     // this.btn_laba.active = false;
        //     return;
        // }
        let questin = Game.getIns().getCurrentPage();
        if (!questin || !questin.audio) return;
        let btn_laba1 = this.btn_laba.getChildByName("btn_laba1");
        let btn_laba2 = this.btn_laba.getChildByName("btn_laba2");
        let btn_laba3 = this.btn_laba.getChildByName("btn_laba3");
        // cc.audioEngine.stopAllEffects();
        let count = 0;
        if (this.intervalId) clearInterval(this.intervalId);
        let stop = false;
        this.intervalId = setInterval(() => {
            count++;
            btn_laba1.active = count % 3 == 0;
            btn_laba2.active = count % 3 == 1;
            btn_laba3.active = count % 3 == 2;
            if (stop && count % 3 == 2) {
                clearInterval(this.intervalId);
                btn_laba1.active = true;
                btn_laba2.active = true;
                btn_laba3.active = true;
            }
        }, 200)
        pg.audio.playAudioByUrl(questin.audio, (() => {
            stop = true;
        }))
    }
    private endX = 1300;
    private endX2 = 1650;
    private showBgLightAction(speedup = false) {
        let runbg = cc.find("bg/bgRun", this.node);
        let bg_stone1 = cc.find("bg_stone1", runbg);
        let bg_stone2 = cc.find("bg_stone2", runbg);
        let bg_stone3 = cc.find("bg_stone3", runbg);
        let bg_stone4 = cc.find("bg_stone4", runbg);
        let bg_stone5 = cc.find("bg_stone5", runbg);

        let bg_planet = cc.find("bg_planet", runbg);
        let bg_planet2 = cc.find("bg_planet2", runbg);
        let bg_bottom1 = cc.find("bg_bottom1", runbg);
        let bg_bottom3 = cc.find("bg_bottom3", runbg);

        cc.Tween.stopAllByTarget(bg_bottom1);
        cc.Tween.stopAllByTarget(bg_bottom3);
        cc.Tween.stopAllByTarget(bg_planet);
        cc.Tween.stopAllByTarget(bg_planet2);
        cc.Tween.stopAllByTarget(bg_stone1);
        cc.Tween.stopAllByTarget(bg_stone2);
        cc.Tween.stopAllByTarget(bg_stone4);
        cc.Tween.stopAllByTarget(bg_stone3);
        cc.Tween.stopAllByTarget(bg_stone5);



        cc.tween(bg_stone1).to(speedup ? 2 : 4, { x: -this.endX }).call(() => { this.bgRunAction(bg_stone1, 7, this.endX) }).start();
        cc.tween(bg_stone2).to(speedup ? 4 : 8, { x: -this.endX }).call(() => { this.bgRunAction(bg_stone2, 7, this.endX) }).start();
        cc.tween(bg_stone3).to(speedup ? 3 : 6, { x: -this.endX }).call(() => { this.bgRunAction(bg_stone3, 7, this.endX) }).start();
        cc.tween(bg_stone4).to(speedup ? 2.5 : 5, { x: -this.endX }).call(() => { this.bgRunAction(bg_stone4, 7, this.endX) }).start();
        cc.tween(bg_stone5).to(speedup ? 4.5 : 9, { x: -this.endX }).call(() => { this.bgRunAction(bg_stone5, 7, this.endX) }).start();


        cc.tween(bg_planet).to(speedup ? 12 : 25, { x: -this.endX2 }).call(() => { this.bgRunAction(bg_planet, 30, this.endX2) }).start();
        cc.tween(bg_planet2).to(speedup ? 20 : 40, { x: -this.endX2 }).call(() => { this.bgRunAction(bg_planet2, 47, this.endX2) }).start();

        cc.tween(bg_bottom1).to(speedup ? 5 : 10, { x: -this.endX2 }).call(() => { this.bgRunAction(bg_bottom1, 17, this.endX2) }).start();
        cc.tween(bg_bottom3).to(speedup ? 12 : 25, { x: -this.endX2 }).call(() => { this.bgRunAction(bg_bottom3, 27, this.endX2) }).start();

    }
    private bgRunAction(item, time, endX) {
        let x = item.x;
        cc.tween(item).repeatForever(cc.tween().to(time, { x: - this.endX }).call(() => {
            item.x = endX;
        })).start();

    }






    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); });
        })
    }
    // private intervalId;
    // private playLaba() {
    //     let btn_kaba2 = this.btn_laba.getChildByName("btn_laba2");
    //     let btn_kaba3 = this.btn_laba.getChildByName("btn_laba3");
    //     btn_kaba2.active = true;
    //     btn_kaba3.active = true;

    //     let count = 0;
    //     if (this.intervalId) clearInterval(this.intervalId);
    //     let stop = false;
    //     this.intervalId = setInterval(() => {
    //         count++;
    //         btn_kaba2.active = count % 3 == 1;
    //         btn_kaba3.active = count % 3 == 2;
    //         if (stop && count % 3 == 2) clearInterval(this.intervalId);
    //     }, 150)

    //     pg.audio.playAudioByUrl(Game.getIns().getCurrentPage().audio, (() => {
    //         stop = true;
    //     }))
    // }


    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;
    }
}



