// 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/Z_04_syys_defaultData');
import {
    asyncTweenTo,
    asyncTweenBy,
    asyncDelay,
    asyncPlayDragonBoneAnimation,
    asyncPlayEffectByUrl,
    RandomInt
} from '../script/Z_04_syys_utils';

cc.Class({
    extends: cc.Component,

    properties: {
        bubblePrefab: {
            type: cc.Prefab,
            default: null,
        },
        fishPrefab: {
            type: cc.Prefab,
            default: null,
        },
        shellPrefab: {
            type: cc.Prefab,
            default: null,
        },

    },

    intervalIdArray: [],

    ctor() {
        this._imageResList = [];
        this._audioResList = [];
        this._status = {
            treeHeight: -1,
        }
    },

    start() {
        cc.debug.setDisplayStats(false);
        this.intervalIdArray = [];
        
        this.data = defaultData;
        this.getData((data) => {
            if (data) {
                this.data = data;
            }
            this.preloadItem();
        });
        this.initListeners();

        this.createBubbles();

        this.showKnockKnock();

        this.showFish();
        this.intervalIdArray.push(setInterval(() => {
            this.showFish();
        }, 9000));
    },

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

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

    addPreloadImage() { },

    addPreloadAudio() {
        this._audioResList.push(...this.data.wordList.map(data => ({ url: data.audio })));
        this._audioResList.push(...this.data.wordList.map(data => ({ url: data.backWordAudio })));
    },

    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');
        }
    },

    initListeners() {
        const btnWheel = cc.find('Canvas/NodeBg/BtnWheel');
        btnWheel.on('click', () => {
            this.onClickWheel();
        });
    },

    async onClickWheel() {

        this.hideKnockKnock();

        await this.openTheDoor();

        this.characterWalk();
    },

    async openTheDoor() {
        const nodeWheel = cc.find('Canvas/NodeBg/NodeWheel');

        this.playEffect('门铃');
        await asyncDelay(0.3);

        this.playEffect('旋转');
        await asyncTweenBy(nodeWheel, 0.5, { angle: -360 });
        nodeWheel.active = false;

        this.playEffect('开门');
        const nodeDoor = cc.find('Canvas/NodeBg/NodeDoor');
        nodeDoor.active = true;
        nodeDoor.opacity = 0;
        await asyncTweenBy(nodeDoor, 0.1, { opacity: 255 });
    },

    async characterWalk() {
        const nodeCharacterWalk = cc.find('Canvas/NodeBg/NodeCharacterBase/NodeCharacterWalk');
        nodeCharacterWalk.active = true;
        asyncPlayDragonBoneAnimation(nodeCharacterWalk, 'walk', -1);

        this.playEffect('走路');
        const nodeCharacterBase = cc.find('Canvas/NodeBg/NodeCharacterBase');
        await asyncTweenTo(nodeCharacterBase, 3, { x: 100 });

        nodeCharacterWalk.active = false;
        const nodeCharacterWater = cc.find('Canvas/NodeBg/NodeCharacterBase/NodeCharacterWater');
        nodeCharacterWater.active = true;

        cc.tween(nodeCharacterBase)
            .delay(1.5)
            .call(() => {
                this.showTree(0);
            })
            .delay(1)
            .to(2.5, { x: 0 })
            .start();
        this.playEffect('浇水');
        await asyncPlayDragonBoneAnimation(nodeCharacterWater, 'water', 1);
        nodeCharacterWater.active = false;

        const nodeCharacterNormal = cc.find('Canvas/NodeBg/NodeCharacterBase/NodeCharacterNormal');
        nodeCharacterNormal.active = true;
        asyncPlayDragonBoneAnimation(nodeCharacterNormal, 'normal', -1);
    },

    async showTree(idx) {
        if (idx <= this._status.treeHeight || this.data.wordList.length <= idx) {
            return;
        }
        const nodeTree = cc.find('Canvas/NodeBg/TreeMaskNode/NodeTree');
        this.playEffect('植物');
        this._status.treeHeight = idx;
        this.growTree(idx);
        this.growSky(idx);
        this.moveCamera(idx);
        await asyncTweenTo(nodeTree, 3, { y: 500 + 200 * idx });

        this.playEffect('路牌');
        this.showShell(idx);
    },

    growTree(idx) {
        if (idx < 5) {
            return;
        }
        const nodeTree = cc.find('Canvas/NodeBg/TreeMaskNode/NodeTree');
        asyncTweenTo(nodeTree, 3, { scaleY: (nodeTree.height + 200 * (idx - 4)) / nodeTree.height });
    },

    growSky(idx) {
        if (idx < 5) {
            return;
        }
        const nodeBg = cc.find('Canvas/NodeBg');
        asyncTweenTo(nodeBg, 3, { height: (nodeBg.height + 200 * (idx - 4)) });
    },

    moveCamera(idx) {
        const cameraYList = [0, 0];
        this.data.wordList.forEach((word, idx) => {
            if (idx < 2) {
                return;
            }
            cameraYList.push((idx - 1) * 200 + 50);
        });
        const camera = cc.find('Canvas/Main Camera');
        asyncTweenTo(camera, 3, { y: cameraYList[idx] });
    },

    showShell(idx) {
        const nodeShell = cc.instantiate(this.shellPrefab);
        nodeShell.parent = cc.find('Canvas/NodeBg/TreeMaskNode');
        nodeShell.y = idx * 200 + 300;

        const btnChange = nodeShell.getChildByName('BtnChange');
        const labelNode = nodeShell.getChildByName('LabelNode');
        const labelNodeBack = nodeShell.getChildByName('LabelNodeBack');

        btnChange.on('click', () => {
            cc.tween(nodeShell)
                .to(0.3, { scaleX: 0 }, { easing: 'cubicIn' })
                .call(() => {
                    labelNode.active = !labelNode.active;
                    labelNode.scaleX = labelNode.scaleX == 0 ? 1 : 0;
                    labelNodeBack.active = !labelNodeBack.active;
                    labelNodeBack.scaleX = labelNodeBack.scaleX == 0 ? 1 : 0;
                })
                .to(0.3, { scaleX: 1 }, { easing: 'cubicOut' })
                .start();
        });

        if (this.data.wordList[idx].backWord == '') {
            btnChange.active = false;
        }

        labelNode.on('click', () => {
            asyncPlayEffectByUrl(this.data.wordList[idx].audio);
            if (this.data.wordList[idx].backWord == '') {
                this.showTree(idx + 1);
                return;
            }
        });

        labelNodeBack.on('click', () => {
            asyncPlayEffectByUrl(this.data.wordList[idx].backWordAudio);
            this.showTree(idx + 1);
        });

        labelNode.getComponent(cc.Label).string = this.data.wordList[idx].word;
        labelNodeBack.active = true;
        labelNodeBack.scaleX = 1;

        labelNodeBack.getComponent(cc.Label).string = this.data.wordList[idx].backWord;
        labelNodeBack.active = false;
        labelNodeBack.scaleX = 0;

        cc.tween(nodeShell)
            .to(0.3, { scaleX: 1 }, { easing: 'cubicIn' })
            .start();
    },

    createBubbles() {
        this.intervalIdArray.push(setInterval(() => {
            if (Math.random() < 0.6) {
                return;
            }
            const speedX = RandomInt(30, 70);
            const speedY = RandomInt(20, 40);
            const nodeBubblePos = cc.find('Canvas/NodeBg/NodeBubblePos');
            const bubble = cc.instantiate(this.bubblePrefab);
            bubble.parent = nodeBubblePos;
            bubble.scale = 0;

            const bubbleScale = Math.random() * 0.7 + 0.3;

            cc.tween(bubble)
                .to(0.7, { scale: bubbleScale, x: speedX, y: speedY })
                .by(1, { x: speedX, y: speedY })
                .repeatForever()
                .start();
            cc.tween(bubble)
                .to(0.3 + Math.random() * 0.1, { scaleX: 0.95 * bubbleScale, scaleY: 1.05 * bubbleScale })
                .to(0.3 + Math.random() * 0.1, { scaleX: 1.05 * bubbleScale, scaleY: 0.95 * bubbleScale })
                .union()
                .repeatForever()
                .start();
        }, 900));
    },

    showKnockKnock() {
        const nodeKnockMask = cc.find('Canvas/NodeBg/NodeKnockMask');
        const heightList = [40, 80, 200, 200, 0];
        let idx = 0;
        this.intervalIdArray.push(setInterval(() => {
            if (idx >= heightList.length) {
                idx = 0;
            }
            nodeKnockMask.height = heightList[idx];
            idx++;
        }, 500));
    },

    hideKnockKnock() {
        const nodeKnockMask = cc.find('Canvas/NodeBg/NodeKnockMask');
        nodeKnockMask.active = false;
    },

    showFish() {
        const targetPosList = []
        for (let i = 1; i < 5; i++) {
            const node = cc.find(`Canvas/NodeBg/NodePosBase/NodeFishPos_${i}`);
            targetPosList.push({ x: node.x, y: node.y + 720 });
        }

        const nodeBg = cc.find('Canvas/NodeBg');
        for (let i = 0; i < RandomInt(15, 25); i++) {
            const fishScle = 0.7 + Math.random() * 0.2;

            const offsetX = RandomInt(-3, 3) * 120;
            const offsetY = RandomInt(-2, 1) * 50 + (offsetX / 100 % 2) * 25;

            offsetX += Math.random() * 50;
            offsetY += Math.random() * 25;

            const fish = cc.instantiate(this.fishPrefab);
            fish.parent = nodeBg;
            fish.x = -1000 + offsetX;
            fish.y = 1020 + offsetY;
            fish.scaleX = fishScle + Math.random() * 0.3;
            fish.scaleY = fishScle + Math.random() * 0.3;

            cc.tween(fish)
                .call(() => {
                    fish.getComponent('Z_04_syys_NodeFish').offsetX = offsetX;
                    fish.getComponent('Z_04_syys_NodeFish').offsetY = offsetY;
                    fish.getComponent('Z_04_syys_NodeFish').targetPosList.push(...targetPosList);
                })
                .start();
        }
    },

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

    onDestroy() {
        this.intervalIdArray.forEach(intervalId => {
            clearInterval(intervalId);
        });
        this.intervalIdArray = [];
    },

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

