import { _decorator, Node, Tween, Vec3, ProgressBar, UIOpacity, tween, Label, SkeletalAnimation, Animation, SphereCollider, CylinderCollider, MeshCollider, Collider} from 'cc';
import { Game } from './Game';
import { Player } from './Player';
import { Utils } from '../utils/Utils';
import { ResUtil } from '../utils/ResUtil';
import MsgHints from '../utils/MsgHints';
import { userIns } from '../data/UserData';
import { autoBind } from '../extend/AutoBind';
import { BaseExp } from '../core/base/BaseExp';
import { GunBase } from '../items/base/GunBase';
import { PoolManager } from '../core/manager/PoolManager';
import { audioMgr } from '../core/manager/AudioManager';
import { Constants } from '../data/Constants';
const { ccclass, property } = _decorator;


//部位类型
export enum EPartType {
    head = "headCollider",  //头部的碰撞体
    body = "bodyCollider",  //身体的碰撞体
    tank = "tankCollider", //坦克的碰撞体
    shield = "shieldCollider", //盾的碰撞体
    sundries = "sundriesCollider", //杂物的碰撞体
}

//敌人动作类型
export enum EAnimType {
    idle = "idle",  //idle 待机状态
    die = "die",  //die 死亡状态
    shoot = "shoot", //shoot 射击状态
    walk = "walk", //shoot 行走状态
}

//敌人类型枚举
export enum EnemyType {
    SoldierPistol = 10001,    // 大兵 - 普通士兵，使用手枪
    SniperSoldier = 10002,   // 狙击兵 - 远程攻击单位，使用狙击枪
    ShieldSoldier = 10003,   // 盾牌兵 - 高生命值防御单位，使用手枪和盾牌
    SnipeCaptain = 20001,    // 狙击队长 - BOSS单位，使用强力狙击枪
    ScatterCaptain = 20002, // 机枪队长 - BOSS单位，使用高射速机关枪
    Tank = 20003,           // 坦克 - BOSS单位，高生命值重型单位
    GeneralPistol = 20004   // 将军 - BOSS单位，综合型强力敌人
}

//武器类型枚举
export enum WeaponType {
    Pistol = 1001,    // 大兵手枪 将军手枪
    Sniper = 1002,    // 狙击兵狙击枪 狙击队长狙击枪
    Shield = 1003,    // 盾牌兵盾牌
    Scatter = 1005,   // 机枪队长机关枪
    Tank_Pao = 1006, // 坦克
}

@ccclass('Enemy')
export class Enemy extends BaseExp {
    @autoBind({type: ProgressBar,tooltip: "敌人血量"})
    public hpBar: ProgressBar  = null!;
    @autoBind({type: Node,tooltip: "敌人受伤节点"})
    public hurt_num: Node  = null!;
    @autoBind({type: Collider,tooltip: "敌人头部"})
    public headCollider: Collider  = null!;
    @autoBind({type: Collider,tooltip: "敌人身体"})
    public bodyCollider: Collider  = null!;
    @autoBind({type: Collider,tooltip: "坦克身体"})
    public tankCollider: Collider  = null!;
    @autoBind({type: Node,tooltip: "坦克行走"})
    public tank_walk: Node  = null!;
    @autoBind({type: Node,tooltip: "坦克射击"})
    public tank_shoot: Node  = null!;
    //敌人动画节点
    private skeletalAnim: SkeletalAnimation = null!;

    //根据敌人类型动态获取
    public enemyNode: Node  = null!;
    public oTween: Tween<object>;//敌人透明变化
    public defaultSpeed: number = 0;
    public speed: number = 0;
    public isDead: boolean = false;

    //拥有的枪
    public gun: GunBase = null;
    //盾的节点
    public shieldNode: Node  = null!;
    //拥有的盾可以使用的血量
    private _shieldHp: number = 0;
    public set shieldHp(value: number) {
        this._shieldHp = value;
        if(this._shieldHp <= 0){
           this.removeShield();
        }
    }
    public get shieldHp(): number {
        return this._shieldHp;
    }

    //当前金币的值
    public goldCount : number = 0;
    //玩家
    public player: Player = null!;
    //运动方向
    public moveDir: Vec3 = new Vec3();
    //设置的血量
    public totalHP: number = 0;
    //是否是没打死逃逸
    public escape: boolean = false;
    //敌人数据
    public data: any = null;
    //是否能锁定攻击对象了
    public isCanLock: boolean = false;
    //是否是在开火
    private isFire: boolean = false;

    //敌人行走的路径
    public pathList: Array<Vec3> = [];
    //当前行走的位置
    public curMoveIndex: number = 0;
    //枪旋转角度
    public angle: number = 0;
    //新增警戒状态属性
    public isAlert: boolean = false;

    start() {
        this.hurt_num.active = false;
    }

    /**
     * 初始化数据
     */
    public async init(data: any){
        this.data = data;
        this.player = Game.I.player.getComponent(Player);
        const isTank:boolean = this.isTank();
        this.enemyNode = this.node.getChildByName(data.prb_name);
        if(isTank){
            this.tankCollider["args"] = [EPartType.tank,this];
        }else{
            this.headCollider["args"] = [EPartType.head,this];
            this.bodyCollider["args"] = [EPartType.body,this];
            this.skeletalAnim = this.enemyNode.getComponent(SkeletalAnimation);
            if(this.skeletalAnim){
               this.skeletalAnim?.play(EAnimType.idle);
            }
        }
        if(!this.enemyNode){
            MsgHints.show(`不存在:${JSON.stringify(data)}`)
            return;
        }
        this.isAlert = false;
        this.data = this.enemyData(data);
        this.isDead = false;
        this.escape = false;
        //设置血量
        this.totalHP = data.hp;
        //敌人速度
        const s: number = data.speed * 3;
        this.speed = s;
        this.defaultSpeed = s;
        //设置枪的数据
        await this.createGun();
        //恢复初始雪条
        this.hpBar.progress = 1;
        this.hpBar.node.active = false;
        this.endFire();   
    }

    /**
     * 把武器的参数带到敌人身上
     */
    public enemyData(data:any){
        if(!data)return;
        //主武器id
        const mainWeaponID:number = data.weapon_id_1;
        let hp: number = Utils.clone(data).hp;
        let gData:any = userIns.enemyWeaponTable.find(e=>e.gun_id == mainWeaponID);
        //副武器 盾上的血量
        const secondWeaponID:number = data.weapon_id_2;
        if(secondWeaponID != 0){
            let sData:any = userIns.enemyWeaponTable.find(e=>e.gun_id == secondWeaponID);
            if(sData && sData.hp > 0){
               data.hp += hp + sData.shield_hp;
            }
        }
        return Object.assign(data,gData);
    }
    
    /**
     * 创建英雄所拥有的枪
     */
    public async createGun(){
        this.removeGun();
        //敌人主武器
        let gunPos:Node = this.enemyNode.getChildByName("gun_pos");
        const mainWeaponID:number = this.data.weapon_id_1;
        let mData:any = userIns.enemyWeaponTable.find(e=>e.gun_id == mainWeaponID);
        let gunNode:Node = await ResUtil.loadRes(`enemy/gun/${mData.gun_prb_name}`,this.enemyNode) as Node;
        this.gun = gunNode.getComponent(GunBase);
        gunNode.active = true;
        gunNode.parent = gunPos.parent;
        gunNode.worldPosition = gunPos.worldPosition.clone();
        gunNode.eulerAngles = gunPos.eulerAngles.clone();
        this.gun.init(this.data,this);
        //敌人附武器
        const secondWeaponID:number = this.data.weapon_id_2;
        if(secondWeaponID != 0){
            let sData:any = userIns.enemyWeaponTable.find(e=>e.gun_id == secondWeaponID);
            let shieldNode:Node = await ResUtil.loadRes(`enemy/gun/${sData.gun_prb_name}`,this.enemyNode) as Node;
            let shieldPos:Node = this.enemyNode.getChildByName("shield_pos");
            shieldNode.active = true;
            shieldNode.parent = shieldPos.parent;
            shieldNode.worldPosition = shieldPos.worldPosition.clone();
            shieldNode.eulerAngles = shieldPos.eulerAngles.clone();
            shieldNode.children[0].getComponent(Collider)["args"] = [EPartType.shield,this];
            this.shieldNode = shieldNode;
            this.shieldHp = sData.shield_hp;
        }
    }

    /**
     * 移除枪回收武器的时候调用
     */
    public removeGun(){
        if(this.gun){
           this.gun.endFire();
           PoolManager.putNode(this.gun.node);
           this.gun = null;
        }
        this.isFire = false;
        this.removeShield();
    }

    /**
     * 移除盾
     */
    public removeShield(){
        if(this.shieldNode){
           PoolManager.putNode(this.shieldNode);
           this.shieldNode = null;
        }
        this._shieldHp = 0;
    }

    /**
     * 扣掉血
     * @param hp 血
     * @param pData 英雄数据
     * @param isHeadShot 是否是爆头
     */
    public subHP(hp: number, pData:any,isHeadShot: boolean = false){
        if(Game.I.isPause
            ||this.isDead
            ||hp == null
            ||this.totalHP <= 0){
            return;
        }
        this.hpBar.node.active = true;
        this.scheduleOnce(() => {
            if(this.hpBar){this.hpBar.node.active = false;}
        }, 0.8);
        this.totalHP -= hp;
        //这种是伤害超级高直接死亡了
        if(hp > this.totalHP){
           this.escape = false;
           this.showHurt(Utils.numberToString(hp));
           this.recycle()
           return;
        }
        //敌人死亡
        if(this.totalHP <= 0 && !this.isDead){
            //爆头击杀播放音效
            if(isHeadShot){
               audioMgr.playOneShot(Constants.audios.head_shot);
            }
            this.escape = false;
            this.recycle();
        }else{//进度条和单独扣血
            this.hpBar.progress = this.totalHP / this.data.hp; 
            this.showHurt(Utils.numberToString(hp));
        }
    }

    /**
     * 开始敌人移动，面向玩家行走
     */
    public walk(points:Vec3[]) {
        if(points.length <= 0)return;
        this.curMoveIndex = 0;
        this.pathList = points;
        const time: number = 1 / this.data.speed;
        if(this.isTank()){
           this.tank_walk.active = true;
           this.tank_shoot.active = false;
        }else{
            ResUtil.playSkeletalAnim(this.skeletalAnim,EAnimType.walk,time);
        }
        this.updateDir(points[0].clone());
    }

    /**
     * 开始攻击
     */
    public beginFire(){
        if(this.player
            && !this.player.isDead 
            && this.gun){
            this.isFire = true;
            this.gun.fire();
        }
    }

    /**
     * 结束攻击
     */
    public endFire(){
        this.gun.endFire();
        this.isFire = false;
    }

    /**
     * 回收敌人节点
     * @param f 是否是游戏进行中的正常回收 程序主动回收不参数个数统计和加分这些 
     * @returns 
     */
    public recycle(f: boolean = true){
        if(!this.node 
            ||this.isDead){
            return;
        };
        this.removeGun();
        this.totalHP = 0;
        if(!this.isTank()){
           this.skeletalAnim.play(EAnimType.die);
        }
        this.isDead = true;
        this.hpBar.node.active = false;
        let death: Function = function(inite: boolean){
            this.node.getComponent(UIOpacity).opacity = 255;
            PoolManager.putNode(this.node);
            if(inite){
               Game.I.buildEnemys.subtractEnemy(this);
            }
        }.bind(this,f);
        if(this.oTween){this.oTween?.stop()};
        if(f){//修改透明度
            let op: UIOpacity = this.node.getComponent(UIOpacity);
            this.oTween = tween(op)
                .delay(0.4)
                .to(0.15,{ opacity: 0})
                .call(()=>{death();})
                .start();
        }else{
            death();
        }
    }



    /**
     * 展示敌人受到的伤害
     * @param hpStr 
     */
    public showHurt(hpStr: string) {
        if(Game.I.isGameOver || this.isDead) return;
        //创建3D伤害数字
        const n = PoolManager.getNode(this.hurt_num, this.hurt_num.parent);
        n.getComponent(Label).string = hpStr;
        const oPos: Vec3 = this.hpBar.node.position.clone();
        n.position = oPos;
        const oScale: Vec3 = this.hurt_num.scale.clone();
        n.scale = oScale;
        n.getComponent(UIOpacity).opacity = 255;
        let bezier: Vec3[] = [];
        let num: number = 100;
        let forward =  Utils.getRandomFloat(0, 1) > 0.5 ;
        if (forward) {
            bezier = [new Vec3(-(10/num)+oPos.x, (30/num)+oPos.y), new Vec3((-40/num)+oPos.x, (40/num)+oPos.y), new Vec3((-60/num)+oPos.x, oPos.y)];
        } else {
            bezier = [new Vec3((10/num)+oPos.x, (30/num)+oPos.y), new Vec3((40/num)+oPos.x, (40/num)+oPos.y), new Vec3((60/num)+oPos.x, oPos.y)];
        }
        n.position = new Vec3(bezier[2].x,bezier[2].y - (80/num),oPos.z);
        //贝塞尔曲线坐标函数
        let twoBezier = (t: number, p1: Vec3, cp: Vec3, p2: Vec3) => {
            let x = (1 - t) * (1 - t) * p1.x + 2 * t * (1 - t) * cp.x + t * t * p2.x;
            let y = (1 - t) * (1 - t) * p1.y + 2 * t * (1 - t) * cp.y + t * t * p2.y;
            return new Vec3(x, y, oPos.z);
        };
        let time: number = 0.65;
        tween(n)
        .parallel(
            tween()
            .to(time,{ scale: new Vec3(oScale.x * 0.4,oScale.y * 0.4,oScale.z * 0.4)}),
            tween()
            .to(time, bezier[2], { 
                onUpdate: (target: Vec3, ratio: number) => {
                    if(n.parent){
                       const pos: Vec3 = twoBezier(ratio, bezier[0], bezier[1], bezier[2]);
                       n.position = new Vec3(pos.x,pos.y - (80/num),oPos.z)
                    }
                }
            })
        ).call(function(){
            tween(this.getComponent(UIOpacity))
            .to(0.15,{opacity: 0})
            .call(()=>{
                PoolManager.putNode(this);
            })
            .start();
        }.bind(n)).start();
    }
    
    /**
     * 计算是否命中玩家
     * @returns 返回命中状态
     */
    public calculateIsHit():boolean{
        let isGuaranteedHit: boolean = false;
        //获取射击的精准度
        const data:any = this.getDifficultyData();
        //生成0-1随机数用于命中判定 根据precision范围确定命中逻辑
        const random = Math.random();
        if(data.precision < 0){//负值100%不命中
            isGuaranteedHit = false;
        }else if(data.precision > 1) {//超过1 100%命中
            isGuaranteedHit = true;
        }else {//正常范围：随机判定
            isGuaranteedHit = random <= data.precision;
        }
        return isGuaranteedHit;
    }
    
    /**
     * 轻松杀敌增加游戏难度 只有单其他附加因素 例如:连杀等叠加状态 给敌人增加血
     */
    public addDiffHP(){
        if(!this.node 
            ||this.isDead
            ||Game.I.isGameOver 
            ||this.isDead){
            return;
        };
        const data:any = this.getDifficultyData();
        if(data.hp_ratio > 0){
           this.totalHP = this.data.hp * (1 + data.hp_ratio);
        }
    }
   
    /**
    * 敌人的射击的精准度 获得难度数据
    */
    public getDifficultyData(): any{
        //获取基础精准度（玩家预设值）
        const precision: number = userIns.getCurLevelData().precision;
        let basePrecision: number = precision;
        let diff:any = {
            precision: precision,//增加或减少的精准度 0-100%
            hp_ratio: 0,//增加或减少的血量 0-100%
            reaction_time: 0,//增加或减少的反应时间 0-100%
        }
        const each: number = Math.floor(Game.I.buildEnemys.getCurKillNum() / 3);
        //连杀3个敌人的次数 AI精准度增加1%
        diff.precision += each * 0.01;
        //连续通关3次以上才有的难度
        const lx_num: number = 3;
        if(userIns.passNum > lx_num){//1、连续通关 AI生命值增加15% 精准度增加5%  
           diff.precision += userIns.passNum * 0.05;
           diff.precision = Math.min(basePrecision, 0.9);
           diff.hp_ratio += userIns.passNum * 0.15;
           diff.hp_ratio = Math.min(diff.hp_ratio, 1);
        }else{//2、通关失败 下一局 AI精准度下降5% AI反应时间增加0.5s
           diff.precision -= userIns.passNum * 0.05;
           diff.precision = Math.max(diff.precision, 0.1);
           diff.reaction_time += 0.5;
        }
        return diff;
    }


    /**
     * 更新敌人行走和变化方向
     */
    protected update(dt: number): void {
        if(Game.I.isGameOver 
            || Game.I.isPause 
            || !this.data 
            || this.isDead) return;
        if(this.curMoveIndex >= this.pathList.length) {
           return;
        }
        dt = dt / Game.I.map.multiplySpeed();
        const targetPos = this.pathList[this.curMoveIndex];
        const currentPos = this.node.worldPosition.clone();
        const moveDirection = new Vec3();
        Vec3.subtract(moveDirection, targetPos, currentPos);
        const distanceToTarget = moveDirection.length();
        const moveDistance = this.speed * dt;
        const normalizedDir = moveDirection.normalize();
        if(distanceToTarget > 0.1) { 
            const newPos = currentPos.add(normalizedDir.multiplyScalar(moveDistance));
            this.node.worldPosition = newPos;
            //根据是否是最后一个路径点选择目标坐标
            const isLastPathPoint = this.curMoveIndex == this.pathList.length - 1;
            const dirTarget = isLastPathPoint 
                ? Game.I.player.node.worldPosition
                : this.pathList[this.curMoveIndex + 1]; 
            this.updateDir(dirTarget); // 仅传递目标坐标
        }else{//到达当前路径点后切换目标
            this.curMoveIndex++;
            if(this.curMoveIndex < this.pathList.length) {
                //切换路径点时修正方向（指向新的目标点）
                const nextTarget = this.pathList[this.curMoveIndex];
                this.updateDir(nextTarget); // 传递下一个路径点
            }
        }
        //到达所有路径终点处理
        if(this.curMoveIndex >= this.pathList.length) {
            this.beginFire();
            if(this.isTank()){
                this.tank_walk.active = false;
                this.tank_shoot.active = true;
            }else{
                const time: number = 1 / this.data.atk_speed;
                ResUtil.playSkeletalAnim(this.skeletalAnim,EAnimType.walk,time);
            }
            this.updateDir(Game.I.player.node.worldPosition); // 终点指向玩家
        }
    }

    /**
     * 更新敌人方向（根据目标坐标转向）
     * @param targetPos 目标坐标（路径点或玩家坐标）
     */
    public updateDir(targetPos: Vec3){
        const curPos = this.node.worldPosition.clone();
        //从目标位置指向当前位置
        const targetDir = Vec3.subtract(new Vec3(), curPos, targetPos); 
        targetDir.normalize();
        //平滑插值转向 避免瞬间转向
        const currentDir = this.node.forward.clone();
        Vec3.slerp(currentDir, currentDir, targetDir, 0.15);
        this.node.forward = currentDir;
    }
    
    /**
     * 是否是坦克
     */
    public isTank():boolean{
        return this.data.id == EnemyType.Tank;
    }
}


/**
 * 
    if (this.isDead 
        || !this.player) return;
    if (!this.isAlert) {
        this.skeletalAnim.play(EAnimType.walk);
        const playerPos = this.player.node.getWorldPosition();
        const enemyPos = this.node.getWorldPosition();
        //创建射线对象修复类型错误
        const ray = new geometry.Ray();
        ray.o = enemyPos;
        ray.d = playerPos.subtract(enemyPos).normalize();
        //修正物理检测参数
        if (PhysicsSystem.instance.raycast(ray, 1 << 0, 2)) {
            const randomDir = Math.random() > 0.5 ? 1 : -1;
            //修改为正确的参数格式
            const quat = new Quat();
            Quat.fromAxisAngle(quat, Vec3.UP, 45 * randomDir * Math.PI / 180);
            this.node.rotate(quat, NodeSpace.WORLD);
        }
        //this.skeletalAnim.play("walk");
        //使用定时器持续移动
        this.schedule(() => {
            const distance: number = Vec3.distance(this.node.worldPosition,Game.I.buildEnemys.ambush.worldPosition);
            if(distance < 10) {
                this.isAlert = true;
                this.walk();
                return;
            }
            const moveVec = this.node.forward.negative().multiplyScalar(this.speed * 0.016);
            this.node.position = this.node.position.add(moveVec);
        }, 0.1);
    } else if (!this.currentCover) {
        const nearestCover = this.findNearestCover();
        if (nearestCover) {
            this.currentCover = nearestCover;
            //生成Z轴随机偏移（-18到+18）
            const targetPos = nearestCover.worldPosition.clone();
            targetPos.z += Math.random() * 36 - 18;
            //移动到掩体位置 直接使用缓动动画移动到掩体
            tween(this.node)
            .to(2, { worldPosition: targetPos }, {
                easing: easing.quadOut,
                onStart: () => {
                    this.speed = this.defaultSpeed * 1.5; //加速移动
                },
                onComplete: () => {
                    this.skeletalAnim.play(EAnimType.shoot);
                    this.beginFire(); //到达后开始攻击
                    this.currentCover = nearestCover;
                }
            })
            .start();
        }
    }
 */