import Scene from "../MViews/MScene";
import { MConst } from "../Global/MConst";
import Ball from "../Global/Ball";
import { Decorator } from "../Decorator/Decorator";
import GameMgr from "../Mgr/GameMgr";
import Net from "../Global/Net";
import PanelCtrl from "../MCtrls/MPanelCtrl";
import { NetUtils } from "../Global/NetUtils";
import Loading from "../../loading/Loading";
import SoundMgr from "../Mgr/SoundMgr";
import GameOverPanel from "../Panel/GameOverPanel";
import { initNECaptcha } from "../MComponents/initNECaptcha";
import MTimer from "../MComponents/MTimer";
import Game from "./Game";

@Decorator.OnUpdate
@Decorator.OnDestroy
export default class MainScene extends Scene implements Decorator.IDefaultCallback {
    get skinKey() { return "MainScene" }
    public groupTop: eui.Group;
    public labelBulletScore: eui.Label;
    public labelScore: egret.BitmapText;
    public labelPowerScore: eui.Label;
    public toggleMusic: eui.ToggleButton;
    public labelTime: eui.Label;

    public startId: number = null;
    public reviveSeq: number = 1;
    public maxScore: number = null;
    private inited = false;
    private isSubmited = false;
    private constantSubmitSeq = 1;
    private needSubmitCount = 0; //实际分数减去ConstantSubmitScoreNum的次数
    private isSubmiting = false;
    public game: Game = null;

    // private submitedScore: number = 0;

    private _localScore: number = 0;
    public get localScore(): number {
        return this._localScore;
    }
    public set localScore(v: number) {
        this._localScore = v;

        if (this._localScore >= MConst.ConstantSubmitScoreNum) {
            let count = Math.floor(this._localScore / MConst.ConstantSubmitScoreNum);
            this.needSubmitCount += count;
            // let submitScore = MConst.ConstantSubmitScoreNum * count;
            // this.submitedScore += submitScore;
            this._localScore -=  MConst.ConstantSubmitScoreNum * count;
            if (!this.isSubmiting) {
                this.constantSubmit();
            }
        }
    }

    constructor(data?: any) {
        super(data);
        this.startId = data.startId;
        this.maxScore = data.maxScore;
    }

    onSkinComplete() {
        super.onSkinComplete();

        this.toggleMusic.selected = SoundMgr.instance.enabled;
        this.toggleMusic.addEventListener(eui.UIEvent.CHANGE, (evt: eui.UIEvent) => {
            SoundMgr.instance.enabled = (evt.target as eui.ToggleButton).selected;
        }, this);

        GameMgr.instance.init(this);
        this.game = new Game(this);

        //监听游戏结束
        this.game.onGameOver = () => {
            this.gameOver();
        }

        //监听游戏分数变化
        this.game.onScoreChange = (delta: number) => {
            this.localScore += delta;
        }

        //UI层置顶
        this.groupTop.touchThrough = true;
        this.addChild(this.groupTop);

        this.inited = true;

        this.labelScore = new egret.BitmapText();
        this.labelScore.font = RES.getRes("num_fnt");
        this.labelScore.x = 375;
        this.labelScore.y = 252;
        this.addChild(this.labelScore);

        //耦合引导
        if (GameMgr.instance.guideFlag == true) {
            GameMgr.instance.runGuide(0, this.game._car.posX - 6, this.game._car.posY - 62);
        }
    }

    private constantSubmit(score: number = MConst.ConstantSubmitScoreNum) {
        if (this.isSubmiting) {
            return;
        }
        if (this.needSubmitCount == 0) {
            return;
        } else if (this.needSubmitCount < 0) {
            //异常，有bug
            console.error("invalid needSubmitCount value");
            return;
        }

        this.isSubmiting = true;
        let seq = NetUtils.encryptSeq(this.constantSubmitSeq);

        return new Promise((resolve, reject) => {
            Net.sendPost(Net.Url.constantSubmit, {
                startId: this.startId,
                seq: seq,
                score: score,
                token: NetUtils.md5(this.startId.toString() + seq.toString() + score.toString() + "wzmsBank123")
            }, () => {
                this.constantSubmitSeq++;
                this.needSubmitCount--;
                this.isSubmiting = false;

                resolve();
            }, (res) => {
                this.isSubmiting = false;
                Net.defaultOnFail(res);
                reject();
            });
        });
    }

    onUpdate() {
        if (!this.inited) return;

        // this.localScore = this.game.score - this.submitedScore;
        this.labelBulletScore.text = "x" + this.game.bulletScore.toString()
        this.labelScore.text = this.game.score.toString();
        this.labelScore.x = 375 - this.labelScore.width / 2;
        this.labelPowerScore.text = this.game.powerScore.toString() + "%";
        this.updateTime();
    }

    private updateTime() {
        let temp = Math.ceil(this.game.timer / 1000);
        let second = temp % 60;
        let minute = (temp - second) / 60;
        let str = "";
        str += (minute < 10 ? "0" : "") + minute.toString();
        str += ":";
        str += (second < 10 ? "0" : "") + second.toString();
        this.labelTime.text = str;
    }


    gameOver() {
        this.finalSubmit().then((res) => {
            PanelCtrl.instance.show<GameOverPanel>(GameOverPanel).init({
                score: res.data.finalScore,
                topScore: res.data.maxScore,
                rewardUrl: (res.data.prize && res.data.prize.icon) || "",
                rewardName: (res.data.prize && res.data.prize.name) || ""
            });
        })
    }

    public async finalSubmit(propsId?: string, onSubmited?: () => void) {
        if (this.isSubmited) {
            return;
        }
        this.isSubmited = true;

        Loading.instace.show();
        if (this.needSubmitCount > 0) {
            if (!this.isSubmiting) {
                while (this.needSubmitCount > 0) {
                    await this.constantSubmit();
                }
            }
        }

        const score = this.game.score;
        let serverScore = this.localScore + (this.constantSubmitSeq - 1 + this.needSubmitCount) * MConst.ConstantSubmitScoreNum;
        if (serverScore != score) {
            console.error(`[score error] server:${serverScore} local:${score}`);
        } else {
            console.log(`[score] server:${serverScore} local:${score}`);
        }

        //中途提交最后一次
        if (this.localScore > 0) {
            this.needSubmitCount++;
            await this.constantSubmit(this.localScore);
            console.log("extra submit:" + this.localScore);
        }

        //滑块验证
        let validate = await new Promise<string>(resolve => {
            if (typeof GameMgr.instance.minEnableCaptchaScore == "number" && score >= GameMgr.instance.minEnableCaptchaScore) {
                initNECaptcha({
                    captchaId: MConst.captchaId,
                    callback: (ret: { validate: string }) => {
                        resolve(ret.validate);
                    }
                });
            } else {
                resolve("");
            }
        });


        return new Promise<any>((resolve, reject) => {
            //调用接口
            Net.sendPost(Net.Url.finalSubmit, {
                startId: this.startId,
                score: score,
                useSpId: propsId || "",
                token: NetUtils.md5(this.startId.toString() + score.toString() + "wzmsBank123"),
                validate: validate
            }, (res) => {
                Loading.instace.hide();
                resolve(res);
            }, (res) => {
                Net.defaultOnFail(res);
                reject(res);
            });
        });

    }

    onDestroy() {
        SoundMgr.instance.enabled = false;
        this.game.destroy();
    }
}

