import { asyncDelay, exchangeNodePos, getSprNode, onHomeworkFinish, playAudio } from "../script/util";
import { MyCocosSceneComponent } from "../script/MyCocosSceneComponent";
import Game, { Item, Option } from "./Game";
import pg from "./pg";

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();
        this.initEvent();
        pg.event.emit("startGame");
    }
    @property(cc.Node)
    ani_flower: cc.Node = null;

    @property(cc.Node)
    layout_card: cc.Node = null;
    @property(cc.Node)
    layout_card_result: cc.Node = null;

    @property(cc.Node)
    node_card: cc.Node = null;

    @property(cc.Node)
    bg_card: cc.Node = null;

    @property(cc.Node)
    layout_lollipop: cc.Node = null;

    initData() {
        Game.getIns().init(this.data);
    }
    initView() {
        pg.event.emit("mouse_start_play", { voice: Game.getIns().aniEnter.audioUrl, time: Game.getIns().aniEnter.time });
    }
    initEvent() {
        this.schedule(this.updateLoop, 1 / 60)
        pg.view.touchOn(pg.view.find(this, 'bg/bg_card/btn_check'), this.onTouchCheck, this);

        pg.event.on("startGame", () => { this.startGame() })
        pg.event.on("nextPage", () => { this.nextPage() })
        pg.event.on("gameOver", () => { this.gameOver() })
    }





    private currentCards: cc.Node[];
    //开始游戏
    startGame() {
        Game.getIns().reset();
        pg.event.emit("mouse_num", Game.getIns().getTotalPageNum());
        this.nextPage();
    }
    nextPage() {
        this.checked = false;
        this.cards = [];
        this.cardBgs = [];
        this.currentCards = [];
        let data: Item = Game.getIns().getCurrentPage();
        //自动创建卡片
        this.layout_card.active = true;
        this.layout_card_result.active = false;
        this.layout_lollipop.active = false;
        this.createCrads(data);
    }
    getCurrentOpSet() {
        let op = {
            "2": {
                x: -135,
                y: 160,
                y2: -80,
                space: 260,
                scale: 1,
            },
            "3": {
                x: -260,
                y: 160,
                y2: -80,
                space: 260,
                scale: 1,
            },
            "4": {
                x: -390,
                y: 110,
                y2: -100,
                space: 260,
                scale: 0.85,
            },
            "5": {
                x: -410,
                y: 110,
                y2: -90,
                space: 260 * 0.8,
                scale: 0.8,
            },
        }
        let len = Game.getIns().getCurrentPage().optionList.length;
        let opSet = op[`${len}`];
        return opSet;
    }
    getPostionById(count) {
        let opSet = this.getCurrentOpSet();
        let x = opSet.space * count + opSet.x;
        let y = opSet.y;
        return cc.v2(x, y);
    }
    getBgPostionById(count) {
        let opSet = this.getCurrentOpSet();
        let x = opSet.space * count + opSet.x;
        let y = opSet.y2;
        return cc.v2(x, y);
    }

    //创建卡片
    private cards: cc.Node[];
    private cardBgs: cc.Node[];
    createCrads(list) {
        this.layout_card.removeAllChildren();

        let count = 0;
        list.optionList.forEach(li => {
            let opSet = this.getCurrentOpSet();
            let posBg = this.getBgPostionById(count);
            let card_bg = cc.instantiate(this.bg_card);
            card_bg.setPosition(posBg);
            card_bg.scale = opSet.scale;
            this.layout_card.addChild(card_bg);
            this.updateCardBg(card_bg, li);
            this.cardBgs.push(card_bg);
            count++;
        })
        count = 0;
        list.optionList.forEach(li => {
            let opSet = this.getCurrentOpSet();
            let pos = this.getPostionById(count);
            let card = cc.instantiate(this.node_card);
            card.setPosition(pos);
            card.scale = opSet.scale;
            this.layout_card.addChild(card);
            this.updateCard(card, li);
            this.cards.push(card);
            card.data = li;
            count++;
        })
    }
    updateCard(item: cc.Node, data: Option) {
        item.active = true;
        pg.view.visible(pg.view.find(item, 'text'), false);
        pg.view.visible(pg.view.find(item, 'pic'), false);
        pg.view.visible(pg.view.find(item, 'picText'), false);
        switch (data.type) {
            case "text":
                pg.view.visible(pg.view.find(item, 'text'), true);
                pg.view.setString(pg.view.find(item, 'text/label'), data.txt);
                break;
            case "pic":
                pg.view.visible(pg.view.find(item, 'pic'), true);
                pg.view.setNetImg(pg.view.find(item, 'pic/img'), data.picUrl, { w: 140, h: 160 });
                break;
            case "picText":
                pg.view.visible(pg.view.find(item, 'picText'), true);
                pg.view.setString(pg.view.find(item, 'picText/label'), data.txt);
                pg.view.setNetImg(pg.view.find(item, 'picText/img'), data.picUrl, { w: 140, h: 160 });
                break;
        }
        item.on(cc.Node.EventType.TOUCH_START, this.onItemTouchStart, this);
        item.on(cc.Node.EventType.TOUCH_MOVE, this.onItemTouchMove, this);
        item.on(cc.Node.EventType.TOUCH_END, this.onItemTouchEnd, this);
        item.on(cc.Node.EventType.TOUCH_CANCEL, this.onItemTouchCancel, this);
    }

    updateCardBg(item, data) {
        item.data = data
        item.active = true;
    }
    private setTouchPos(e) {
        let location = e.getLocation();
        let size = cc.view.getCanvasSize();
        let scale = (size.width / size.height) / (1280 / 720);
        if (scale > 1) {
            let width = size.width / size.height * 720;
            let pos = location.sub(cc.v2(width / 2, 720 / 2))
            e.target.setPosition(pos)
        } else {
            let height = size.height / size.width * 1280;
            let pos = location.sub(cc.v2(1280 / 2, height / 2))
            e.target.setPosition(pos)
        }
    }
    onItemTouchStart(e) {
        let target: cc.Node = e.target;
        let data = target.data;
        if (data.isChecked) return;
        this.setTouchPos(e);
    }
    onItemTouchMove(e) {
        let target: cc.Node = e.target;
        let data = target.data;
        if (data.isChecked) return;
        this.setTouchPos(e);
    }
    onItemTouchEnd(e) {
        //
        let target: cc.Node = e.target;
        let data = target.data;
        if (data.isChecked) return;
        let rect1 = cc.rect(target.x, target.y, target.width * target.scale, target.height * target.scale);
        let itemBg = this.cardBgs.find(bg => {
            return rect1.intersects(cc.rect(bg.x, bg.y, bg.width * bg.scale, bg.height * bg.scale / 2));
        })
        if (!itemBg || this.currentCards[itemBg.data.count]) {
            //回退
            this.playLocalAudio("error");
            target.setPosition(this.getPostionById(data.count))
            for (let i = 0; i < this.currentCards.length; i++) {
                let cd = this.currentCards[i];
                if (cd && cd.data.id == target.data.id) {
                    this.currentCards.splice(i, 1);
                    break;
                }
            }
            return;
        }
        //执行
        let pos = this.getBgPostionById(itemBg.data.count);
        target.setPosition(pos);
        this.currentCards[itemBg.data.count] = target;
        data.isChecked = true;

        this.playLocalAudio("right");
        let ani_flower = cc.instantiate(this.ani_flower);
        ani_flower.active = true;
        target.addChild(ani_flower);
        setTimeout(() => {
            ani_flower && (ani_flower.parent = null);
        }, 3000);
    }
    onItemTouchCancel() {

    }
    checked: boolean;
    updateCheckBtn() {
        if (this.checked) {
            pg.view.visible(pg.view.find(this, 'bg/bg_card/btn_check'), false)
            pg.view.visible(pg.view.find(this, 'bg/bg_card/btn_check_grey'), false)
            return;
        }
        let isFull = this.checkFull();
        pg.view.visible(pg.view.find(this, 'bg/bg_card/btn_check'), isFull)
        pg.view.visible(pg.view.find(this, 'bg/bg_card/btn_check_grey'), !isFull)
    }
    checkFull() {
        if (!this.currentCards) return;
        if (!this.cards) return;
        if (this.currentCards.length != this.cards.length) return false;
        return this.currentCards.every(card => !!card);
    }
    private onTouchCheckCantouch: boolean;
    onTouchCheck() {
        if (this.onTouchCheckCantouch) return;
        let isSuccess = Game.getIns().checkSuccess(this.currentCards.map(cd => cd.data));
        if (!isSuccess) {
            this.playLocalAudio("error");
            this.currentCards.forEach(card => {
                cc.tween(card).to(0.3, { x: this.getPostionById(card.data.count).x, y: this.getPostionById(card.data.count).y }).start();
                card.data.isChecked = false;
            })
            this.currentCards.length = 0;
            return;
        }
        this.onTouchCheckCantouch = true;
        this.checked = true;
        let page = Game.getIns().getCurrentPage();
        if (!!page.image) {
            this.layout_card.active = false;
            this.layout_card_result.active = true;
            //执行效果
            let img = pg.view.find(this.layout_card_result, "img");
            pg.view.setNetImg(img, page.image, { w: 340, h: 150 })

            let label = pg.view.find(this.layout_card_result, 'label');
            pg.view.setString(label, Game.getIns().getTotalLabel());
        }
        if (!page.audio) {
            pg.event.emit("mouse_add");
            setTimeout(() => {
                this.updateCardResult();
                this.updateLollipop().then(() => {
                    if (!Game.getIns().addPage()) {
                        pg.event.emit("gameOver")
                    } else {
                        pg.event.emit("nextPage")
                    }
                    this.onTouchCheckCantouch = false;
                })
            }, 2000);
        } else {
            pg.audio.playAudioByUrl(page.audio).then(() => {
                pg.event.emit("mouse_add");
                setTimeout(() => {
                    this.updateCardResult();
                    this.updateLollipop().then(() => {
                        if (!Game.getIns().addPage()) {
                            pg.event.emit("gameOver")
                        } else {
                            pg.event.emit("nextPage")
                        }
                        this.onTouchCheckCantouch = false;
                    })
                }, 2000);
            })
        }
    }
    updateCardResult() {
        return new Promise((res, rej) => {
            let page = Game.getIns().getCurrentPage();
            //显示小老鼠
            if (page.voice) {
                pg.event.on("mouse_start_play_success", () => { res(true); })
                pg.event.emit("mouse_start_play", { voice: page.voice, time: page.time });//
            } else {
                setTimeout(() => { res(true); }, 1000);
            }
        })
    }
    updateLollipop() {
        return new Promise((res, rej) => {
            //出现棒棒糖的部分。
            //1.波浪。
            //2.倒计时转圈
            //3.弹出goodJob
            //4.resolve
            this.layout_lollipop.active = true;
            pg.view.find(this.layout_lollipop, 'icon').active = true;
            pg.view.find(this.layout_lollipop, 'texts').active = false;
            pg.view.find(this.layout_lollipop, 'progressbar_red').active = false;
            pg.view.find(this.layout_lollipop, 'progressbar_grey').active = false;
            pg.view.find(this.layout_lollipop, 'progressbar_highlight').active = false;
            let vs = [pg.view.find(this.layout_lollipop, 'v1'), pg.view.find(this.layout_lollipop, 'v2'), pg.view.find(this.layout_lollipop, 'v3')]
            //出现波浪
            let count = 0;
            let i1 = setInterval(() => {
                count++;
                let max = count % (vs.length + 2);
                vs[0].active = 1 < max;
                vs[1].active = 2 < max;
                vs[2].active = 3 < max;
            }, 200)
            let lolliTouch = () => {
                clearInterval(i1);
                vs[0].active = false;
                vs[1].active = false;
                vs[2].active = false;
                pg.view.find(this.layout_lollipop, 'progressbar_red').active = true;
                pg.view.find(this.layout_lollipop, 'progressbar_grey').active = true;
                pg.view.find(this.layout_lollipop, 'progressbar_highlight').active = true;
                pg.view.touchOff(this.layout_lollipop, lolliTouch, this);
                let progressbar_red = pg.view.find(this.layout_lollipop, 'progressbar_red');
                let sprite = progressbar_red.getComponent(cc.Sprite);
                sprite.fillRange = 1;
                let countdown = pg.view.find(this.layout_lollipop, 'countdown');
                pg.audio.playAudioByNode(countdown);

                let i2 = setInterval(() => {
                    sprite.fillRange -= 0.01;
                }, 30)

                setTimeout(() => {
                    clearInterval(i2);
                    pg.view.find(this.layout_lollipop, 'icon').active = false;
                    pg.view.find(this.layout_lollipop, 'progressbar_red').active = false;
                    pg.view.find(this.layout_lollipop, 'progressbar_grey').active = false;
                    pg.view.find(this.layout_lollipop, 'progressbar_highlight').active = false;

                    let texts = pg.view.find(this.layout_lollipop, 'texts')
                    pg.audio.playAudioByNode(pg.view.find(texts, 'audio'))
                    texts.active = true;

                    let complate = texts.getChildByName("complate");
                    let well = texts.getChildByName("well");
                    let good = texts.getChildByName("good");
                    complate.active = false;
                    well.active = false;
                    good.active = false;
                    let words = [complate, well, good];
                    let item = words[Math.floor(Math.random() * words.length)];
                    item.active = true;
                    item.opacity = 0;
                    item.scale = 0.1;
                    cc.tween(item).to(0.2, { scale: 1.1, opacity: 255 }).to(0.1, { scale: 1 }).delay(0.5).to(0.1, { opacity: 0, scale: 0 }).call(() => {
                        this.layout_lollipop.active = false;
                        res(true);
                    }).start();
                }, 3000);
            }
            pg.view.touchOn(this.layout_lollipop, lolliTouch, this);
        })
    }



    updateLoop() {
        this.updateCheckBtn();
        this.updateProgress();
    }
    updateProgress() {
        let page = pg.view.find(this, 'bg/bg_card/page/label');
        pg.view.setString(page, Game.getIns().getCurrentPageNum() + '/' + Game.getIns().getTotalPageNum())
    }

    gameOver() {
        let mouse_end = pg.view.find(this, "mouse_end");
        mouse_end.active = true;
        mouse_end.getComponent("mouse_end").play().then(() => {
            onHomeworkFinish();
        })
    }


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