import { asyncDelay, asyncPlayDragonBoneAnimation, Between, getSpriteFrimeByUrl, onHomeworkFinish, showTrebleFirework } from "../script/util";
import { MyCocosSceneComponent } from "../script/MyCocosSceneComponent";
import StarScore from "../prefabs/StarScore";

const { ccclass, property } = cc._decorator;

@ccclass
export default class SceneComponent extends MyCocosSceneComponent {

    addPreloadImage() {
        // TODO 根据自己的配置预加载图片资源
        // this._imageResList.push({ url: this.data.pic_url });
        // this._imageResList.push({ url: this.data.pic_url_2 });
    }

    addPreloadAudio() {
        // TODO 根据自己的配置预加载音频资源
        // this._audioResList.push({ url: this.data.audio_url });
    }

    addPreloadAnima() {

    }

    onLoadEnd() {
        // TODO 加载完成后的逻辑写在这里, 下面的代码仅供参考
        this.initData();
        this.initView();
    }

    _status = {
        canClick: true,
        currentSelectedCard: null,
        tryAgainFlg: false,
        starLength: 0,
        getStarNumber: 0,
        isRecording: false,
        starIdx: 0,
        groupIdx: 0
    };
    cardList: Array<cc.Node>;
    initData() {

    }

    createCards() {
        console.log('createCards' + Math.random());
        const cardList = [];
        const picArr = this.data.contentObj.picArr[this._status.starIdx][0];
        picArr.forEach((item, idx) => {
            cardList.push(this.createCard(item.left, idx, item.word));
            cardList.push(this.createCard(item.right, idx, item.word));
        });

        cardList.sort((a, b) => {
            return Math.random() - 0.5;
        });

        const length = cardList.length;
        cardList.forEach((card, idx) => {
            card.parent = cc.find('Canvas/bg/cardBg');
            card.x = (idx % (length / 2) - (length / 4 - 0.5)) * (card.width * card.scale + 50);
            card.y = (0.5 - Math.floor(idx / (length / 2))) * (card.height * card.scale + 40);
        });
        this.cardList = cardList;
    }

    createCard(data, id, word) {
        const cardLength = this.data.contentObj.picArr[this._status.starIdx][0].length;
        let cardSize = '';
        if (cardLength == 2) {
            cardSize = 'big';
        } else if (3 == cardLength || cardLength == 4) {
            cardSize = 'middle';
        } else {
            cardSize = 'small';
        }

        const card = cc.instantiate(cc.find(`card_${cardSize}`));
        card['data'] = id;
        card['word'] = word;
        card['audio'] = data.audio_url;

        const speaker = cc.find('speaker', card);
        const label = cc.find('label', card);
        const img = cc.find('img', card);

        speaker.active = false;
        label.active = false;
        img.active = false;

        if (data.radioValue == 'A') { // 文字
            label.active = true;
            label.getComponent(cc.Label).string = data.title;
        } else if (data.radioValue == 'B') { // 图片
            img.active = true;
            getSpriteFrimeByUrl(data.pic_url, (sp: cc.SpriteFrame) => {
                img.getComponent(cc.Sprite).spriteFrame = sp;
                img.scale = Math.min((card.width - 20) / img.width, (card.height - 20) / img.height);
            });
        } else { // 音频
            speaker.active = true;
            let idx = 0;
            speaker.on('click', () => {
                cc.tween(speaker)
                    .call(() => {
                        for (let i = 0; i < 4; i++) {
                            const speaker_0 = speaker.getChildByName(`speak_${i}`);
                            speaker_0.active = i == idx;
                        }
                        idx = (idx + 1) % 4;
                    })
                    .delay(0.2)
                    .union()
                    .repeatForever()
                    .start();

                this.playAudioByUrl(data.audio_url, () => {
                    speaker.stopAllActions();
                });
            });
        }

        const bg = card.getChildByName('bg');
        const bgBack = card.getChildByName('bg_back');
        bgBack.on('click', () => {
            this.onCardClicked(card);
        });

        return card;
    }

    async onCardClicked(card: cc.Node) {
        if (!this._status.canClick) {
            return;
        }
        const id = card['data'];

        if (this._status.currentSelectedCard == card) {
            return;
        }

        if (!this._status.currentSelectedCard) {
            this._status.currentSelectedCard = card;
            this._status.canClick = false;
            this.playAudioByUrl(card['audio']);
            await this.turnCard(card, false);
            this._status.canClick = true;
            return;
        }

        if (this._status.currentSelectedCard['data'] != id) {
            this._status.canClick = false;
            await this.turnCard(card, false);
            await this.playLocalAudio('error');
            this.playAudioByUrl(card['audio'], async () => {
                await asyncDelay(0.5);
                this.turnCard(this._status.currentSelectedCard, true);
                await this.turnCard(card, true);
                this._status.currentSelectedCard = null;
                this._status.canClick = true;
            });
            return;
        }

        this._status.canClick = false;
        await this.turnCard(card, false);

        const right1 = card.getChildByName('right');
        right1.active = true;
        const right2 = this._status.currentSelectedCard.getChildByName('right');
        right2.active = true;
        await this.playLocalAudio('right');

        this.playAudioByUrl(card['audio'], async () => {
            if (cc.find('Canvas/mask').active) {
                return;
            }
            await this.userSpeak();
            await this.hideCards(card, this._status.currentSelectedCard);
            this.checkQuestionOver();
            this._status.currentSelectedCard = null;
            this._status.canClick = true;
        });
    }

    async checkQuestionOver() {
        if (this.cardList.every(card => !card.active)) {
            this.showStar();
            this.stopProgress();
            await asyncDelay(0.5);
            this.nextQuestion();
        }
    }
    stopProgress() {
        console.log('stopProgress');
        const progress = cc.find('Canvas/bg/progress');
        progress.active = true;
        progress['countDownTweenId'].stop();
    }
    async stopRecord() {
        const baseSpeaker = cc.find('Canvas/bg/speaker');
        baseSpeaker.active = false;

        const btnStart = baseSpeaker.getChildByName('btnStart');
        const btnStop = baseSpeaker.getChildByName('btnStop');

        btnStart.active = false;
        btnStop.active = false;

        return new Promise((resolve, reject) => {
            if (this._status.isRecording == true) {
                if (window['courseware']) {
                    window['courseware'].stopTest();
                }
                this._status.isRecording = false;
                resolve(null);
            } else {
                resolve(null);
            }
        });
    }
    async nextQuestion() {
        console.log('nextQuestion');
        const baseSpeaker = cc.find('Canvas/bg/speaker');
        baseSpeaker.active = false;
        const btnStart = baseSpeaker.getChildByName('btnStart');
        btnStart.active = false;
        const btnStop = baseSpeaker.getChildByName('btnStop');
        btnStop.active = false;
        const tryAgain = baseSpeaker.getChildByName('tryAgain');
        tryAgain.active = false;
        const skip = baseSpeaker.getChildByName('skip');
        skip.active = false;
        const doItAgain = baseSpeaker.getChildByName('doItAgain');
        doItAgain.active = false;
        const goodjob = baseSpeaker.getChildByName('goodjob');
        goodjob.active = false;

        const progress = cc.find('Canvas/bg/progress');
        progress.active = false;
        progress.getChildByName('mask').width = progress.width;

        await this.stopRecord();
        this.cardList.forEach(card => {
            if (card.active) {
                cc.tween(card)
                    .to(0.3, { scale: 0 })
                    .removeSelf()
                    .start();
            } else {
                card.removeFromParent();
            }
        });
        this.cardList = [];
        this._status.starIdx++;

        if (this._status.starIdx < this.data.contentObj.picArr.length) {
            await asyncDelay(2);
            this.startQuestion();
        } else {
            if (this._status.getStarNumber < this.data.contentObj.picArr.length) {
                await this.showYouLoss();
            } else {
                await this.showYouWin();
            }
            // TODO 上报成绩
            window["courseware"].nextPage();
            // this.showRestart();
        }
    }
    showYouLoss() {
        return new Promise((resolve, reject) => {
            const mask = cc.find('Canvas/mask');
            mask.active = true;
            const youLoss = mask.getChildByName('youLoss');
            youLoss.active = true;

            this.playLocalAudio('try_again');

            cc.tween(youLoss)
                .set({ opacity: 0, scale: 2 })
                .to(1, { opacity: 255, scale: 1 }, { easing: "quartIn" })
                .delay(1)
                .to(1, { opacity: 0 })
                .call(() => {
                    resolve(null);
                })
                .start();
        });
    }

    showYouWin() {
        return new Promise((resolve, reject) => {
            const mask = cc.find('Canvas/mask');
            mask.active = true;
            const youWin = mask.getChildByName('youWin');
            youWin.active = true;

            showTrebleFirework(cc.find('Canvas'), cc.find('rabbon').children);

            this.playLocalAudio('sahua');

            cc.tween(youWin)
                .set({ opacity: 0, scale: 2 })
                .to(1, { opacity: 255, scale: 1 }, { easing: "quartIn" })
                .delay(1)
                .to(1, { opacity: 0 })
                .call(() => {
                    resolve(null);
                })
                .start();
        });
    }

    showRestart() {
        return new Promise((resolve, reject) => {
            const btnRestart = cc.find('Canvas/mask/btnRestart');
            btnRestart.active = true;
            btnRestart.once('click', () => {
                const mask = cc.find('Canvas/mask');
                mask.active = false;
                this._status = {
                    canClick: true,
                    currentSelectedCard: null,
                    tryAgainFlg: false,
                    starLength: 0,
                    getStarNumber: 0,
                    isRecording: false,
                    starIdx: 0,
                    groupIdx: 0
                };
                this.clearAllStar();
                console.log('汪汪汪');
                this.addStar(this.data.contentObj.picArr.length);
                this.startQuestion();
                btnRestart.active = false;
            });

            cc.tween(btnRestart)
                .set({ opacity: 0 })
                .to(1, { opacity: 255 }, { easing: "quartIn" })
                .call(() => {
                    resolve(null);
                })
                .start();
        });
    }

    hideCards(card: cc.Node, currentSelectedCard: cc.Node) {
        return new Promise((resolve, reject) => {
            cc.tween(card)
                .to(0.5, { scale: 0 }, { easing: "cubicIn" })
                .call(() => {
                    card.active = false;
                })
                .start();
            cc.tween(currentSelectedCard)
                .to(0.5, { scale: 0 }, { easing: "cubicIn" })
                .call(() => {
                    currentSelectedCard.active = false;
                    resolve(null);
                })
                .start();
        });
    }

    async userSpeak() {
        const word = this._status.currentSelectedCard['word'];
        const baseSpeaker = cc.find('Canvas/bg/speaker');
        baseSpeaker.active = true;
        const bg = baseSpeaker.getChildByName('bg');
        cc.tween(bg)
            .set({ opacity: 0 })
            .to(0.5, { opacity: 100 })
            .start();
        const speaker = baseSpeaker.getChildByName('speaker');
        asyncPlayDragonBoneAnimation(speaker, 'newAnimation', -1);
        if (window['courseware']) {
            window['courseware'].startTest(word);
            this._status.isRecording = true;
        } else {
            console.log('word = ' + word);
        }
        await asyncDelay(3);
        const dragonDisplay = speaker.getComponent(dragonBones.ArmatureDisplay);
        dragonDisplay.playAnimation('newAnimation', -1);
        dragonDisplay.timeScale = 0.00000001;
        let score = await this.stopTest();
        this._status.isRecording = false;

        if (score >= 60) {
            await this.showGoodjob();
            baseSpeaker.active = false;
            this._status.tryAgainFlg = false;
        } else {
            await this.showTryAgain();
            baseSpeaker.active = false;
            this._status.tryAgainFlg = false;
        }

    }

    stopTest() {
        return new Promise<number>((resolve, reject) => {
            if (window['courseware']) {
                window['courseware'].stopTest((res) => {
                    if (typeof (res) == 'string') {
                        resolve(parseInt(JSON.parse(res).result.overall));
                    } else {
                        resolve(parseInt(res.result.overall));
                    }
                });
            } else {
                resolve(Math.floor(Math.random() * 100));
            }
        });
    }

    showTryAgain() {
        return new Promise((resolve, reject) => {
            const tryAgain = cc.find('Canvas/bg/speaker/tryAgain');
            tryAgain.active = true;
            cc.tween(tryAgain)
                .set({ opacity: 0, scale: 2 })
                .call(async () => {
                    await asyncDelay(0.5);
                    this.playLocalAudio('try_again');
                })
                .to(1, { opacity: 255, scale: 1 }, { easing: "quartIn" })
                .delay(1)
                .call(() => {
                    tryAgain.active = false;
                    resolve(null);
                })
                .start();
        });
    }
    showGoodjob() {
        return new Promise((resolve, reject) => {
            const goodjob = cc.find('Canvas/bg/speaker/goodjob');
            goodjob.active = true;
            cc.tween(goodjob)
                .set({ opacity: 0, scale: 2 })
                .call(async () => {
                    await asyncDelay(0.5);
                    this.playLocalAudio('good_job');
                })
                .to(1, { opacity: 255, scale: 1 }, { easing: "quartIn" })
                .delay(1)
                .call(() => {
                    goodjob.active = false;
                    resolve(null);
                })
                .start();
        });
    }

    turnCard(card: cc.Node, backSide = true) {
        return new Promise((resolve, reject) => {
            const scaleX = card.scaleX;
            const bgBack = card.getChildByName('bg_back');
            cc.tween(card)
                .to(0.2, { scaleX: 0 }, { easing: 'sineIn' })
                .call(() => {
                    bgBack.active = backSide;
                })
                .to(0.2, { scaleX: scaleX }, { easing: 'sineOut' })
                .call(() => {
                    resolve(null);
                })
                .start();
        });
    }

    async initView() {
        // const btnStart = cc.find('Canvas/mask/btnStart');
        // btnStart.on('click', () => {
            const mask = cc.find('Canvas/mask');
            mask.active = false;
            this._status = {
                canClick: true,
                currentSelectedCard: null,
                tryAgainFlg: false,
                starLength: 0,
                getStarNumber: 0,
                isRecording: false,
                starIdx: 0,
                groupIdx: 0
            };
            this.clearAllStar();
            this.addStar(this.data.contentObj.picArr.length);
            this.startQuestion();
            // btnStart.active = false;
            this.playLocalAudio('btn');
        // });
    }

    async startQuestion() {
        this.createCards();
        await this.startCountDown(this.data.contentObj.countDownNumber);
        this.cardList.forEach(async (card, idx) => {
            await asyncDelay(idx * 0.4 / this.cardList.length);
            this.turnCard(card);
        });
        await this.startProgressCountDown(this.data.contentObj.answerTime);
        // this.showStar();
        this.nextQuestion();
    }

    clearAllStar() {
        const StarScore: StarScore = cc.find('Canvas/bg/StarScore').getComponent('StarScore');
        StarScore.clearAllStar();
    }
    addStar(number) {
        if (number == 1) {
            return;
        }
        console.log('addStar: ' + number);
        const StarScore: StarScore = cc.find('Canvas/bg/StarScore').getComponent('StarScore');
        for (let i = 0; i < number; i++) {
            StarScore.addStar();
        }
    }

    showStar() {
        this._status.getStarNumber++;
        const StarScore: StarScore = cc.find('Canvas/bg/StarScore').getComponent('StarScore');
        if (StarScore.starLength > 0) {
            StarScore.showStar();
        }
    }

    startCountDown(time) {
        const numberLayout = cc.find('Canvas/bg/number_layout');
        numberLayout.removeAllChildren();
        if (time == 0) {
            return;
        }
        if (time == 3) {
            this.playLocalAudio('time_up');
        }
        return new Promise((resolve, reject) => {
            (time + '').split('').forEach(char => {
                const number = cc.instantiate(cc.find(`numbers/text_${char}`));
                number.parent = numberLayout;
            });
            cc.tween(numberLayout)
                .set({ opacity: 0, scale: 2 })
                .to(0.5, { opacity: 255, scale: 1 }, { easing: 'quartIn' })
                .delay(0.5)
                .call(async () => {
                    await this.startCountDown(time - 1);
                    resolve(null);
                })
                .start();
        });
    }

    startProgressCountDown(time) {
        return new Promise((resolve, reject) => {
            const progress = cc.find('Canvas/bg/progress');
            const mask = progress.getChildByName('mask');
            progress.active = true;
            progress['countDownTweenId'] = cc.tween(mask)
                .set({ width: progress.width })
                .to((time - 2), { width: 2 / time * progress.width })
                .call(() => {
                    this.playLocalAudio('time_up');
                })
                .to(2, { width: 0 })
                .call(() => {
                    resolve(null);
                })
                .start()
        });
    }

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