import { Vec2 } from "cc";
import GBaseMode from "../GBaseMode";
import { GRoleUtil } from "../entity/GRole";
import { GTactical } from "../entity/GTactical";
import GRoleDefault from "../base/role/GRoleDefault";
import { Prefab } from "cc";
import { _decorator } from "cc";
import { instantiate } from "cc";
import { GPVPModePlayerEnum } from "./GPVPMode";
import { JNFrameInfo } from "../../../../extensions/ngame/assets/ngame/sync/frame/JNSyncFrame";
import { GMapLoop } from "../base/common/map/GMapLoop";
import { Node } from "cc";
import JNFrameTime from "../../../../extensions/ngame/assets/ngame/sync/frame/game/time/JNFrameTime";
import { TD, app } from "../../App";
import { v3 } from "cc";
import { v2 } from "cc";
import GFSMOnHookMode from "./OnHook/GFSMOnHookMode";
import { TB, TbGEntity } from "../../config/data/schema";
import PlayerTacticalData, { PlayerTacticalEvent } from "../../data/PlayerTacticalData";
import GRoleOnHookPlayerExpand from "../base/role/expand/OnHook/GRoleOnHookPlayerExpand";
import PlayerPetData from "../../data/PlayerPetData";
import { GUI } from "../../ui/UIConfig";
import { GOnHookPet, GOnHookPets } from "../../../../extensions/ngame/assets/ngame/message/proto";
import GOnHookManager, { GOnHookManagerEvent } from "../../manager/battle/mode/GOnHookManager";
import GRoleOnHookCreepsExpand from "../base/role/expand/OnHook/GRoleOnHookCreepsExpand";
import GPetAttribute from "../base/values/attribute/role/GPetAttribute";
import GDefaultMode from "./default/GDefaultMode";
import GOnHookData from "../../data/GOnHookData";
import { GModeEvent, GModeHitInfo } from "./GMode";
const { ccclass, property } = _decorator;

//挂机模式状态
export enum GOnHookModeState{
    GoTarget,//前往目标
    Attack, //攻击
    AttackEnd, //攻击结束
}

//角色
export enum GOnHookModePlayerEnum{
    PLAYER, //玩家
    ENEMY, //怪物
}

//玩家信息
export interface GOnHookInfo{
    //阵法
    tactical: GTactical;
}

/**
 * 挂机模式 无限出现小怪 (不是联机模式 该模式支持使用本地数据 和 API)
 */
@ccclass('GOnHookMode')
export default class GOnHookMode extends GDefaultMode<{},{}>{

    @property(Prefab)
    rolePrefab: Prefab = null;

    @property(Node)
    objects: Node = null;

    get scene():Node{
        return this.objects;
    }
    
    //玩家信息
    playerInfo:GOnHookInfo;
    //宠物信息
    enemyInfo:GOnHookInfo;
    
    //玩家宠物位置
    playerPos: Vec2 = new Vec2(-400,0);
    //怪物位置
    enemyPos: Vec2 = new Vec2(400,0);

    //玩家宠物
    playerRoles: GRoleDefault[] = [];
    //敌方宠物
    enemyRoles: GRoleDefault[] = [];

    //每一波怪的距离
    everyX:number = 600;

    //下一波怪的对战位置X
    _nextFightX:number = 0;
    get nextFightX(){return this._nextFightX}
    set nextFightX(value:number){
        //修改玩家阵法位置
        this.playerInfo.tactical.setOffset(this.playerPos.clone().add(v2(value,0)))
        this.enemyInfo.tactical.setOffset(this.enemyPos.clone().add(v2(value,0)))
        this._nextFightX = value;
    }

    fsm:GFSMOnHookMode;

    //是否允许攻击
    isAllowAttack:boolean = false;

    //添加监听事件
    addEvent(){
        app.event.on(PlayerTacticalEvent.UPDATE_TACTICAL,this.onUpdatePlayerPet,this);
        // app.event.on(GOnHookManagerEvent.UPDATE_MAP,this.onUpdateWorld,this);
    }
    //移除监听事件
    onDestroy(){
        super.onDestroy();
        app.event.off(PlayerTacticalEvent.UPDATE_TACTICAL,this.onUpdatePlayerPet,this);
        // app.event.off(GOnHookManagerEvent.UPDATE_MAP,this.onUpdateWorld,this);
    }

    onSyncInitSuccess():void{

        //初始化战斗
        console.log("GOnHookMode 模式初始化");

        //调整相机
        this.camera.enabled = true;
        let camreaPos = this.camera.node.worldPosition;
        this.camera.node.worldPosition = v3(0,750,camreaPos.z)

        //初始化状态机
        this.fsm = new GFSMOnHookMode(this);

        //更新场景
        this.onUpdateWorld();

        this.playerInfo = { tactical: GTactical.getTactical().setOffset(this.playerPos) };
        this.enemyInfo = { tactical: GTactical.getTactical(true).setOffset(this.enemyPos) };

        this.onUpdatePlayerPet();

        //添加监听
        this.addEvent();

        // //模拟请求生成宠物
        // app.socket.SendBack(GAction.MODE_ON_HOOK_SPAWN_PET,{
        //     type:GActionType.GOnHookPets,
        //     fun:(info:GOnHookPets) => {
        //         console.log("接受到野怪列表",info)
        //     }
        // })

        //生成玩家
        // this.playerInfo.roles.forEach((info,index) => this.onGenRole(GOnHookModePlayerEnum.PLAYER,index + 1,info))

        // //生成敌人
        // this.onResetGenerateEnemy();

    }

    //更新地图
    onUpdateWorld(){
        let info = TD.TbGOnHookMaps.get(GOnHookData.getIns().info.onHookMap);
        this.setWorldMap(info.mapId);
    }

    //更新页面
    onUpdateView(){

    }
    
    //更新玩家宠物
    onUpdatePlayerPet(){
        //获取玩家阵容
        let infos = PlayerTacticalData.getIns().getTacticalInfo();
        
        //移除不再阵容中的宠物
        let roles = [...this.getOnesRoleAlive(GOnHookModePlayerEnum.PLAYER)]
        roles.forEach(role => {
            let expand = role.getComponent(GRoleOnHookPlayerExpand);
            //如果宠物不再阵容中 则 移除宠物
            if(infos.indexOf(expand.petId) < 0){
                //移除宠物
                this.playerRoles.splice(this.playerRoles.indexOf(role),1);
                role.isDie = true;
            }
        })

        infos.forEach((petId,index) => {
            if(petId){
                this.onGenPlayerPet(index+1,petId);
            }
        })

    }

    //更新帧
    onSyncUpdate(dt: number,frame:JNFrameInfo, input?: {}){
        super.onSyncUpdate(dt,frame,input);
        this.onUpdateMap(dt);
        this.onUpdateCamera(dt);
        this.fsm.onUpdate(dt,frame);
    }

    //更新相机逻辑
    onUpdateCamera(dt:number){

        //如果没有敌人相机永远锁定最前面的宠物
        if(this.isAllowAttack && this.isHaveEnemy()){

            //如果有敌人则移动到战斗位置
            let cameraWorld = this.camera.node.worldPosition.clone();
            this.camera.node.worldPosition = cameraWorld.lerp(v3(this.nextFightX,cameraWorld.y,cameraWorld.z),(dt / 1000));

        }else{
            //获取冲到最前面的宠物
            let roles = this.getOnesRoleAlive(GOnHookModePlayerEnum.PLAYER);
            let frontRole = roles.sort((role1,role2) => role2.v2World.x - role1.v2World.x)[0];
            if(!frontRole) return;

            //设置相机 位置
            let cameraWorld = this.camera.node.worldPosition.clone();
            this.camera.node.worldPosition = cameraWorld.lerp(v3(frontRole.v2World.x,cameraWorld.y,cameraWorld.z),(dt / 1000));
        }

    }

    //生成玩家宠物
    onGenPlayerPet(index:number,petId:number){

        //如果场上有这个宠物则更新阵法位置
        let passRole:GRoleDefault;
        this.playerRoles.forEach(role => {
            if(role.getComponent(GRoleOnHookPlayerExpand).petId == petId)
                passRole = role;
        })
        if(passRole){
            //更新宠物阵法位置
            passRole.tacticalIndex = index;
            return;
        }


        //获取要生成的宠物
        let info = PlayerPetData.getIns().petIdQueryPetInfo(petId);
        if(!info){
            app.layer.Open(GUI.Tips,{text:"未拥有当前上阵的宠物"});
            return;
        }
        let role = this.onGenRole(GOnHookModePlayerEnum.PLAYER,index,TD.TbGRole.get(info.petTbId));
        //向宠物添加 OnHook 扩展
        let expand = role.node.addComponent(GRoleOnHookPlayerExpand);
        expand.petId = petId;

        //添加宠物属性
        role.onEffectiveValue(new GPetAttribute(info));

    }

    //生成野怪
    onGenCreeps(index:number,creeps:GOnHookPet){

        let role = this.onGenRole(GOnHookModePlayerEnum.ENEMY,index,TD.TbGRole.get(creeps.petTbId));

        //向野怪添加扩展
        let expand = role.node.addComponent(GRoleOnHookCreepsExpand);
        expand.creeps = creeps;

        //添加野怪属性
        role.onEffectiveValue(new GPetAttribute({
            petId:0,               
            petPlayerId:0,         
            petTbId:creeps.petTbId,        
            petLevel:creeps.petLevel,            
            petStar:0,             
            petStarExp:0,          
        }));

    }

    //生成宠物
    onGenRole(type: GOnHookModePlayerEnum,index:number,info:TB.TbGRole):GRoleDefault {

        let tactical = this.getInfo(type).tactical;
        let pos:Vec2 = this.getInfo(type).tactical.getPosition(index);
        if(!pos) return;
        let role = instantiate(this.rolePrefab);

        let entity = role.getComponent(GRoleDefault);
        //初始化
        entity.onInit(type,info,tactical,index);

        //绑定寻敌
        entity.onQueryEunmy = () => {
            return this.getEnumy(entity,type);
        }

        //绑定死亡回调
        entity.addKillBackEvent(this.onRoleKillBack.bind(this))
        //绑定受击回调
        entity.addHitCallback(this.onHitBack.bind(this));

        this.addGObject(entity,tactical.getPosition(index));

        this.getOnesRole(type).push(entity);

        return entity;

    }

    //获取配置
    getInfo(type: GOnHookModePlayerEnum): GOnHookInfo {
        if(type == GOnHookModePlayerEnum.PLAYER) return this.playerInfo;
        if(type == GOnHookModePlayerEnum.ENEMY) return this.enemyInfo;
    }

    //获取阵营宠物
    getOnesRole(type: GOnHookModePlayerEnum):GRoleDefault[]{
        if(type == GOnHookModePlayerEnum.PLAYER) return this.playerRoles;
        if(type == GOnHookModePlayerEnum.ENEMY) return this.enemyRoles;
    }

    //获取存活的宠物
    getOnesRoleAlive(type: GOnHookModePlayerEnum):GRoleDefault[]{
        if(type == GOnHookModePlayerEnum.PLAYER) return this.playerRoles.filter(role => !!role.get());
        if(type == GOnHookModePlayerEnum.ENEMY) return this.enemyRoles.filter(role => !!role.get());
    }

    //获取敌人
    getEnumy(player:GRoleDefault,type:GOnHookModePlayerEnum):GRoleDefault{

        if(!this.isAllowAttack) return null;

        let enumyOnes = GOnHookModePlayerEnum.ENEMY
        //如果是ENEMY 则 它的敌人是 PLAYER
        if(type == GOnHookModePlayerEnum.ENEMY) enumyOnes = GOnHookModePlayerEnum.PLAYER

        //获取敌人
        let roles = this.getOnesRoleAlive(enumyOnes);

        //通过距离获取最近的敌人
        if(roles[0]){
            let len = Math.abs(Vec2.distance(player.v2World,roles[0].v2World));
            let enumy = roles[0];

            for (let index = 0; index < roles.length; index++) {
                const role = roles[index];
                let tLen;
                if(tLen = Math.abs(Vec2.distance(player.v2World,role.v2World)) < len){
                    enumy = role;
                    len = tLen;
                }
                
            }

            return enumy;
        }else{
            return null;
        }

    }

    //生成敌人
    onResetGenerateEnemy(){
        this.enemyRoles = [];
        let sign = TD.TbGOnHookMaps.get(GOnHookData.getIns().info.onHookMap).sign;
        let table:{data:TbGEntity.TOnHookLevel} = TD[sign].get(GOnHookData.getIns().info.levelId);

        for (let index = 0; index < table.data.petSize; index++) {
            //获取敌人
            let creeps = GOnHookManager.getIns().getNextCreeps();
            if(!creeps) return; //没有获取到野怪则返回
            this.onGenCreeps(index + 1,creeps);
        }

        this.onUpdatePlayerPet();
        // this.enemyInfo.roles.forEach((info,index) => this.onGenRole(GOnHookModePlayerEnum.ENEMY,index + 1,info));
    }

    //角色死亡回调
    onRoleKillBack(role:GRoleDefault){
        //死亡销毁
        JNFrameTime.getInstance().setTimeout(() => {
            if(role.isValid)
                role.node.destroy()
        },3000)

        //如果死亡的是野怪则通知野怪死亡
        if(role.getComponent(GRoleOnHookCreepsExpand)){
            GOnHookManager.getIns().onKillSreeps(role.getComponent(GRoleOnHookCreepsExpand).creeps);
        }

        //清理
        this.onClearCache();

    }

    //角色受击回调
    onHitBack(role:GRoleDefault,hit:number){

        if(!role.get()) return;

        //添加受击显示
        app.event.emit(GModeEvent.HIT,{
            mode:this,
            role:role,
            hit:hit,
            world:role.v2World,
            camera:this.camera,
        });

    }

    //清理缓存
    onClearCache(){

        //清理宠物
        let roles = [...this.playerRoles];
        roles.forEach(role => {
            if(!role.get()){
                this.playerRoles.splice(this.playerRoles.indexOf(role),1);
            }
        })
        roles = [...this.enemyRoles];
        roles.forEach(role => {
            if(!role.get()){
                this.enemyRoles.splice(this.enemyRoles.indexOf(role),1);
            }
        })

    }

    //是否有怪物
    isHaveEnemy(){
        if(!this.isAllowAttack) return [];
        return this.getOnesRoleAlive(GOnHookModePlayerEnum.ENEMY).filter(role => !!role.get()).length > 0;
    }

    //前往下一个目标
    onNextTarget(){

        //下一个目标点
        this.nextFightX = this.nextFightX + this.everyX;

    }

}