import {
    _decorator,
    Camera, Color,
    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";

import mobx from "mobx";
import { getUrlParam } from "../../Utils/Utils";
import { Snake } from "./Snake";

const { reaction, } = mobx;

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() {

        if (getUrlParam("width")) {
            Global.MAP_WIDTH = +getUrlParam("width");
            Global.MAP_HEIGHT = +getUrlParam("height");
            Global.HALF_MAP_WIDTH = Global.MAP_WIDTH * 0.5;
            Global.HALF_MAP_HEIGHT = Global.MAP_HEIGHT * 0.5;
        }
        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);

        this.debug();

    }

    debugLabel: Label = null;

    debug() {
        return;
        const debugNode = new Node("debug");
        debugNode.layer = this.killTxt.node.layer;
        debugNode.addComponent(UITransform);
        this.debugLabel = debugNode.addComponent(Label);
        this.debugLabel.color = Color.clone(Color.BLACK);
        this.killTxt.node.parent.addChild(debugNode);
    }

    async start() {

        await this.initStage();

        this.isStart = true;
    }

    onDestroy() {
        if (MainGame._ins == this) {
            MainGame._ins = null;
        }

        this.reactionLenDisposer?.();
        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(gameStore.startInfo.startId);
                if (gameSuc) {
                    await changeScene(MainGame);
                } else {
                    changeScene(HomeScene);
                }
            }

        } else if (currentStage == 2) {
            const { time, energy } = Global.stageConfig[1];
            if (MainGame.ins.player.energy >= energy) {
                const submitSuc = await gameStore.submitTwo();
                if (submitSuc) {
                    const gameSuc = await gameStore.startGame(gameStore.startInfo.startId);
                    if (gameSuc) {
                        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 {energy, killNum, luckNum} = gameStore.gameInfo || {};

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

    reactionLenDisposer = null;
    async initStage() {
        let { currentStage } = gameStore.startInfo;

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

        // 初始化食物
        FoodManger.ins.init(gameStore.startInfo?.barrierFlag ? 250 : 500);

        if (getUrlParam("aiNum")) {
            this.initAnimal(+getUrlParam("aiNum"));
        } else {
            // 初始化NPC
            this.initAnimal(15);
            // this.initAnimal(1);
        }

        PreCd.ins.node.active = true;

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

            PropManager.ins.init(gameStore.startInfo?.barrierFlag ? 1 : 3);
            CardManager.ins.init(gameStore.startInfo?.barrierFlag ? 1 : 3);
            LuckyBagManager.ins.init();
            await Target.ins.showTarget3();
            await PreCd.ins.startCd();

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

            this.reactionLenDisposer = reaction(
                () => gameStore.gameInfo.energy,
                async (newEnergy) => {
                    if (newEnergy >= energy) {
                        if (this.isOver) return;
                        this.isOver = true;
                        const submitSuc = await gameStore.submitTwo();
                        if (submitSuc) {
                            const gameSuc = await gameStore.startGame(gameStore.startInfo.startId);
                            if (gameSuc) {
                                await changeScene(MainGame);
                            } else {
                                changeScene(HomeScene);
                            }
                        }
                    }
                }
            );

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

        // let now = performance.now();
        // let temp = 0;

        this.player.onUpdate(dt);

        // temp = performance.now();
        // console.log(`玩家更新：${temp - now}ms`);
        // now = temp;

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

        // 更新NPC移动
        this.animalNode.children.forEach(child => {
            child.getComponent(AISnake)?.onUpdate(dt);
            // temp = performance.now();
            // console.log(`ai更新：${temp - now}ms`);
            // now = temp;
        });

        // temp = performance.now();
        // console.log(`ai更新：${temp - now}ms`);
        // now = temp;


        if (this.debugLabel) {
            let totalBody = 0;
            this.animalNode.children.forEach((child) => {
                totalBody += child.getComponent(Snake).length;
            });

            this.debugLabel.string = `
                food: ${FoodManger.ins.node.children.length}
                body: ${totalBody}
                节数: ${this.player.length}
            `;
        }
    }

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

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

        const skin = [
            "ai橙",
            "ai绿",
            "ai蓝色",
            "ai蓝",
            "default",
            "newYear2025",
        ];
        node.getComponent(AISnake)?.init({
            nickName: nickName,
            tag: tag,
            x, y,
            // x: 50,
            // y: 50,
            // bodyCount: 100,
            angle: math.randomRange(0, 360),
            skinName: skin[math.randomRangeInt(0, skin.length)]
        });
        this.animalNode.addChild(node);
    }

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

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

}