import { OTWSceneManager } from "./OTWSceneManager";
import { FrameSyncExecutor } from "../common/FrameSyncExecutor";
import { ConnectionInputOperate } from "../../shared/gameClient/GameSyncFrame";

import { IArea, ICountry, IMap, InputType, IPlayer, ITroop } from "../../shared/gameClient/games/OccupationTheWarModels";
import { Component, _decorator, Node, Prefab, instantiate, PhysicsSystem, Vec3, UICoordinateTrackerComponent, EventHandler, EventTouch, SpriteComponent, Sprite, SpriteFrame, Collider, ICollisionEvent, ITriggerEvent } from "cc";
import { OTWAreaFlagComponent } from "./Components/OTWAreaFlagComponent";
import { OTWFlagComponent } from "./Components/OTWFlagComponent";
import { OTWAreaData } from "./Data/OTWAreaData";
import { OTWAreaComponent } from "./Components/OTWAreaComponent";
import { OTWTroopComponent } from "./Components/OTWTroopComponent";
import { OTWTroopData } from "./Data/OTWTroopData";
import { PHY_GROUP } from "./Const";
import { LinkMainNodeComponent } from "../common/LinkMainNodeComponent";
import { OTWGameData } from "./Data/OTWGameData";
const { ccclass, property } = _decorator;

@ccclass('OTWGameManager')
export class OTWGameManager extends Component {

    @property({ type: Node, tooltip: "存放所有游戏对象的3D节点" })
    public GameObjContainer?: Node;
    @property({ type: Node, tooltip: "存放所有Flag的UI节点" })
    public GameObjFlagUI?: Node;

    @property({ type: Prefab, tooltip: "地域模型预制体" })
    public AreaPrefab?: Prefab;
    @property({ type: Prefab, tooltip: "地域旗帜UI的预制体" })
    public AreaFlagPrefab?: Prefab;
    @property({ type: Prefab, tooltip: "士兵渲染模型预制体" })
    public TroopRenderPrefab?: Prefab;
    @property({ type: Prefab, tooltip: "士兵碰撞体预制体" })
    public TroopColliderPrefab?: Prefab;
    @property({ type: Prefab, tooltip: "士兵旗帜UI的预制体" })
    public TroopFlagPrefab?: Prefab;

    public sceneMgr!: OTWSceneManager;
    private frameSyncExecutor: FrameSyncExecutor | null = null;

    private gameData: OTWGameData = {
        map: null,
        allAreaInfo: [],
        allAttackingTroopInfo: [],
        myPlayer: null,
        myCountryId: null,
    };
    private getGameData = () => this.gameData;

    start() {
        this.sceneMgr.TouchCtrl.touchRayGetObjHandler = (isFrom, ray) => {
            if (!this.gameData.myPlayer) return null;
            if (!PhysicsSystem.instance.raycastClosest(ray, PHY_GROUP.Area)) {
                //没点到area节点,忽略
                return null;
            }
            var collider = PhysicsSystem.instance.raycastClosestResult.collider;
            var group = collider.getGroup();
            var node = collider.node;
            var mainNode = node?.getComponent(LinkMainNodeComponent)?.MainNode;
            var areaInfoComp = mainNode?.getComponent(OTWAreaComponent);
            if (!areaInfoComp) return null;
            if (isFrom) {
                if (this.gameData.myPlayer.countryId != areaInfoComp.areaInfo.area.countryId) {
                    //不是自己国家的地域,不能操作!
                    return null;
                }
            }

            return areaInfoComp.areaInfo.area;
        };
        this.sceneMgr.TouchCtrl.touchFromToHandler = (fromArea: IArea, toArea: IArea) => {
            if (!fromArea || !toArea) {
                return;
            }

            this.frameSyncExecutor?.sendInputFrame(
                {
                    inputType: InputType.Attack,
                    countryId: fromArea.countryId,
                    fromAreaIndex: fromArea.areaIndex,
                    toAreaIndex: toArea.areaIndex,
                }
            );
        };

        //PhysicsSystem.instance.enable = false;
        PhysicsSystem.instance.autoSimulation = false;
    }

    public enterGame() {
        this.frameSyncExecutor = new FrameSyncExecutor(this.sceneMgr.gameClient!, this,
            (stateData) => this.onSyncStateData(stateData),
            (dt) => this.executeOneFrame(dt),
            () => this.gameData.map);
    }
    public async exitGame() {
        await this.frameSyncExecutor?.dispose();
        this.frameSyncExecutor = null;
    }

    clearMap() {
        this.gameData.allAreaInfo.forEach(n => {
            n.areaNode.parent?.removeChild(n.areaNode);
            n.flagNode.parent?.removeChild(n.flagNode);
        });
        this.gameData.allAreaInfo.length = 0;

        this.gameData.allAttackingTroopInfo.forEach(n => {
            n.renderNode.parent?.removeChild(n.renderNode);
            n.troopNode.parent?.removeChild(n.troopNode);
            n.flagNode.parent?.removeChild(n.flagNode);
        });
        this.gameData.allAttackingTroopInfo.length = 0;
    }
    createArea(area: IArea, country: ICountry): OTWAreaData {
        var areaInfo = OTWAreaComponent.createNode(this.AreaPrefab!, this.AreaFlagPrefab!, this.getGameData,
            area, country, this.sceneMgr.MainCamera!, this.node, this.GameObjFlagUI!, this.GameObjContainer!);
        this.gameData.allAreaInfo[areaInfo.area.areaIndex] = areaInfo;

        var collider = areaInfo.areaNode.getComponentInChildren(Collider);
        collider?.on('onTriggerEnter', (event: ITriggerEvent) => { this.onTriggerEnter(event) });

        return areaInfo;
    }
    createTroop(troop: ITroop, country: ICountry): OTWTroopData {
        var troopInfo = OTWTroopComponent.createNode(this.TroopRenderPrefab!, this.TroopColliderPrefab!, this.TroopFlagPrefab!,
            this.getGameData, troop, country, this.sceneMgr.MainCamera!, this.node,
            this.GameObjFlagUI!, this.GameObjContainer!);
        this.gameData.allAttackingTroopInfo[troopInfo.troop.troopIndex] = troopInfo;

        var collider = troopInfo.troopNode.getComponentInChildren(Collider);
        collider?.on('onTriggerEnter', (event: ITriggerEvent) => { this.onTriggerEnter(event) });

        return troopInfo;
    }

    onTriggerEnter(event: ITriggerEvent) {
        console.log(event.type, event);
    }


    onSyncStateData(stateData: any) {
        //需要同步状态数据,当作重新初始化游戏数据
        this.clearMap();
        this.gameData.map = stateData;
        if (!this.gameData.map) return;
        this.gameData.myPlayer = this.gameData.map.allPlayer[this.sceneMgr.gameClient!.connectionId];
        if (this.gameData.myPlayer) {
            this.gameData.myCountryId = this.gameData.myPlayer.countryId;
        }

        this.gameData.map?.allArea.forEach(a => {
            var country = this.gameData.map!.allCountry[a.countryId!];
            this.createArea(a, country);
        });
        this.gameData.map?.allAttackingTroop.forEach(t => {
            var country = this.gameData.map!.allCountry[t.countryId!];
            this.createTroop(t, country);
        });
    }

    onAreaFlagUIUpdate(localUIPos: Vec3, distanceScale: number, customEventData: string) {
        var areaIndex = parseInt(customEventData);
        var areaInfo = this.gameData.allAreaInfo[areaIndex];
        areaInfo.flagNode.setPosition(localUIPos);
    }
    onTroopFlagUIUpdate(localUIPos: Vec3, distanceScale: number, customEventData: string) {
        var troopIndex = parseInt(customEventData);
        var troopInfo = this.gameData.allAttackingTroopInfo[troopIndex];
        troopInfo.flagNode.setPosition(localUIPos);
        console.log('onTroopFlagUIUpdate',localUIPos, customEventData);
    }


    execInput_NewPlayer(connId: string, inputFrame: ConnectionInputOperate, dt: number): void {
        if (!this.gameData.map) return;
        //新玩家进来,是取代某个电脑玩家
        var player: IPlayer = {
            connId: connId,
            userName: inputFrame.userName,
            countryId: inputFrame.countryId,
        };
        this.gameData.map.allPlayer[player.connId] = player;
        var country = this.gameData.map.allCountry[player.countryId];
        country.playerConnId = player.connId;

        //更新flag
        for (let i = 0; i < this.gameData.map.allArea.length; i++) {
            var a = this.gameData.map.allArea[i];
            if (a.countryId != player.countryId) continue;
            this.gameData.allAreaInfo[a.areaIndex]?.flagComp?.updateShow();
        }

        if (connId == this.sceneMgr.gameClient?.connectionId) {
            this.gameData.myPlayer = this.gameData.map.allPlayer[this.sceneMgr.gameClient!.connectionId];
            if (this.gameData.myPlayer) {
                this.gameData.myCountryId = this.gameData.myPlayer.countryId;
            }
        }
    }
    execInput_RemovePlayer(connId: string, inputFrame: ConnectionInputOperate, dt: number): void {
        if (!this.gameData.map) return;
        //玩家离开,将该玩家改成电脑玩家
        var player = this.gameData.map.allPlayer[connId];
        if (!player) {
            return;
        }
        delete this.gameData.map.allPlayer[connId];
        var country = this.gameData.map.allCountry[player.countryId];
        if (!country) {
            return;
        }
        country.playerConnId = null;
        delete this.gameData.map.allCountry[player.countryId];
        //更新flag
        for (let i = 0; i < this.gameData.map.allArea.length; i++) {
            var a = this.gameData.map.allArea[i];
            if (a.countryId != player.countryId) continue;
            this.gameData.allAreaInfo[a.areaIndex]?.flagComp?.updateShow();
        }
    }
    execInput_Attack(connId: string, inputFrame: ConnectionInputOperate, dt: number): void {
        if (!this.gameData.map) return;
        var country = inputFrame.countryId ? this.gameData.map.allCountry[inputFrame.countryId] : null;
        if (!country) {
            //没有国家,则不能发动攻击
            return;
        }
        var fromArea = this.gameData.map.allArea[inputFrame.fromAreaIndex];
        if (fromArea.troopsCurr <= 0) return;//兵力为0则不能发动攻击

        var troop: ITroop = {
            troopIndex: this.gameData.map.allAttackingTroop.length,
            countryId: country.countryId,
            fromAreaIndex: inputFrame.fromAreaIndex,
            toAreaIndex: inputFrame.toAreaIndex,
            troopsCount: fromArea.troopsCurr,
            x: fromArea.x,
            z: fromArea.z,
        };
        this.gameData.map.allAttackingTroop[troop.troopIndex] = troop;
        this.createTroop(troop, country);
        fromArea.troopsCurr = 0;
        fromArea.troopsCurrCalculate = 0;
        var fromAreaInfo = this.gameData.allAreaInfo[fromArea.areaIndex];
        fromAreaInfo.flagComp.updateShow();
    }
    executeOneFrame(dt: number): void {
        //运算增兵
        for (let i = 0; i < this.gameData.allAreaInfo.length; i++) {
            this.gameData.allAreaInfo[i].areaComp.updateData(dt);
        }
        //物理分离
        //PhysicsSystem.instance.step(dt, dt);
        //PhysicsSystem.instance.emitEvents();
    }

    update(dt:number){
        //运算移动以及产生的效果
        for (let i = 0; i < this.gameData.allAttackingTroopInfo.length; i++) {
            this.gameData.allAttackingTroopInfo[i].troopComp.updateData(dt);
        }
    }


    /*
        playerUpdate(player: PlayerData, dt: number) {
            if (player.moveDirX != 0 || player.moveDirZ != 0) {
                //有移动,转向直接生效,小方块,懒得转忽略
                var distance = player.speed * dt;//本帧移动的距离
    
                var oldX = player.x;
                var oldZ = player.z;
    
                var cosA = Math.cos(player.moveAcuteRad);
                var sinA = Math.sin(player.moveAcuteRad);
    
                var stepReC = distance;
    
                var stepReX = player.moveDirZ == 0 ?
                    player.moveDirX * distance : cosA * stepReC * player.moveDirX;//如果Z方向没动,直接用X方向的距离
                var stepReZ = player.moveDirX == 0 ?
                    player.moveDirZ * distance : sinA * stepReC * player.moveDirZ;//如果X方向没动,直接用Z方向的距离
    
                player.x = oldX + stepReX;
                player.z = oldZ + stepReZ;
            }
        }*/

}