import {
    _decorator,
    Camera,
    director, game, instantiate,
    Label,
    math,
    Node,
    PhysicsSystem2D,
    Prefab,
    UITransform,
} from "cc";
import { FoodManger } from "./Manager/FoodManger";
import { Global, SkinName } from "./Global";
import { Events, GameState } from "./Common/Enums";
import { changeScene, showPanel, showToast } from "../../../Module/UIFast";
import Scene from "../../../Module/Scene";
import { Player } from "./Player";
import { AISnake } from "./AISnake";
import { aiPool, clearAllPool } from "./Manager/CommonPool";
import { useNick } from "./Common/AINick";
import { observer, render } from "../../store/decorators";
import gameStore from "../../store/gameStore";
import { PreCd } from "./Components/PreCd";
import { Target } from "./Components/Target";
import { PropManager } from "./Manager/PropManager";
import { CardManager } from "./Manager/CardManager";
import { LuckyBagManager } from "./Manager/LuckyBagManager";
import GameFailPanel from "../../Panels/GameFailPanel";
import { GameLoading } from "./GameLoading";
import { HomeScene } from "../HomeScene";
import { sendWebNet, WebNetName } from "../../Utils/WebNet/WebNet";
import GameRevivePanel from "../../Panels/GameRevivePanel";
import store from "../../store/store";
import { AudioMgr } from "../../../core_tgx/base/AudioMgr";

const { ccclass, property } = _decorator;

@observer
@ccclass("MainGame")
export class MainGame extends Scene {

    static bundle: string = "MainGame";
    static skin: string = "MainGame";

    private static _ins: MainGame = null;
    static get ins(): MainGame {
        return MainGame._ins;
    }

    constructor() {
        super();
        MainGame._ins = this;
    }


    @property(Prefab)
    private animalPrefab: Prefab = null;

    @property(Node) private uiBg: Node = null;

    @property(Player) player: Player = null;

    @property(Node) animalNode: Node = null;

    @property(Camera) camera: Camera = null;

    @property({ type: Label, group: "UI" }) killTxt: Label = null;
    @property({ type: Label, group: "UI" }) lengthTxt: Label = null;
    @property({ type: Label, group: "UI" }) luckyNum: Label = null;

    private isStart: boolean = false;
    private isOver: boolean = false;

    async onLoad() {

        PhysicsSystem2D.instance.enable = true;
        // PhysicsSystem2D.instance.gravity = math.Vec2.ZERO;
        // PhysicsSystem2D.instance.debugDrawFlags = EPhysics2DDrawFlags.Aabb |
        //     EPhysics2DDrawFlags.Pair |
        //     EPhysics2DDrawFlags.CenterOfMass |
        //     EPhysics2DDrawFlags.Joint |
        //     EPhysics2DDrawFlags.Shape;

        this.uiBg.getComponent(UITransform)
            .setContentSize(Global.MAP_WIDTH, Global.MAP_HEIGHT);

        // 注册事件
        director.on(Events.Death, this.playerDeath, this);
    }

    async start() {

        await this.initStage();

        this.isStart = true;
    }

    onDestroy() {
        if (MainGame._ins == this) {
            MainGame._ins = null;
        }
        director.off(Events.Death, this.playerDeath, this);
        // this.player.node.destroy();
        clearAllPool();
    }

    playerDeath = async () => {
        if (this.isOver) return;
        this.isOver = true;

        const { currentStage } = gameStore.startInfo;
        AudioMgr.ins.playOneShot("audio/游戏失败音效");

        if (currentStage == 1) {
            showPanel(GameFailPanel);
        } else if (currentStage == 2) {
            showPanel(GameFailPanel);
        } else {
            await this.gameOver();
        }

    };

    review = async () => {
        await PreCd.ins.startCd();
        this.isOver = false;
        this.node.addChild(this.player.node);
        this.player.revive();
    };

    cdOver = async () => {
        if (this.isOver) return;
        this.isOver = true;

        const { currentStage } = gameStore.startInfo;

        if (currentStage == 1) {
            const submitSuc = await gameStore.submitOne();
            if (submitSuc) {
                const gameSuc = await gameStore.startGame();
                if (gameSuc) {
                    // await changeScene(GameLoading, {
                    //     callBack: async () => {
                    await changeScene(MainGame);
                    // }
                    // });
                } else {
                    changeScene(HomeScene);
                }
            }

        } else if (currentStage == 2) {

            const { time, length } = Global.stageConfig[1];
            // TODO 判断条件
            if (MainGame.ins.player.length >= length) {
                const submitSuc = await gameStore.submitTwo();
                if (submitSuc) {
                    const gameSuc = await gameStore.startGame();
                    if (gameSuc) {
                        // await changeScene(GameLoading, {
                        //     callBack: async () => {
                        await changeScene(MainGame);
                        // }
                        // });
                    } else {
                        changeScene(HomeScene);
                    }
                }
            } else {
                showPanel(GameFailPanel);
            }

        } else {

        }
    };

    async gameOver() {
        const {
            success,
            data
        } = await sendWebNet(WebNetName.queryReviveData, { startId: gameStore.startInfo.startId });
        if (!success) {
            const submitSuc = await gameStore.finalSubmit();
        } else {
            const {
                creditsNum, reviveEachNum,
                creditsReviveTimes, shareReviveTimes, cardReviveTimes,
                reviveCardNum
            } = data;

            if (
                (creditsReviveTimes > 0 || reviveEachNum > creditsNum)
                && shareReviveTimes > 0
                && (cardReviveTimes > 0 || reviveCardNum <= 0)
            ) {
                const submitSuc = await gameStore.finalSubmit();
            } else {
                // 复活弹窗
                showPanel(GameRevivePanel, data);
            }
        }
    }

    @render
    render() {
        const {length, killNum, luckNum} = gameStore.gameInfo || {};

        this.lengthTxt.string = `${length}`;
        this.killTxt.string = `${killNum}名`;
        this.luckyNum.string = `×${luckNum + gameStore.startInfo?.accumulateLuckNum || 0}`;
    }

    async initStage() {
        const { currentStage } = gameStore.startInfo;

        // 初始化玩家
        this.player.init({
            // initEnergy: 10000
            tag: this.player.tag,
            nickName: "我",
            skinName: SkinName[gameStore.startInfo.currentDressUp],
        });

        // 初始化食物
        FoodManger.ins.init(300);

        // 初始化NPC
        this.initAnimal(20);
        // this.initAnimal(1);

        PreCd.ins.node.active = true;

        if (!currentStage || currentStage == 3) {

            PropManager.ins.init(10);
            CardManager.ins.init(10);
            LuckyBagManager.ins.init();
            await Target.ins.showTarget3();
            await PreCd.ins.startCd();

        } else if (currentStage == 2) {
            const { time } = Global.stageConfig[1];
            Target.ins.totalCd = Target.ins.cd = time;
            await Target.ins.showTarget2();
            await PreCd.ins.startCd();
            Target.ins.startCd(time, this.cdOver);
        } else if (currentStage == 1) {
            const { time } = Global.stageConfig[0];
            Target.ins.totalCd = Target.ins.cd = time;
            await Target.ins.showTarget1();
            await PreCd.ins.startCd();
            Target.ins.startCd(time, this.cdOver);

        }
    }

    update(dt: number) {
        if (!this.isStart) return;

        this.player.onUpdate(dt);

        // 更新相机位置
        this.camera.node.setPosition(this.player.head.position);

        // 更新NPC移动
        this.animalNode.children.forEach(child => {
            child.getComponent(AISnake)?.onUpdate(dt);
        });
    }

    initAiSnake(nickName?: string, tag?: number) {
        const node = instantiate(this.animalPrefab);

        const { x, y } = Global.getRandomPosition(100);

        node.getComponent(AISnake)?.init({
            nickName: nickName,
            tag: tag,
            x, y,
            // x: 50,
            // y: 50,
            // bodyCount: 100,
            angle: math.randomRange(0, 360),
            skinName: Math.random() > 0.5 ? SkinName.sp_decoration_default : SkinName.sp_skin_snake_year,
        });
        this.animalNode.addChild(node);
    }

    async initAnimal(count: number) {
        const nickArr = useNick(count);

        for (let i = 0; i < count; i++) {
            this.initAiSnake(nickArr[i]);
        }
    }

}