import { _decorator, Collider, Enum, Node, RigidBody, Animation, Vec3 } from 'cc';
import { BaseExp } from '../core/base/BaseExp';
import { PoolManager } from '../core/manager/PoolManager';
import { userIns } from '../data/UserData';
import { autoBind } from '../extend/AutoBind';
import { Logger } from '../extend/Logger';
import { ResUtil } from '../utils/ResUtil';
import { Game } from './Game';
import { Enemy, EPartType } from './Enemy';
import { audioMgr } from '../core/manager/AudioManager';
import { Constants } from '../data/Constants';
import MsgHints from '../utils/MsgHints';
const { ccclass, property } = _decorator;

//沙袋堆动画
const sandbge_take = "take"

/**
 * 战场障碍物类型
 */
export enum ObstacleType {
    /** 沙袋堆 */
    SANDBAG_PILE = "沙袋堆",
    /** 油桶 */
    OIL_BARREL = "油桶",
    /** 军车 */
    MILITARY_TRUCK = "军车",
    /** 小沙袋 */
    SMALL_SANDBAG = "小沙袋"
}

/**
 * 杂物建筑物类
 */
@ccclass('Sundries')
export class Sundries extends BaseExp {
    @property({ type: Enum(ObstacleType), tooltip: "沙袋堆:SANDBAG_PILE 油桶:OIL_BARREL 军车: MILITARY_TRUCK  小沙袋:SMALL_SANDBAG", displayName: "障碍物类型"})
    public obstacleType: ObstacleType = ObstacleType.SANDBAG_PILE;
    
    //添加爆炸队列和标记
    private static explosionQueue: { 
        target: Enemy | Sundries, 
        damage: number, 
        source: any }[] = [];
    //标记是否正在处理爆炸队列
    private static isProcessingQueue = false;

    //杂物信息数据
    public data: any = null;
    //杂物是否被打报废
    private isDead: boolean = false;
    //杂物当前的总血量
    private totalHp: number = 0;
    
    start() {
        //给碰撞体绑定数据
        this.setupColliders(this.node);
        //根据障碍物类型设置总血量
        let sundrie_id: number = -1;
        switch (this.obstacleType) {
            case ObstacleType.SANDBAG_PILE:
                sundrie_id = 11001;
                break;
            case ObstacleType.OIL_BARREL:
                sundrie_id = 11002;
                break;
            case ObstacleType.MILITARY_TRUCK:
                sundrie_id = 11003;
                break;
            case ObstacleType.SMALL_SANDBAG:
                sundrie_id = 11004;
                break;
        }
        if(sundrie_id !== -1){
            const data: any = userIns.sundriesTable.find(e=>e.id == sundrie_id);
            this.data = data;
            this.totalHp = data.hp;
        }else{
            Logger.log('未找到对应的杂物信息');
        }
    }

    /**
     * 杂物被打掉血
     * @param hp 血
     * @param pData 玩家数据
     */
    public subHP(hp: number, pData:any){
        if(!this.node
            ||Game.I.isPause
            ||this.isDead
            ||hp == null
            ||this.totalHp <= 0){
            return;
        }
        this.totalHp -= hp;
        //杂物打打死报废
        if(this.totalHp <= 0 
            && !this.isDead){
            this.isDead = true;
            this.scrap();
        }
    }
    
    /**
     * 杂物被打报废
     */
    public scrap(){
        switch (this.obstacleType) {
            case ObstacleType.SANDBAG_PILE:{//沙袋堆
                    let skeletal:Animation = this.node.getComponent(Animation);
                    if(!skeletal)return;
                    //沙袋掀开的动画
                    skeletal.play(sandbge_take);
                    skeletal.scheduleOnce(()=>{
                        skeletal.pause();
                    },0.9);
                }
                break;
            case ObstacleType.OIL_BARREL:{//油桶
                    //油漆桶音效
                    audioMgr.playOneShot(Constants.audios.Oildrum_explosion);
                    //爆炸后生成爆炸特效 粒子路径、自动回收时间、外部设置回调
                    ResUtil.playParticle(
                        `effects/Prefabs/OilBoom`, 
                        4, 
                        (particle) => { 
                            particle.parent = this.node.parent; 
                            const targetPos: Vec3 = this.node.worldPosition.clone();
                            particle.worldPosition = targetPos;
                            particle.active = true;
                            this.recycle();
                            //爆炸后生成爆炸伤害
                            this.explosionDamage(targetPos);
                        }
                    );
                }
                break;
            case ObstacleType.MILITARY_TRUCK:{//军车
                    //加载报废的军车
                    ResUtil.loadRes(`enemy/sundries/scrap_car`, this.node)
                        .then((military: Node | null) => {
                            if(!military)return;
                            military.active = true;
                            military.parent = this.node.parent;
                            const targetPos: Vec3 = this.node.worldPosition.clone();
                            military.worldPosition = targetPos;
                            military.eulerAngles = this.node.eulerAngles.clone();
                            military.scale = this.node.scale.clone();
                            //回收原有的军车
                            this.recycle();
                            //播放爆炸过后的浓烟
                            ResUtil.playParticle(
                                `effects/Prefabs/HeavySmoke`, 
                                3, 
                                (particle) => { 
                                    particle.parent = Game.I.map.node; 
                                    particle.worldPosition = targetPos;
                                    particle.active = true;
                                    //爆炸后生成爆炸伤害
                                    this.explosionDamage(targetPos);
                                }
                            );
                        });
                }
                break;
            case ObstacleType.SMALL_SANDBAG:{//小沙袋
                    //获取刚体组件
                    const rigidBody = this.node.getComponent(RigidBody);
                    if (!rigidBody) return;
                    //计算抛射方向
                    const startPos = this.node.worldPosition.clone();
                    const playerPos = Game.I.player.node.worldPosition.clone();
                    const direction = startPos.subtract(playerPos).normalize();
                    //随机抛射参数 水平力1500-2500N
                    const horizontalForce = 1500 + Math.random() * 1000;
                    //垂直力800-1500N
                    const verticalForce = 800 + Math.random() * 700;
                    //旋转扭矩50-150
                    const torqueForce = 50 + Math.random() * 100;
                    //施加作用力
                    rigidBody.applyForce(new Vec3(
                        direction.x * horizontalForce,
                        verticalForce,
                        direction.z * horizontalForce
                    ));
                    //施加旋转扭矩
                    rigidBody.applyTorque(new Vec3(0, torqueForce, 0));
                }
                break;
        }
    }

    /**
     * 爆炸物产生爆炸伤害
     * @param targetPos 爆炸物的位置
     */
    public explosionDamage(targetPos: Vec3){
        //爆炸半径
        const eRadius: number = this.data.explosion_radius / 10;
        //查找不是自身的所有杂物 然后去看看是否有连续爆炸
        const allSundries: Sundries[] = Game.I.map.sundries.children
            .filter(node => node.active && node.parent && node != this.node)
            .map(node => node.getComponent(Sundries))
            .filter(comp => 
                comp && !comp.isDead
            ) as Sundries[];  
        const allEnemys = [...Game.I.buildEnemys.allEnemys.filter(e=>!e.isDead),...allSundries];
        if(allEnemys.length <= 0)return;
        //爆炸伤害
        const damage: number = this.data.explosion_injury;
        allEnemys.forEach((e: any) => {
            if(e.node){
                const ePos: Vec3 = e.node.worldPosition;
                const distance = ePos.clone().subtract(targetPos).length();
                if(distance <= eRadius) {
                    if(e instanceof Enemy){//敌人直接扣血
                        e.subHP(damage, this.data);
                    }else{//爆炸物 如果队列未在处理则开始处理 将爆炸目标加入队列而不是立即触发
                        Sundries.explosionQueue.push({
                            target: e,
                            damage: damage,
                            source: this.data
                        });
                        if(!Sundries.isProcessingQueue) {
                            this.processExplosionQueue();
                        }
                    }
                }
            }
        })
    }

     /**
     * 处理爆炸队列（新增方法）
     */
    private processExplosionQueue() {
        if (Sundries.explosionQueue.length == 0) {
            Sundries.isProcessingQueue = false;
            return;
        }
        Sundries.isProcessingQueue = true;
        const explosion = Sundries.explosionQueue.shift()!;
        //触发当前爆炸
        explosion.target.subHP(explosion.damage, explosion.source);
        //添加0.2秒延迟后处理下一个爆炸
        this.scheduleOnce(()=>{
            this.processExplosionQueue();
        },0.2)
    }

    /**
     * 递归设置所有子节点的Collider参数
     * @param node 起始节点
     */
    private setupColliders(node: Node) {
        const collider = node.getComponent(Collider);
        if(collider){
           collider["args"] = [EPartType.sundries, this];
        }
        //递归处理所有子节点
        node.children.forEach(child => {
            this.setupColliders(child);
        });
    }

    /**
     * 杂物回收
     */
    public recycle(){
        if(this.node.parent){
            this.isDead = true;
            PoolManager.putNode(this.node);
        }
    }
}

