"""
粒子管理器
负责粒子系统的整体管理和协调
"""

import time
import random
from typing import List, Dict, Optional
from panda3d.core import Vec3, Point3, NodePath
from direct.task import Task

from .particle_emitter import ParticleEmitter
from .particle_renderer import ParticleRenderer
from .particle_physics import ParticlePhysics

class ParticleManager:
    """
    粒子管理器
    统一管理所有粒子发射器、渲染器和物理系统
    """
    
    def __init__(self, world):
        """
        初始化粒子管理器
        
        Args:
            world: 3D世界对象
        """
        self.world = world
        self.enabled = False
        
        # 核心组件
        self.renderer = ParticleRenderer(world)
        self.physics = ParticlePhysics(world)
        
        # 粒子发射器管理
        self.emitters: Dict[str, ParticleEmitter] = {}
        self.emitter_counter = 0
        
        # 全局粒子设置
        self.global_time_scale = 1.0
        self.max_particles = 10000
        self.current_particle_count = 0
        
        # 性能统计
        self.stats = {
            'total_particles': 0,
            'active_emitters': 0,
            'render_time': 0.0,
            'physics_time': 0.0,
            'update_time': 0.0
        }
        
        # 粒子系统设置
        self.auto_cleanup = True  # 自动清理已完成的发射器
        self.emit_rate_multiplier = 1.0  # 发射速率倍增器
        self.particle_size_multiplier = 1.0  # 粒子尺寸倍增器
        
        # 任务管理
        self.update_task = None
        
        print("✓ 粒子管理器初始化完成")
        
    def enable(self):
        """启用粒子管理器"""
        if self.enabled:
            return
            
        self.enabled = True
        
        # 启动更新任务
        self.update_task = self.world.taskMgr.add(
            self._update_task, 
            "particle_manager_update"
        )
        
        # 启用渲染器和物理系统
        self.renderer.enable()
        self.physics.enable()
        
        print("✓ 粒子管理器已启用")
        
    def disable(self):
        """禁用粒子管理器"""
        if not self.enabled:
            return
            
        self.enabled = False
        
        # 停止更新任务
        if self.update_task:
            self.world.taskMgr.remove(self.update_task)
            self.update_task = None
            
        # 禁用渲染器和物理系统
        self.renderer.disable()
        self.physics.disable()
        
        # 清除所有粒子
        self.clear_all_particles()
        
        print("✓ 粒子管理器已禁用")
        
    def cleanup(self):
        """清理资源"""
        self.disable()
        
        # 清理组件
        if self.renderer:
            self.renderer.cleanup()
            self.renderer = None
            
        if self.physics:
            self.physics.cleanup()
            self.physics = None
            
        self.emitters.clear()
        
    def _update_task(self, task):
        """粒子系统更新任务"""
        if not self.enabled:
            return task.done
            
        dt = globalClock.getDt() * self.global_time_scale
        start_time = time.time()
        
        try:
            # 更新所有发射器
            active_emitters = 0
            total_particles = 0
            
            # 创建一个发射器列表的副本，以防在迭代过程中有发射器被删除
            emitters_copy = list(self.emitters.items())
            
            for emitter_id, emitter in emitters_copy:
                if emitter.is_active():
                    emitter.update(dt)
                    active_emitters += 1
                    total_particles += emitter.get_particle_count()
                elif emitter.should_remove() and self.auto_cleanup:
                    # 移除已完成的发射器
                    self.remove_emitter(emitter_id)
                    
            # 更新物理系统
            physics_start = time.time()
            self.physics.update(dt)
            self.stats['physics_time'] = time.time() - physics_start
            
            # 更新渲染系统
            render_start = time.time()
            self.renderer.update(dt)
            self.stats['render_time'] = time.time() - render_start
            
            # 更新统计信息
            self.stats['active_emitters'] = active_emitters
            self.stats['total_particles'] = total_particles
            self.current_particle_count = total_particles
            
        except Exception as e:
            print(f"⚠ 粒子系统更新错误: {e}")
            
        self.stats['update_time'] = time.time() - start_time
        return task.cont
        
    def create_emitter(self, emitter_type: str = "default", 
                      position: Point3 = None, 
                      config: Dict = None) -> str:
        """
        创建粒子发射器
        
        Args:
            emitter_type: 发射器类型
            position: 发射器位置
            config: 发射器配置
            
        Returns:
            发射器ID
        """
        if position is None:
            position = Point3(0, 0, 0)
            
        if config is None:
            config = {}
            
        # 应用全局设置
        if 'emission_rate' in config:
            config['emission_rate'] *= self.emit_rate_multiplier
            
        if 'start_size' in config:
            config['start_size'] *= self.particle_size_multiplier
            
        if 'end_size' in config:
            config['end_size'] *= self.particle_size_multiplier
            
        # 生成唯一ID
        emitter_id = f"emitter_{self.emitter_counter}"
        self.emitter_counter += 1
        
        # 创建发射器
        emitter = ParticleEmitter(
            emitter_id, 
            emitter_type, 
            position, 
            self.world,
            config
        )
        
        # 注册到渲染器和物理系统
        self.renderer.register_emitter(emitter)
        self.physics.register_emitter(emitter)
        
        # 添加到管理器
        self.emitters[emitter_id] = emitter
        
        print(f"✓ 创建粒子发射器: {emitter_id} ({emitter_type})")
        return emitter_id
        
    def remove_emitter(self, emitter_id: str):
        """
        移除粒子发射器
        
        Args:
            emitter_id: 发射器ID
        """
        if emitter_id not in self.emitters:
            return
            
        emitter = self.emitters[emitter_id]
        
        # 从渲染器和物理系统注销
        self.renderer.unregister_emitter(emitter)
        self.physics.unregister_emitter(emitter)
        
        # 清理发射器
        emitter.cleanup()
        
        # 从管理器移除
        del self.emitters[emitter_id]
        
        print(f"✓ 移除粒子发射器: {emitter_id}")
        
    def get_emitter(self, emitter_id: str) -> Optional[ParticleEmitter]:
        """获取粒子发射器"""
        return self.emitters.get(emitter_id)
        
    def clear_all_particles(self):
        """清除所有粒子"""
        # 创建一个发射器ID列表的副本，以防在迭代过程中字典被修改
        emitter_ids = list(self.emitters.keys())
        
        for emitter_id in emitter_ids:
            self.remove_emitter(emitter_id)
            
        if self.renderer:
            self.renderer.clear_all()
            
        if self.physics:
            self.physics.clear_all()
        
        print("✓ 已清除所有粒子")
        
    def set_global_time_scale(self, scale: float):
        """设置全局时间缩放"""
        self.global_time_scale = max(0.0, scale)
        
    def get_particle_count(self) -> int:
        """获取当前粒子总数"""
        return self.current_particle_count
        
    def get_emitter_count(self) -> int:
        """获取活跃发射器数量"""
        return len([e for e in self.emitters.values() if e.is_active()])
        
    def get_stats(self) -> Dict:
        """获取性能统计信息"""
        return self.stats.copy()
        
    def set_max_particles(self, max_count: int):
        """设置最大粒子数"""
        self.max_particles = max(1, max_count)
        
    def set_auto_cleanup(self, enabled: bool):
        """设置自动清理"""
        self.auto_cleanup = enabled
        
    def set_emit_rate_multiplier(self, multiplier: float):
        """设置发射速率倍增器"""
        self.emit_rate_multiplier = max(0.0, multiplier)
        
    def set_particle_size_multiplier(self, multiplier: float):
        """设置粒子尺寸倍增器"""
        self.particle_size_multiplier = max(0.0, multiplier)
        
    # 预设效果创建方法
    def create_fire_effect(self, position: Point3 = None) -> str:
        """创建火焰效果"""
        if position is None:
            position = Point3(0, 0, 0)
            
        config = {
            'particle_type': 'fire',
            'emission_rate': 50,
            'particle_lifetime': 2.0,
            'start_color': Vec3(1.0, 0.3, 0.0),
            'end_color': Vec3(1.0, 0.0, 0.0),
            'start_size': 0.2,
            'end_size': 0.8,
            'velocity': Vec3(0, 0, 2),
            'velocity_variation': 0.5,
            'gravity_scale': -0.2,
            'air_resistance': 0.02,
            'emitter_shape': 'circle',
            'emitter_radius': 0.3
        }
        
        return self.create_emitter("fire", position, config)
        
    def create_smoke_effect(self, position: Point3 = None) -> str:
        """创建烟雾效果"""
        if position is None:
            position = Point3(0, 0, 0)
            
        config = {
            'particle_type': 'smoke',
            'emission_rate': 30,
            'particle_lifetime': 4.0,
            'start_color': Vec3(0.8, 0.8, 0.8),
            'end_color': Vec3(0.3, 0.3, 0.3),
            'start_size': 0.3,
            'end_size': 1.5,
            'velocity': Vec3(0, 0, 1),
            'velocity_variation': 0.3,
            'gravity_scale': -0.1,
            'air_resistance': 0.05,
            'emitter_shape': 'circle',
            'emitter_radius': 0.5
        }
        
        return self.create_emitter("smoke", position, config)
        
    def create_explosion_effect(self, position: Point3 = None) -> str:
        """创建爆炸效果"""
        if position is None:
            position = Point3(0, 0, 0)
            
        config = {
            'particle_type': 'explosion',
            'emission_rate': 200,
            'burst_count': 100,
            'particle_lifetime': 1.5,
            'start_color': Vec3(1.0, 0.8, 0.0),
            'end_color': Vec3(1.0, 0.2, 0.0),
            'start_size': 0.1,
            'end_size': 0.5,
            'velocity': Vec3(0, 0, 0),
            'velocity_variation': 2.0,
            'gravity_scale': 0.5,
            'duration': 0.2,
            'emitter_shape': 'sphere',
            'emitter_radius': 0.1
        }
        
        return self.create_emitter("explosion", position, config)
        
    def create_water_effect(self, position: Point3 = None) -> str:
        """创建水花效果"""
        if position is None:
            position = Point3(0, 0, 0)
            
        config = {
            'particle_type': 'water',
            'emission_rate': 80,
            'particle_lifetime': 3.0,
            'start_color': Vec3(0.2, 0.6, 1.0),
            'end_color': Vec3(0.1, 0.3, 0.8),
            'start_size': 0.1,
            'end_size': 0.05,
            'velocity': Vec3(0, 0, 3),
            'velocity_variation': 1.0,
            'gravity_scale': 2.0,
            'bounce_factor': 0.3,
            'air_resistance': 0.01,
            'emitter_shape': 'circle',
            'emitter_radius': 0.2
        }
        
        return self.create_emitter("water", position, config)
        
    def create_magic_effect(self, position: Point3 = None) -> str:
        """创建魔法效果"""
        if position is None:
            position = Point3(0, 0, 0)
            
        config = {
            'particle_type': 'magic',
            'emission_rate': 40,
            'particle_lifetime': 3.0,
            'start_color': Vec3(0.5, 0.2, 1.0),
            'end_color': Vec3(0.8, 0.6, 1.0),
            'start_size': 0.15,
            'end_size': 0.05,
            'velocity': Vec3(0, 0, 0.5),
            'velocity_variation': 0.8,
            'gravity_scale': -0.5,
            'rotation_enabled': True,
            'rotation_speed': 2.0,
            'emitter_shape': 'sphere',
            'emitter_radius': 0.8
        }
        
        return self.create_emitter("magic", position, config)
        
    def create_snow_effect(self, position: Point3 = None) -> str:
        """创建雪花效果"""
        if position is None:
            position = Point3(0, 0, 10)  # 从高处开始
            
        config = {
            'particle_type': 'snow',
            'emission_rate': 60,
            'particle_lifetime': 8.0,
            'start_color': Vec3(0.9, 0.9, 1.0),
            'end_color': Vec3(0.9, 0.9, 1.0),
            'start_size': 0.05,
            'end_size': 0.05,
            'velocity': Vec3(0, 0, -1),
            'velocity_variation': 0.5,
            'gravity_scale': 0.8,
            'air_resistance': 0.1,
            'bounce_factor': 0.2,
            'emitter_shape': 'box',
            'emitter_dimensions': Vec3(20, 20, 1)
        }
        
        return self.create_emitter("snow", position, config)
        
    def create_test_effect(self, position: Point3 = None) -> str:
        """创建测试效果"""
        if position is None:
            # 在摄像机前方创建
            camera_pos = self.world.camera.getPos()
            camera_forward = self.world.camera.getNetTransform().getMat().getRow3(1)
            position = camera_pos + camera_forward * 5
            
        # 随机选择一种效果
        effects = [
            self.create_fire_effect,
            self.create_smoke_effect,
            self.create_explosion_effect,
            self.create_water_effect,
            self.create_magic_effect
        ]
        
        effect_func = random.choice(effects)
        return effect_func(position)