// Learn cc.Class:
//  - https://docs.cocos.com/creator/manual/en/scripting/class.html
// Learn Attribute:
//  - https://docs.cocos.com/creator/manual/en/scripting/reference/attributes.html
// Learn life-cycle callbacks:
//  - https://docs.cocos.com/creator/manual/en/scripting/life-cycle-callbacks.html
const defaultData = require('../script/SN11_defaultData');
import {
    exchangeNodePos,
    asyncTweenTo,
    asyncPlayDragonBoneAnimation,
    randomSortByArr,
    asyncPlayEffectByUrl
} from '../script/SN11_utils';

cc.Class({
    extends: cc.Component,

    properties: {
        grassItemPrefab: {
            type: cc.Prefab,
            default: null,
        },
        createRate: 0.5
    },

    // LIFE-CYCLE CALLBACKS:

    ctor() {
        this._imageResList = [];
        this._audioResList = [];
        this._status = {
            currentRoundIdx: 0,
            currentQuestionIdx: 0
        };
    },

    // onLoad () {
    //     cc.debug.setDisplayStats(false);
    // },

    start() {
        // if (window) {
        //     const sw = 1280 / window.outerwidth;
        //     const sh = 720 / window.outerheight;
        //     const scale = Math.min(sw, sh);
        //     console.log('sw = ' + sw);
        //     console.log('sh = ' + sh);
        //     this.node.scale = scale;
        // }

        cc.debug.setDisplayStats(false);

        console.log(this.node.width);
        console.log(this.node.height);

        this.data = defaultData;
        this.getData((data) => {
            if (data) {
                this.data = data;
            }
            this.preloadItem();
            this.playBGM();
        });

        this.moveGrass();
        this.moveRailWay();

        this.initListeners();

        const btnStart = cc.find(`Canvas/BtnStart`);
        btnStart.active = true;
        btnStart.on('click', () => {
            this.playEffect('点击');
            btnStart.off('click');
            this.gameStart();
            cc.tween(btnStart)
                .to(0.3, { scale: 3, opacity: 0 })
                .call(() => { btnStart.active = false })
                .start();
        });
    },

    _bgmPlayed: false,
    playBGM() {
        if(this.data.bgAudio===false){
            // 不播放背景音
            return;
        }
        if (!this._bgmPlayed) {
            this.playEffect('bgm', true, 0.5);
            this._bgmPlayed = true;
        }
    },

    gameStart() {
        this.showOptions();
        this.showCar(() => {
            asyncPlayEffectByUrl(this.data.roundList[this._status.currentRoundIdx].audio);
            this._canOptionClick = true;
        });
    },

    initListeners() {
        for (let i = 0; i < 3; i++) {
            const btnOption = cc.find(`Canvas/NodeOptions/NodeOption_${i}/BtnOption`)
            btnOption.on('click', () => {
                this.onOptionClicked(i);
            });
        }
    },

    _canOptionClick: false,
    onOptionClicked(idx) {
        if (!this._canOptionClick) {
            return;
        }

        this._canOptionClick = false;

        let { currentRoundIdx, currentQuestionIdx } = this._status;

        let rightWord = this.data.roundList[currentRoundIdx].questionList[currentQuestionIdx].rightWord;

        const label = cc.find(`Canvas/NodeOptions/NodeOption_${idx}/BtnOption/LabelOption`)

        if (label.getComponent(cc.Label).string == rightWord) {
            this.showSuccess(idx);
        } else {
            this.showFail(idx);
        }
    },

    async showSuccess(idx) {
        const audioUrl = this.data.roundList[this._status.currentRoundIdx].questionList[this._status.currentQuestionIdx].rightAudio;
        asyncPlayEffectByUrl(audioUrl);

        const nodeOption = cc.find(`Canvas/NodeOptions/NodeOption_${idx}`);
        const imgBg0 = cc.find(`Canvas/NodeOptions/NodeOption_${idx}/BtnOption/ImgBg_0`);
        const imgBg1 = cc.find(`Canvas/NodeOptions/NodeOption_${idx}/BtnOption/ImgBg_1`);
        const imgBg2 = cc.find(`Canvas/NodeOptions/NodeOption_${idx}/BtnOption/ImgBg_2`);
        this.showLight();
        await this.charactorMoveToTarget(idx);

        this.hideOtherOptions(idx);
        await this.showCharactorAttack();

        imgBg0.active = false;
        imgBg1.active = true;
        await this.showCharactorAttack();

        imgBg1.active = false;
        imgBg2.active = true;
        await this.showCharactorAttack();

        nodeOption.active = false;
        this.showStar(idx);

        this.hideLight();
        this.hideCar();
        await this.charactorFall();

        this.resetCharactor();

        if (!this.nextQuestion()) {
            this.showGameOver();
            return;
        }

        imgBg2.active = false;
        imgBg0.active = true;

        nodeOption.active = true;
        this.showOptions();
        this.showCar(() => {
            asyncPlayEffectByUrl(this.data.roundList[this._status.currentRoundIdx].audio);
            this._canOptionClick = true;
        });
    },

    showGameOver() {
        // TODO: showGameOver
        console.log('showGameOver');
        // this.moveGrassInterval
        clearInterval(this.moveGrassInterval);
        cc.director.loadScene('SN11_end');
    },

    nextQuestion() {
        let { currentRoundIdx, currentQuestionIdx } = this._status;
        this._status.currentQuestionIdx++;
        if (this._status.currentQuestionIdx >= this.data.roundList[currentRoundIdx].questionList.length) {
            this._status.currentQuestionIdx = 0;
            this._status.currentRoundIdx++;
            if (this._status.currentRoundIdx >= this.data.roundList.length) {
                return false;
            }
        }
        return true;
    },

    hideOtherOptions(idx) {
        let [idx1, idx2] = [0, 1, 2].filter(data => data != idx);

        const nodeOption1 = cc.find(`Canvas/NodeOptions/NodeOption_${idx1}`);
        const nodeOption2 = cc.find(`Canvas/NodeOptions/NodeOption_${idx2}`);

        cc.tween(nodeOption1)
            .to(0.2, { scale: 0 })
            .start();
        this.showSmoke(idx1);

        cc.tween(nodeOption2)
            .to(0.2, { scale: 0 })
            .start();
        this.showSmoke(idx2);
    },

    showLight() {
        const light = cc.find('Canvas/ImgCar/ImgCarLight');
        cc.tween(light)
            .to(0.3, { opacity: 255 })
            .start();
    },

    hideLight() {
        const light = cc.find('Canvas/ImgCar/ImgCarLight');
        cc.tween(light)
            .to(0.3, { opacity: 0 })
            .start();
    },

    showStar(idx) {
        const btnOption = cc.find(`Canvas/NodeOptions/NodeOption_${idx}/BtnOption`);
        const imgStar = cc.find('Canvas/ImgStar');
        this.playEffect('星星');

        imgStar.zIndex = 11;
        imgStar.opacity = 255;
        imgStar.scale = 0.3;
        imgStar.setPosition(exchangeNodePos(imgStar.parent, btnOption));

        cc.tween(imgStar)
            .parallel(
                cc.tween(imgStar).by(1, { angle: 360 * 3 }),
                cc.tween(imgStar).to(1, { scale: 1, x: 0, y: 0, opacity: 255 })
            )
            .to(1, { scale: 3, opacity: 0 })
            .start();
    },

    getWrongAudioUrl(idx) {
        const currentRound = this.data.roundList[this._status.currentRoundIdx];
        const currentQuestion = currentRound.questionList[this._status.currentQuestionIdx];
        const wrongAudioList = currentQuestion.wrongAudioList;
        const wrongWordList = currentQuestion.wrongWordList;
        const label = cc.find(`Canvas/NodeOptions/NodeOption_${idx}/BtnOption/LabelOption`);
        const wrongWordIdx = wrongWordList.findIndex((data) => data == label.getComponent(cc.Label).string);

        return wrongAudioList[wrongWordIdx]
    },

    async showFail(idx) {
        const audioUrl = this.getWrongAudioUrl(idx)
        asyncPlayEffectByUrl(audioUrl);

        this.showLight();
        await this.charactorMoveToTarget(idx);
        await this.showCharactorAttack();

        this.showSmoke(idx);
        this.playEffect('爆炸');
        this.hideLight();
        this.hideCar();
        this.playEffect('眩晕');
        await this.charactorFall();

        this.resetCharactor();

        this.showCar(() => {
            asyncPlayEffectByUrl(this.data.roundList[this._status.currentRoundIdx].audio);
            this._canOptionClick = true;
        });
    },

    async charactorMoveToTarget(idx) {
        const nodeCharactor = cc.find('Canvas/ImgCar/NodeCharactor');
        const nodeCharactorTarget = cc.find(`Canvas/NodeOptions/NodeOption_${idx}/BtnOption/NodeCharactorTarget`);
        const targetPos = exchangeNodePos(nodeCharactor.parent, nodeCharactorTarget);
        await asyncTweenTo(nodeCharactor, 0.5, { x: targetPos.x, y: targetPos.y }, { easing: 'cubicInOut' });
    },

    async showCharactorAttack() {
        const imgCharactor = cc.find('Canvas/ImgCar/NodeCharactor/ImgCharactor');
        const dragonBoneNodeCharactor = cc.find('Canvas/ImgCar/NodeCharactor/DragonBoneNodeCharactor');

        imgCharactor.active = false;
        dragonBoneNodeCharactor.active = true;

        this.playEffect('砸');

        await asyncPlayDragonBoneAnimation(dragonBoneNodeCharactor, 'attack', 1);

        imgCharactor.active = true;
        dragonBoneNodeCharactor.active = false;
    },

    async showSmoke(idx) {
        const dragonBoneNodeSmoke = cc.find(`Canvas/NodeOptions/NodeOption_${idx}/BtnOption/DragonBoneNodeSmoke`);

        dragonBoneNodeSmoke.active = true;

        await asyncPlayDragonBoneAnimation(dragonBoneNodeSmoke, 'newAnimation', 1);

        dragonBoneNodeSmoke.active = false;
    },

    async charactorFall() {
        return new Promise((resolve, reject) => {
            const nodeCharactor = cc.find('Canvas/ImgCar/NodeCharactor')
            cc.tween(nodeCharactor)
                .by(0.3, { y: 50 }, { easing: 'cubicOut' })
                .by(2, { angle: -360 * 2.7, y: -720 })
                .call(resolve)
                .start();

            const imgCharactor = cc.find('Canvas/ImgCar/NodeCharactor/ImgCharactor');
            cc.tween(imgCharactor)
                .delay(0.3)
                .to(1, { scale: 0.7 })
                .start();
        });
    },

    getData(func) {
        if (window && window.courseware) {
            window.courseware.getData(func, 'tyzdc_001');
        } else {
            func(defaultData);
        }
    },

    _imageResList: null,
    _audioResList: null,
    preloadItem() {
        this.addPreloadImage();
        this.addPreloadAudio();
        this.preload();
    },

    addPreloadImage() { },

    addPreloadAudio() {
        this.data.roundList.forEach(round => {
            this._audioResList.push({ url: round.audio });
            round.questionList.forEach(question => {
                this._audioResList.push({ url: question.rightAudio });
            });
        });
    },

    preload() {
        const preloadArr = this._imageResList.concat(this._audioResList);
        cc.assetManager.loadAny(preloadArr, null, null, (err, data) => {
            this.hideAirClassLoading();
        });
        if (preloadArr.length == 0) {
            this.hideAirClassLoading();
        }
    },

    hideAirClassLoading() {
        if (window && window["air"]) {
            window["air"].hideAirClassLoading();
        }
        console.log('hideAirClassLoading');
    },

    showCar(onFinish) {
        const imgCar = cc.find('Canvas/ImgCar');
        imgCar.zIndex = 11;
        cc.tween(imgCar)
            .delay(1)
            .by(1, { y: 250 })
            .call(onFinish)
            .start();
    },

    async hideCar() {
        const imgCar = cc.find('Canvas/ImgCar');
        await asyncTweenTo(imgCar, 1, { y: -500 });
    },

    resetCharactor() {
        const nodeCharactor = cc.find('Canvas/ImgCar/NodeCharactor');
        nodeCharactor.angle = 0;
        nodeCharactor.x = 0;
        nodeCharactor.y = 0;

        const imgCharactor = cc.find('Canvas/ImgCar/NodeCharactor/ImgCharactor');
        imgCharactor.scale = 1;
    },

    showOptions() {
        const nodeOptions = cc.find('Canvas/NodeOptions');
        nodeOptions.zIndex = 10;
        nodeOptions.y = 720;
        cc.tween(nodeOptions)
            .by(3, { y: -720 }, { easing: 'cubicInOut' })
            .start();

        let { currentRoundIdx, currentQuestionIdx } = this._status;
        let currentQuestion = this.data.roundList[currentRoundIdx].questionList[currentQuestionIdx];
        let wordList = randomSortByArr([currentQuestion.rightWord, ...currentQuestion.wrongWordList]);

        for (let i = 0; i < 3; i++) {
            const nodeOption = cc.find(`Canvas/NodeOptions/NodeOption_${i}`)
            nodeOption.scale = 1;

            const btnOption = cc.find(`Canvas/NodeOptions/NodeOption_${i}/BtnOption`)
            setTimeout(() => {
                cc.tween(btnOption)
                    .by(2.5, { y: 20 }, { easing: 'cubicInOut' })
                    .by(2.5, { y: -20 }, { easing: 'cubicInOut' })
                    .union()
                    .repeatForever()
                    .start();
            }, Math.random() * 2000);

            const label = cc.find(`Canvas/NodeOptions/NodeOption_${i}/BtnOption/LabelOption`)
            label.getComponent(cc.Label).string = wordList[i];
        }
    },

    moveGrassInterval: null,
    moveGrass() {
        let imgBgMove = cc.find('Canvas/ImgBgMove');
        cc.tween(imgBgMove)
            .by(5, { y: -1440 })
            .call(() => {
                imgBgMove.active = false;
            })
            .start();

        this.moveGrassInterval = setInterval(() => {
            if (Math.random() < this.createRate) {
                let node = cc.instantiate(this.grassItemPrefab);
                let offsetY = Math.random() * 360 - 260;
                node.x = -540 + Math.random() * 220;
                node.y = 720 + offsetY;
                this.node.addChild(node);
                cc.tween(node)
                    .by(6, { y: -1440 * 6 / 5 })
                    .call(() => {
                        node.active = false;
                    })
                    .start();
            }
            if (Math.random() < this.createRate) {
                let node = cc.instantiate(this.grassItemPrefab);
                let offsetY = Math.random() * 360 - 260;
                node.x = 540 - Math.random() * 220;
                node.y = 720 + offsetY;
                this.node.addChild(node);
                cc.tween(node)
                    .by(6, { y: -1440 * 6 / 5 })
                    .call(() => {
                        node.active = false;
                    })
                    .start();
            }
        }, 900);
    },

    moveRailWay() {
        let nodeRailWayBase = cc.find('Canvas/NodeRailWayBase');
        cc.tween(nodeRailWayBase)
            .by(2.5 * 780 / 720, { y: -780 })
            .call(() => {
                nodeRailWayBase.y = 0;
                this.moveRailWay();
            })
            .start();
    },

    playEffect(name, loop, volume) {
        let musicComponent = cc.find('Canvas/MusicNode').getComponent('SN11_MusicNode');
        musicComponent.playEffect(name, loop, volume);
    }

    // update (dt) {},
});
