"""
粒子发射器
负责粒子的生成和发射逻辑
"""

import time
import random
import math
from typing import List, Dict, Optional
from panda3d.core import Vec3, Point3, LVector3f
from collections import deque

class Particle:
    """单个粒子类"""
    
    def __init__(self):
        self.position = Point3(0, 0, 0)
        self.velocity = Vec3(0, 0, 0)
        self.acceleration = Vec3(0, 0, 0)
        self.color = Vec3(1, 1, 1)
        self.size = 1.0
        self.rotation = 0.0
        self.angular_velocity = 0.0
        self.lifetime = 1.0
        self.age = 0.0
        self.mass = 1.0
        self.active = True
        
        # 生命周期属性
        self.start_color = Vec3(1, 1, 1)
        self.end_color = Vec3(1, 1, 1)
        self.start_size = 1.0
        self.end_size = 1.0
        
        # 物理属性
        self.gravity_scale = 1.0
        self.air_resistance = 0.01
        self.bounce_factor = 0.5
        
    def update(self, dt: float):
        """更新粒子状态"""
        if not self.active:
            return
            
        # 更新年龄
        self.age += dt
        
        # 检查生命周期
        if self.age >= self.lifetime:
            self.active = False
            return
            
        # 计算生命周期进度
        life_progress = self.age / self.lifetime
        
        # 更新颜色（线性插值）
        self.color = self.start_color + (self.end_color - self.start_color) * life_progress
        
        # 更新尺寸（线性插值）
        self.size = self.start_size + (self.end_size - self.start_size) * life_progress
        
        # 更新旋转
        self.rotation += self.angular_velocity * dt
        
        # 应用空气阻力
        drag = self.velocity * self.air_resistance
        self.velocity -= drag * dt
        
    def is_alive(self) -> bool:
        """检查粒子是否存活"""
        return self.active and self.age < self.lifetime
        
    def reset(self):
        """重置粒子状态（用于对象池）"""
        self.position = Point3(0, 0, 0)
        self.velocity = Vec3(0, 0, 0)
        self.acceleration = Vec3(0, 0, 0)
        self.color = Vec3(1, 1, 1)
        self.size = 1.0
        self.rotation = 0.0
        self.angular_velocity = 0.0
        self.age = 0.0
        self.active = True

class ParticleEmitter:
    """
    粒子发射器
    负责粒子的生成、管理和更新
    """
    
    def __init__(self, emitter_id: str, emitter_type: str, position: Point3, world, config: Dict):
        """
        初始化粒子发射器
        
        Args:
            emitter_id: 发射器唯一ID
            emitter_type: 发射器类型
            position: 发射器位置
            world: 3D世界对象
            config: 发射器配置
        """
        self.emitter_id = emitter_id
        self.emitter_type = emitter_type
        self.world = world
        self.position = position
        
        # 粒子容器
        self.particles: List[Particle] = []
        self.particle_pool = deque()  # 对象池
        self.max_particles = config.get('max_particles', 1000)
        
        # 发射器状态
        self.active = True
        self.enabled = True
        self.age = 0.0
        self.duration = config.get('duration', -1)  # -1表示无限持续
        
        # 发射参数
        self.emission_rate = config.get('emission_rate', 10)  # 每秒发射粒子数
        self.emission_accumulator = 0.0
        self.burst_count = config.get('burst_count', 0)  # 爆发粒子数
        self.burst_emitted = False
        
        # 粒子属性
        self.particle_lifetime = config.get('particle_lifetime', 2.0)
        self.particle_lifetime_variation = config.get('particle_lifetime_variation', 0.2)
        
        # 颜色属性
        self.start_color = config.get('start_color', Vec3(1, 1, 1))
        self.end_color = config.get('end_color', Vec3(1, 1, 1))
        self.color_variation = config.get('color_variation', 0.1)
        
        # 尺寸属性
        self.start_size = config.get('start_size', 1.0)
        self.end_size = config.get('end_size', 1.0)
        self.size_variation = config.get('size_variation', 0.2)
        
        # 速度属性
        self.velocity = config.get('velocity', Vec3(0, 0, 1))
        self.velocity_variation = config.get('velocity_variation', 0.3)
        
        # 物理属性
        self.gravity_scale = config.get('gravity_scale', 1.0)
        self.air_resistance = config.get('air_resistance', 0.01)
        self.bounce_factor = config.get('bounce_factor', 0.5)
        self.mass = config.get('mass', 1.0)
        
        # 发射器形状
        self.emitter_shape = config.get('emitter_shape', 'point')  # point, circle, sphere, box
        self.emitter_radius = config.get('emitter_radius', 0.0)
        self.emitter_dimensions = config.get('emitter_dimensions', Vec3(1, 1, 1))
        
        # 角度和方向
        self.emission_angle = config.get('emission_angle', 0.0)  # 发射角度（弧度）
        self.emission_cone = config.get('emission_cone', math.pi / 6)  # 发射锥角
        self.emission_direction = config.get('emission_direction', Vec3(0, 0, 1))
        
        # 旋转属性
        self.rotation_enabled = config.get('rotation_enabled', False)
        self.rotation_speed = config.get('rotation_speed', 0.0)
        self.rotation_variation = config.get('rotation_variation', 0.5)
        
        # 随机种子支持
        self.random_seed = config.get('random_seed', None)
        if self.random_seed is not None:
            random.seed(self.random_seed)
        
        print(f"✓ 粒子发射器创建: {emitter_id} ({emitter_type})")
        
    def update(self, dt: float):
        """更新发射器"""
        if not self.enabled:
            return
            
        self.age += dt
        
        # 检查持续时间
        if self.duration > 0 and self.age >= self.duration:
            self.active = False
            
        # 发射新粒子
        if self.active:
            self._emit_particles(dt)
            
        # 更新现有粒子
        self._update_particles(dt)
        
        # 清理死亡粒子
        self._cleanup_dead_particles()
        
    def _emit_particles(self, dt: float):
        """发射新粒子"""
        # 爆发发射
        if self.burst_count > 0 and not self.burst_emitted:
            for _ in range(self.burst_count):
                if len(self.particles) < self.max_particles:
                    self._create_particle()
            self.burst_emitted = True
            
        # 持续发射
        if self.emission_rate > 0:
            self.emission_accumulator += self.emission_rate * dt
            
            while self.emission_accumulator >= 1.0 and len(self.particles) < self.max_particles:
                self._create_particle()
                self.emission_accumulator -= 1.0
                
    def _create_particle(self):
        """创建新粒子"""
        # 从对象池获取或创建新粒子
        if self.particle_pool:
            particle = self.particle_pool.popleft()
            particle.reset()
        else:
            particle = Particle()
            
        # 设置粒子基本属性
        particle.mass = self.mass
        
        # 设置粒子位置
        particle.position = self._get_emission_position()
        
        # 设置粒子速度
        particle.velocity = self._get_emission_velocity()
        
        # 设置粒子生命周期
        lifetime_var = random.uniform(-self.particle_lifetime_variation, self.particle_lifetime_variation)
        particle.lifetime = max(0.1, self.particle_lifetime + lifetime_var)
        
        # 设置颜色
        particle.start_color = self._vary_color(self.start_color)
        particle.end_color = self._vary_color(self.end_color)
        particle.color = particle.start_color
        
        # 设置尺寸
        size_var = random.uniform(-self.size_variation, self.size_variation)
        particle.start_size = max(0.01, self.start_size + size_var)
        particle.end_size = max(0.01, self.end_size + size_var)
        particle.size = particle.start_size
        
        # 设置物理属性
        particle.gravity_scale = self.gravity_scale
        particle.air_resistance = self.air_resistance
        particle.bounce_factor = self.bounce_factor
        
        # 设置旋转
        if self.rotation_enabled:
            particle.angular_velocity = self.rotation_speed + random.uniform(
                -self.rotation_variation, self.rotation_variation
            )
            
        # 添加到粒子列表
        self.particles.append(particle)
        
    def _get_emission_position(self) -> Point3:
        """获取发射位置"""
        if self.emitter_shape == 'point':
            return Point3(self.position)
            
        elif self.emitter_shape == 'circle':
            angle = random.uniform(0, 2 * math.pi)
            radius = random.uniform(0, self.emitter_radius)
            offset = Vec3(
                radius * math.cos(angle),
                radius * math.sin(angle),
                0
            )
            return self.position + offset
            
        elif self.emitter_shape == 'sphere':
            # 球形发射器
            phi = random.uniform(0, 2 * math.pi)
            costheta = random.uniform(-1, 1)
            theta = math.acos(costheta)
            radius = random.uniform(0, self.emitter_radius)
            
            offset = Vec3(
                radius * math.sin(theta) * math.cos(phi),
                radius * math.sin(theta) * math.sin(phi),
                radius * math.cos(theta)
            )
            return self.position + offset
            
        elif self.emitter_shape == 'box':
            # 盒形发射器
            offset = Vec3(
                random.uniform(-self.emitter_dimensions.x/2, self.emitter_dimensions.x/2),
                random.uniform(-self.emitter_dimensions.y/2, self.emitter_dimensions.y/2),
                random.uniform(-self.emitter_dimensions.z/2, self.emitter_dimensions.z/2)
            )
            return self.position + offset
            
        return Point3(self.position)
        
    def _get_emission_velocity(self) -> Vec3:
        """获取发射速度"""
        base_velocity = Vec3(self.velocity)
        
        # 添加随机变化
        if self.velocity_variation > 0:
            variation = Vec3(
                random.uniform(-self.velocity_variation, self.velocity_variation),
                random.uniform(-self.velocity_variation, self.velocity_variation),
                random.uniform(-self.velocity_variation, self.velocity_variation)
            )
            base_velocity += variation
            
        # 应用发射锥角
        if self.emission_cone > 0:
            # 在锥形范围内随机方向
            cone_angle = random.uniform(0, self.emission_cone)
            azimuth = random.uniform(0, 2 * math.pi)
            
            # 计算锥形方向
            cone_dir = Vec3(
                math.sin(cone_angle) * math.cos(azimuth),
                math.sin(cone_angle) * math.sin(azimuth),
                math.cos(cone_angle)
            )
            
            # 将锥形方向转换到发射方向
            # 这里简化处理，实际应该做完整的旋转变换
            base_velocity = base_velocity.length() * cone_dir
            
        return base_velocity
        
    def _vary_color(self, base_color: Vec3) -> Vec3:
        """添加颜色变化"""
        if self.color_variation <= 0:
            return Vec3(base_color)
            
        variation = Vec3(
            random.uniform(-self.color_variation, self.color_variation),
            random.uniform(-self.color_variation, self.color_variation),
            random.uniform(-self.color_variation, self.color_variation)
        )
        
        result = base_color + variation
        
        # 确保颜色值在有效范围内
        result.x = max(0.0, min(1.0, result.x))
        result.y = max(0.0, min(1.0, result.y))
        result.z = max(0.0, min(1.0, result.z))
        
        return result
        
    def _update_particles(self, dt: float):
        """更新所有粒子"""
        for particle in self.particles:
            if particle.is_alive():
                particle.update(dt)
                
    def _cleanup_dead_particles(self):
        """清理死亡粒子"""
        alive_particles = []
        
        for particle in self.particles:
            if particle.is_alive():
                alive_particles.append(particle)
            else:
                # 回收到对象池
                self.particle_pool.append(particle)
                
        self.particles = alive_particles
        
    def get_particles(self) -> List[Particle]:
        """获取所有活跃粒子"""
        return [p for p in self.particles if p.is_alive()]
        
    def get_particle_count(self) -> int:
        """获取粒子数量"""
        return len([p for p in self.particles if p.is_alive()])
        
    def is_active(self) -> bool:
        """检查发射器是否活跃"""
        return self.active or len(self.particles) > 0
        
    def should_remove(self) -> bool:
        """检查是否应该移除发射器"""
        return not self.active and len(self.particles) == 0
        
    def stop_emission(self):
        """停止发射新粒子"""
        self.active = False
        
    def resume_emission(self):
        """恢复发射粒子"""
        self.active = True
        
    def set_position(self, position: Point3):
        """设置发射器位置"""
        self.position = position
        
    def set_enabled(self, enabled: bool):
        """设置发射器启用状态"""
        self.enabled = enabled
        
    def cleanup(self):
        """清理发射器资源"""
        self.particles.clear()
        self.particle_pool.clear()
        self.active = False
        self.enabled = False