"""
高级骨骼动画系统 - 核心模块
提供完整的骨骼动画支持，包括加载、播放、控制等核心功能
"""

import math
import json
import os
from collections import defaultdict, deque
from typing import Dict, List, Tuple, Optional, Union, Any, Callable
from dataclasses import dataclass, field
from enum import Enum

from panda3d.core import *
from direct.actor.Actor import Actor
from direct.interval.IntervalGlobal import *
from direct.showbase.DirectObject import DirectObject
from direct.distributed.ClockDelta import globalClockDelta

# 导入工具模块
from .tools import AnimationAnalyzer, AnimationEditor, DebugVisualizer, AnimationProfiler

# 定义常量
DEFAULT_ANIMATION_SETTINGS = {
    'default_play_rate': 1.0,
    'default_loop': False,
    'blend_time': 0.3,
    'max_actors': 1000,
    'cache_size': 100,
    'lod_distance_thresholds': [10.0, 25.0, 50.0],
    'lod_frame_rates': [1.0, 0.5, 0.25, 0.1]
}

# 枚举定义
class AnimationState(Enum):
    """动画状态枚举"""
    STOPPED = 0
    PLAYING = 1
    PAUSED = 2
    BLENDING = 3
    LOOPING = 4

class BlendMode(Enum):
    """混合模式枚举"""
    LINEAR = 0
    EASE_IN = 1
    EASE_OUT = 2
    EASE_IN_OUT = 3
    OVERWRITE = 4

class LODLevel(Enum):
    """LOD级别枚举"""
    HIGH = 0
    MEDIUM = 1
    LOW = 2
    VERY_LOW = 3

@dataclass
class AnimationInfo:
    """动画信息数据类"""
    name: str
    frame_rate: float
    num_frames: int
    play_rate: float
    current_frame: float
    state: AnimationState
    loop: bool
    start_time: float
    duration: float
    blend_weight: float = 1.0
    blend_in_time: float = 0.0
    blend_out_time: float = 0.0

@dataclass
class ActorInfo:
    """Actor信息数据类"""
    actor_id: str
    actor: Actor
    model_path: str
    anim_paths: Dict[str, str]
    position: Tuple[float, float, float]
    scale: Union[float, Tuple[float, float, float]]
    animations: Dict[str, AnimationInfo] = field(default_factory=dict)
    active_animations: List[str] = field(default_factory=list)
    lod_level: LODLevel = LODLevel.HIGH
    last_update_time: float = 0.0
    is_networked: bool = False
    network_id: str = ""

@dataclass
class BlendInfo:
    """混合信息数据类"""
    from_anim: str
    to_anim: str
    blend_time: float
    blend_mode: BlendMode
    current_time: float = 0.0
    total_time: float = 0.0
    active: bool = False

@dataclass
class IKChain:
    """IK链数据类"""
    chain_name: str
    end_effector: str
    pole_vector: Optional[Tuple[float, float, float]]
    iterations: int
    enabled: bool = True
    target_position: Optional[Tuple[float, float, float]] = None

class AnimationCache:
    """动画缓存系统"""
    
    def __init__(self, max_size: int = 100):
        self.max_size = max_size
        self.cache: Dict[str, Any] = {}
        self.access_order: deque = deque()
        self.hits = 0
        self.misses = 0
        
    def get(self, key: str) -> Optional[Any]:
        """获取缓存项"""
        if key in self.cache:
            self.hits += 1
            # 更新访问顺序
            self.access_order.remove(key)
            self.access_order.append(key)
            return self.cache[key]
        else:
            self.misses += 1
            return None
            
    def put(self, key: str, value: Any) -> None:
        """放入缓存项"""
        # 如果缓存已满，移除最久未使用的项
        if len(self.cache) >= self.max_size:
            oldest_key = self.access_order.popleft()
            del self.cache[oldest_key]
            
        self.cache[key] = value
        self.access_order.append(key)
        
    def invalidate(self, key: str) -> None:
        """使缓存项失效"""
        if key in self.cache:
            del self.cache[key]
            self.access_order.remove(key)
            
    def clear(self) -> None:
        """清空缓存"""
        self.cache.clear()
        self.access_order.clear()
        self.hits = 0
        self.misses = 0
        
    def get_stats(self) -> Dict[str, Any]:
        """获取缓存统计信息"""
        total_requests = self.hits + self.misses
        hit_rate = self.hits / total_requests if total_requests > 0 else 0
        return {
            'size': len(self.cache),
            'max_size': self.max_size,
            'hits': self.hits,
            'misses': self.misses,
            'hit_rate': hit_rate
        }

class AnimationCompressor:
    """动画压缩系统"""
    
    def __init__(self):
        self.position_threshold = 0.001
        self.rotation_threshold = 0.01
        self.scale_threshold = 0.001
        
    def compress_keyframes(self, keyframes: List[Tuple[float, Tuple[float, float, float]]], 
                          data_type: str = 'position') -> List[Tuple[float, Tuple[float, float, float]]]:
        """
        压缩关键帧数据
        :param keyframes: 关键帧列表 [(time, (x, y, z)), ...]
        :param data_type: 数据类型 ('position', 'rotation', 'scale')
        :return: 压缩后的关键帧列表
        """
        if len(keyframes) <= 2:
            return keyframes
            
        compressed = [keyframes[0]]  # 总是保留第一帧
        last_keyframe = keyframes[0]
        
        # 根据数据类型选择阈值
        threshold = getattr(self, f'{data_type}_threshold', 0.001)
        
        for i in range(1, len(keyframes) - 1):
            current_keyframe = keyframes[i]
            next_keyframe = keyframes[i + 1]
            
            # 检查当前帧是否可以被简化
            if not self._is_keyframe_necessary(last_keyframe, current_keyframe, next_keyframe, threshold, data_type):
                continue
                
            compressed.append(current_keyframe)
            last_keyframe = current_keyframe
            
        compressed.append(keyframes[-1])  # 总是保留最后一帧
        return compressed
        
    def _is_keyframe_necessary(self, prev_frame: Tuple[float, Tuple[float, float, float]], 
                              current_frame: Tuple[float, Tuple[float, float, float]], 
                              next_frame: Tuple[float, Tuple[float, float, float]], 
                              threshold: float, data_type: str) -> bool:
        """
        判断关键帧是否必要
        :param prev_frame: 前一帧
        :param current_frame: 当前帧
        :param next_frame: 后一帧
        :param threshold: 阈值
        :param data_type: 数据类型
        :return: 是否必要
        """
        prev_time, prev_data = prev_frame
        curr_time, curr_data = current_frame
        next_time, next_data = next_frame
        
        # 计算线性插值
        t = (curr_time - prev_time) / (next_time - prev_time)
        interpolated = tuple(prev_data[i] + t * (next_data[i] - prev_data[i]) for i in range(3))
        
        # 计算与实际值的差异
        diff = math.sqrt(sum((curr_data[i] - interpolated[i]) ** 2 for i in range(3)))
        
        return diff > threshold

class SkeletalAnimationCore(DirectObject):
    """
    骨骼动画核心系统
    提供完整的骨骼动画管理功能
    """
    
    def __init__(self, world):
        """
        初始化骨骼动画核心系统
        :param world: 世界对象
        """
        super().__init__()
        self.world = world
        self.actors: Dict[str, ActorInfo] = {}
        self.actor_configs: Dict[str, Dict[str, Any]] = {}
        self.blend_infos: Dict[str, Dict[str, BlendInfo]] = defaultdict(dict)
        self.ik_chains: Dict[str, Dict[str, IKChain]] = defaultdict(dict)
        self.animation_cache = AnimationCache(DEFAULT_ANIMATION_SETTINGS['cache_size'])
        self.compressor = AnimationCompressor()
        self.event_handlers: Dict[str, List[Callable]] = defaultdict(list)
        self.is_updating = False
        self.update_task = None
        
        # 工具系统
        self.analyzer = AnimationAnalyzer(self)
        self.editor = AnimationEditor(self)
        self.visualizer = DebugVisualizer(world)
        self.profiler = AnimationProfiler(self)
        
        # 性能统计
        self.stats = {
            'actors_loaded': 0,
            'animations_played': 0,
            'blends_performed': 0,
            'ik_calculations': 0,
            'cache_hits': 0,
            'cache_misses': 0
        }
        
        print("骨骼动画核心系统初始化完成")
        
    def load_actor(self, model_path: str, anim_paths: Optional[Dict[str, str]] = None, 
                   actor_id: Optional[str] = None, position: Tuple[float, float, float] = (0, 0, 0),
                   scale: Union[float, Tuple[float, float, float]] = 1.0) -> Tuple[Optional[Actor], str]:
        """
        加载Actor模型
        :param model_path: 模型文件路径
        :param anim_paths: 动画文件路径字典 {anim_name: anim_path}
        :param actor_id: Actor标识符，如果为None则自动生成
        :param position: 位置坐标 (x, y, z)
        :param scale: 缩放比例
        :return: (Actor对象, actor_id)
        """
        try:
            # 检查模型文件是否存在
            if not os.path.exists(model_path):
                raise FileNotFoundError(f"模型文件不存在: {model_path}")
                
            # 生成Actor ID
            if actor_id is None:
                actor_id = f"actor_{len(self.actors)}"
                
            # 检查Actor是否已存在
            if actor_id in self.actors:
                print(f"警告: Actor {actor_id} 已存在，将被替换")
                self.unload_actor(actor_id)
                
            # 检查缓存
            cache_key = f"actor_{model_path}_{hash(str(anim_paths))}"
            cached_actor = self.animation_cache.get(cache_key)
            
            if cached_actor:
                actor = cached_actor
                print(f"从缓存加载Actor: {actor_id}")
            else:
                # 创建Actor
                if anim_paths:
                    # 验证动画文件
                    valid_anims = {}
                    for anim_name, anim_path in anim_paths.items():
                        if os.path.exists(anim_path):
                            valid_anims[anim_name] = anim_path
                        else:
                            print(f"警告: 动画文件不存在: {anim_path}")
                    actor = Actor(model_path, valid_anims)
                else:
                    actor = Actor(model_path)
                    
                # 缓存Actor
                self.animation_cache.put(cache_key, actor)
                
            # 设置位置和缩放
            actor.setPos(*position)
            if isinstance(scale, (int, float)):
                actor.setScale(scale)
            else:
                actor.setScale(*scale)
                
            # 将Actor添加到场景中
            actor.reparentTo(self.world.render)
            actor.setName(actor_id)
            
            # 创建Actor信息
            actor_info = ActorInfo(
                actor_id=actor_id,
                actor=actor,
                model_path=model_path,
                anim_paths=anim_paths or {},
                position=position,
                scale=scale
            )
            
            # 初始化动画信息
            for anim_name in actor.getAnimNames():
                control = actor.getAnimControl(anim_name)
                if control:
                    anim_info = AnimationInfo(
                        name=anim_name,
                        frame_rate=actor.getFrameRate(anim_name),
                        num_frames=actor.getNumFrames(anim_name),
                        play_rate=DEFAULT_ANIMATION_SETTINGS['default_play_rate'],
                        current_frame=0.0,
                        state=AnimationState.STOPPED,
                        loop=DEFAULT_ANIMATION_SETTINGS['default_loop'],
                        start_time=0.0,
                        duration=control.getDuration()
                    )
                    actor_info.animations[anim_name] = anim_info
                    
            # 存储Actor信息
            self.actors[actor_id] = actor_info
            self.actor_configs[actor_id] = {
                'model_path': model_path,
                'anim_paths': anim_paths,
                'position': position,
                'scale': scale
            }
            
            self.stats['actors_loaded'] += 1
            print(f"成功加载Actor: {actor_id}")
            print(f"  模型: {model_path}")
            print(f"  位置: {position}")
            print(f"  缩放: {scale}")
            print(f"  可用动画: {list(actor_info.animations.keys())}")
            
            return actor, actor_id
            
        except Exception as e:
            print(f"加载Actor失败: {e}")
            import traceback
            traceback.print_exc()
            return None, ""
            
    def unload_actor(self, actor_id: str) -> bool:
        """
        卸载Actor
        :param actor_id: Actor标识符
        :return: 是否成功卸载
        """
        if actor_id not in self.actors:
            print(f"错误: Actor {actor_id} 不存在")
            return False
            
        try:
            actor_info = self.actors[actor_id]
            actor = actor_info.actor
            
            # 停止所有动画
            self.stop_all_animations(actor_id)
            
            # 清理混合信息
            if actor_id in self.blend_infos:
                del self.blend_infos[actor_id]
                
            # 清理IK链
            if actor_id in self.ik_chains:
                del self.ik_chains[actor_id]
                
            # 从场景中移除
            actor.cleanup()
            
            # 从管理器中移除
            del self.actors[actor_id]
            if actor_id in self.actor_configs:
                del self.actor_configs[actor_id]
                
            print(f"已卸载Actor: {actor_id}")
            return True
            
        except Exception as e:
            print(f"卸载Actor失败: {e}")
            import traceback
            traceback.print_exc()
            return False
            
    def play_animation(self, actor_id: str, anim_name: str, loop: bool = False, 
                      play_rate: float = 1.0, start_frame: Optional[int] = None, 
                      end_frame: Optional[int] = None) -> bool:
        """
        播放动画
        :param actor_id: Actor标识符
        :param anim_name: 动画名称
        :param loop: 是否循环播放
        :param play_rate: 播放速度
        :param start_frame: 起始帧
        :param end_frame: 结束帧
        :return: 是否成功播放
        """
        if actor_id not in self.actors:
            print(f"错误: Actor {actor_id} 不存在")
            return False
            
        actor_info = self.actors[actor_id]
        actor = actor_info.actor
        
        # 检查动画是否存在
        if anim_name not in actor.getAnimNames():
            print(f"错误: 动画 {anim_name} 不存在于Actor {actor_id} 中")
            print(f"  可用动画: {actor.getAnimNames()}")
            return False
            
        try:
            # 设置播放速度
            actor.setPlayRate(play_rate, anim_name)
            
            # 播放动画
            if loop:
                if start_frame is not None and end_frame is not None:
                    actor.loop(anim_name, restart=False, fromFrame=start_frame, toFrame=end_frame)
                else:
                    actor.loop(anim_name, restart=False)
            else:
                if start_frame is not None and end_frame is not None:
                    actor.play(anim_name, fromFrame=start_frame, toFrame=end_frame)
                else:
                    actor.play(anim_name)
                    
            # 更新动画信息
            if anim_name in actor_info.animations:
                anim_info = actor_info.animations[anim_name]
                anim_info.state = AnimationState.LOOPING if loop else AnimationState.PLAYING
                anim_info.loop = loop
                anim_info.play_rate = play_rate
                anim_info.start_time = globalClock.getRealTime()
                
            # 添加到活动动画列表
            if anim_name not in actor_info.active_animations:
                actor_info.active_animations.append(anim_name)
                
            self.stats['animations_played'] += 1
            print(f"播放动画: {anim_name} (Actor: {actor_id}, 循环: {loop}, 速度: {play_rate}x)")
            return True
            
        except Exception as e:
            print(f"播放动画失败: {e}")
            import traceback
            traceback.print_exc()
            return False
            
    def stop_animation(self, actor_id: str, anim_name: Optional[str] = None) -> bool:
        """
        停止动画
        :param actor_id: Actor标识符
        :param anim_name: 动画名称，如果为None则停止所有动画
        :return: 是否成功停止
        """
        if actor_id not in self.actors:
            print(f"错误: Actor {actor_id} 不存在")
            return False
            
        actor_info = self.actors[actor_id]
        actor = actor_info.actor
        
        try:
            if anim_name:
                # 停止指定动画
                if anim_name in actor.getAnimNames():
                    actor.stop(anim_name)
                    # 从活动动画列表中移除
                    if anim_name in actor_info.active_animations:
                        actor_info.active_animations.remove(anim_name)
                    # 更新动画状态
                    if anim_name in actor_info.animations:
                        actor_info.animations[anim_name].state = AnimationState.STOPPED
                    print(f"停止动画: {anim_name} (Actor: {actor_id})")
                else:
                    print(f"警告: 动画 {anim_name} 不存在于Actor {actor_id} 中")
            else:
                # 停止所有动画
                actor.stop()
                # 清空活动动画列表
                actor_info.active_animations.clear()
                # 更新所有动画状态
                for anim_info in actor_info.animations.values():
                    anim_info.state = AnimationState.STOPPED
                print(f"停止所有动画 (Actor: {actor_id})")
                
            return True
            
        except Exception as e:
            print(f"停止动画失败: {e}")
            import traceback
            traceback.print_exc()
            return False
            
    def stop_all_animations(self, actor_id: str) -> bool:
        """
        停止指定Actor的所有动画
        :param actor_id: Actor标识符
        :return: 是否成功停止
        """
        return self.stop_animation(actor_id)
        
    def pause_animation(self, actor_id: str, anim_name: Optional[str] = None) -> bool:
        """
        暂停动画
        :param actor_id: Actor标识符
        :param anim_name: 动画名称，如果为None则暂停所有动画
        :return: 是否成功暂停
        """
        if actor_id not in self.actors:
            print(f"错误: Actor {actor_id} 不存在")
            return False
            
        actor_info = self.actors[actor_id]
        actor = actor_info.actor
        
        try:
            if anim_name:
                if anim_name in actor.getAnimNames():
                    control = actor.getAnimControl(anim_name)
                    if control and control.isPlaying():
                        # 通过设置播放速度为0来模拟暂停
                        current_rate = actor.getPlayRate(anim_name)
                        actor.setPlayRate(0, anim_name)
                        # 更新动画状态
                        if anim_name in actor_info.animations:
                            actor_info.animations[anim_name].state = AnimationState.PAUSED
                        print(f"暂停动画: {anim_name} (Actor: {actor_id})")
                        return True
                else:
                    print(f"警告: 动画 {anim_name} 不存在于Actor {actor_id} 中")
            else:
                # 暂停所有活动动画
                success = False
                for active_anim in actor_info.active_animations:
                    control = actor.getAnimControl(active_anim)
                    if control and control.isPlaying():
                        current_rate = actor.getPlayRate(active_anim)
                        actor.setPlayRate(0, active_anim)
                        if active_anim in actor_info.animations:
                            actor_info.animations[active_anim].state = AnimationState.PAUSED
                        success = True
                if success:
                    print(f"暂停所有动画 (Actor: {actor_id})")
                return success
                
        except Exception as e:
            print(f"暂停动画失败: {e}")
            import traceback
            traceback.print_exc()
            return False
            
    def resume_animation(self, actor_id: str, anim_name: Optional[str] = None) -> bool:
        """
        恢复动画播放
        :param actor_id: Actor标识符
        :param anim_name: 动画名称，如果为None则恢复所有动画
        :return: 是否成功恢复
        """
        if actor_id not in self.actors:
            print(f"错误: Actor {actor_id} 不存在")
            return False
            
        actor_info = self.actors[actor_id]
        actor = actor_info.actor
        
        try:
            if anim_name:
                if anim_name in actor.getAnimNames():
                    control = actor.getAnimControl(anim_name)
                    if control and control.getPlayRate() == 0:
                        # 恢复正常播放速度
                        actor.setPlayRate(1.0, anim_name)
                        # 更新动画状态
                        if anim_name in actor_info.animations:
                            anim_state = AnimationState.LOOPING if actor_info.animations[anim_name].loop else AnimationState.PLAYING
                            actor_info.animations[anim_name].state = anim_state
                        print(f"恢复动画: {anim_name} (Actor: {actor_id})")
                        return True
                else:
                    print(f"警告: 动画 {anim_name} 不存在于Actor {actor_id} 中")
            else:
                # 恢复所有暂停的动画
                success = False
                for active_anim in actor_info.active_animations:
                    control = actor.getAnimControl(active_anim)
                    if control and control.getPlayRate() == 0:
                        actor.setPlayRate(1.0, active_anim)
                        if active_anim in actor_info.animations:
                            anim_state = AnimationState.LOOPING if actor_info.animations[active_anim].loop else AnimationState.PLAYING
                            actor_info.animations[active_anim].state = anim_state
                        success = True
                if success:
                    print(f"恢复所有动画 (Actor: {actor_id})")
                return success
                
        except Exception as e:
            print(f"恢复动画失败: {e}")
            import traceback
            traceback.print_exc()
            return False
            
    def set_animation_speed(self, actor_id: str, anim_name: str, speed: float) -> bool:
        """
        设置动画播放速度
        :param actor_id: Actor标识符
        :param anim_name: 动画名称
        :param speed: 播放速度
        :return: 是否成功设置
        """
        if actor_id not in self.actors:
            print(f"错误: Actor {actor_id} 不存在")
            return False
            
        actor_info = self.actors[actor_id]
        actor = actor_info.actor
        
        try:
            if anim_name in actor.getAnimNames():
                actor.setPlayRate(speed, anim_name)
                # 更新动画信息
                if anim_name in actor_info.animations:
                    actor_info.animations[anim_name].play_rate = speed
                print(f"设置动画速度: {anim_name} 为 {speed}x (Actor: {actor_id})")
                return True
            else:
                print(f"警告: 动画 {anim_name} 不存在于Actor {actor_id} 中")
                return False
                
        except Exception as e:
            print(f"设置动画速度失败: {e}")
            import traceback
            traceback.print_exc()
            return False
            
    def blend_animations(self, actor_id: str, from_anim: str, to_anim: str, 
                        blend_time: float = 0.3, blend_mode: BlendMode = BlendMode.LINEAR) -> bool:
        """
        混合两个动画
        :param actor_id: Actor标识符
        :param from_anim: 起始动画名称
        :param to_anim: 目标动画名称
        :param blend_time: 混合时间
        :param blend_mode: 混合模式
        :return: 是否成功开始混合
        """
        if actor_id not in self.actors:
            print(f"错误: Actor {actor_id} 不存在")
            return False
            
        actor_info = self.actors[actor_id]
        actor = actor_info.actor
        
        # 检查动画是否存在
        if from_anim not in actor.getAnimNames():
            print(f"错误: 起始动画 {from_anim} 不存在于Actor {actor_id} 中")
            return False
            
        if to_anim not in actor.getAnimNames():
            print(f"错误: 目标动画 {to_anim} 不存在于Actor {actor_id} 中")
            return False
            
        try:
            # 创建混合信息
            blend_info = BlendInfo(
                from_anim=from_anim,
                to_anim=to_anim,
                blend_time=blend_time,
                blend_mode=blend_mode,
                current_time=0.0,
                total_time=blend_time,
                active=True
            )
            
            # 存储混合信息
            blend_id = f"{from_anim}_to_{to_anim}"
            self.blend_infos[actor_id][blend_id] = blend_info
            
            # 开始混合过程
            self._start_animation_blend(actor_info, blend_info)
            
            self.stats['blends_performed'] += 1
            print(f"开始动画混合: {from_anim} -> {to_anim} (Actor: {actor_id}, 时间: {blend_time}s)")
            return True
            
        except Exception as e:
            print(f"动画混合失败: {e}")
            import traceback
            traceback.print_exc()
            return False
            
    def _start_animation_blend(self, actor_info: ActorInfo, blend_info: BlendInfo) -> None:
        """
        开始动画混合过程
        :param actor_info: Actor信息
        :param blend_info: 混合信息
        """
        actor = actor_info.actor
        from_anim = blend_info.from_anim
        to_anim = blend_info.to_anim
        
        # 停止起始动画
        actor.stop(from_anim)
        
        # 播放目标动画
        actor.play(to_anim)
        
        # 设置混合权重（简化实现）
        if to_anim in actor_info.animations:
            actor_info.animations[to_anim].blend_weight = 1.0
            
    def get_actor(self, actor_id: str) -> Optional[Actor]:
        """
        获取Actor对象
        :param actor_id: Actor标识符
        :return: Actor对象或None
        """
        if actor_id in self.actors:
            return self.actors[actor_id].actor
        return None
        
    def get_actor_animations(self, actor_id: str) -> List[str]:
        """
        获取Actor的所有动画名称
        :param actor_id: Actor标识符
        :return: 动画名称列表
        """
        if actor_id in self.actors:
            return list(self.actors[actor_id].animations.keys())
        return []
        
    def get_animation_info(self, actor_id: str, anim_name: str) -> Optional[Dict[str, Any]]:
        """
        获取动画信息
        :param actor_id: Actor标识符
        :param anim_name: 动画名称
        :return: 动画信息字典
        """
        if actor_id not in self.actors:
            print(f"错误: Actor {actor_id} 不存在")
            return None
            
        actor_info = self.actors[actor_id]
        
        if anim_name not in actor_info.animations:
            print(f"错误: 动画 {anim_name} 不存在于Actor {actor_id} 中")
            return None
            
        anim_info = actor_info.animations[anim_name]
        actor = actor_info.actor
        control = actor.getAnimControl(anim_name) if anim_name in actor.getAnimNames() else None
        
        return {
            'name': anim_info.name,
            'frame_rate': anim_info.frame_rate,
            'num_frames': anim_info.num_frames,
            'play_rate': anim_info.play_rate,
            'current_frame': anim_info.current_frame,
            'state': anim_info.state.name,
            'loop': anim_info.loop,
            'start_time': anim_info.start_time,
            'duration': anim_info.duration,
            'is_playing': control.isPlaying() if control else False,
            'is_finished': control.isFinished() if control else True
        }
        
    def get_actor_info(self, actor_id: str) -> Optional[Dict[str, Any]]:
        """
        获取Actor详细信息
        :param actor_id: Actor标识符
        :return: Actor信息字典
        """
        if actor_id not in self.actors:
            print(f"错误: Actor {actor_id} 不存在")
            return None
            
        actor_info = self.actors[actor_id]
        actor = actor_info.actor
        
        return {
            'id': actor_info.actor_id,
            'model_path': actor_info.model_path,
            'anim_paths': actor_info.anim_paths,
            'position': actor.getPos().toTuple(),
            'scale': actor.getScale().toTuple(),
            'available_animations': list(actor_info.animations.keys()),
            'active_animations': actor_info.active_animations.copy(),
            'lod_level': actor_info.lod_level.name,
            'has_character': actor.hasCharacter(),
            'num_parts': actor.getNumParts(),
            'bounds': {
                'min': actor.getTightBounds()[0].toTuple() if actor.getTightBounds() else None,
                'max': actor.getTightBounds()[1].toTuple() if actor.getTightBounds() else None
            }
        }
        
    def set_actor_position(self, actor_id: str, x: float, y: float, z: float) -> bool:
        """
        设置Actor位置
        :param actor_id: Actor标识符
        :param x: X坐标
        :param y: Y坐标
        :param z: Z坐标
        :return: 是否成功设置
        """
        if actor_id in self.actors:
            self.actors[actor_id].actor.setPos(x, y, z)
            self.actors[actor_id].position = (x, y, z)
            if actor_id in self.actor_configs:
                self.actor_configs[actor_id]['position'] = (x, y, z)
            print(f"设置Actor {actor_id} 位置: ({x}, {y}, {z})")
            return True
        return False
        
    def set_actor_scale(self, actor_id: str, scale: Union[float, Tuple[float, float, float]]) -> bool:
        """
        设置Actor缩放
        :param actor_id: Actor标识符
        :param scale: 缩放值 (数值或(x, y, z)元组)
        :return: 是否成功设置
        """
        if actor_id in self.actors:
            actor = self.actors[actor_id].actor
            if isinstance(scale, (int, float)):
                actor.setScale(scale)
            else:
                actor.setScale(*scale)
            self.actors[actor_id].scale = scale
            if actor_id in self.actor_configs:
                self.actor_configs[actor_id]['scale'] = scale
            print(f"设置Actor {actor_id} 缩放: {scale}")
            return True
        return False
        
    def update(self, dt: float) -> None:
        """
        更新动画系统
        :param dt: 时间增量
        """
        if not self.is_updating:
            return
            
        current_time = globalClock.getRealTime()
        
        # 更新所有Actor
        for actor_id, actor_info in self.actors.items():
            # 更新动画信息
            self._update_actor_animations(actor_info, dt, current_time)
            
            # 更新混合
            self._update_blends(actor_info, dt)
            
            # 更新IK
            self._update_ik(actor_info)
            
            # 更新LOD
            self._update_lod(actor_info, current_time)
            
        # 更新工具系统
        self._update_tools(dt)
            
    def _update_actor_animations(self, actor_info: ActorInfo, dt: float, current_time: float) -> None:
        """
        更新Actor动画
        :param actor_info: Actor信息
        :param dt: 时间增量
        :param current_time: 当前时间
        """
        actor = actor_info.actor
        
        # 更新活动动画的当前帧信息
        for anim_name in actor_info.active_animations:
            if anim_name in actor_info.animations:
                anim_info = actor_info.animations[anim_name]
                control = actor.getAnimControl(anim_name) if anim_name in actor.getAnimNames() else None
                
                if control and control.isPlaying():
                    anim_info.current_frame = actor.getCurrentFrame(anim_name)
                    anim_info.state = AnimationState.LOOPING if anim_info.loop else AnimationState.PLAYING
                elif control and control.getPlayRate() == 0:
                    anim_info.state = AnimationState.PAUSED
                else:
                    anim_info.state = AnimationState.STOPPED
                    
        actor_info.last_update_time = current_time
        
    def _update_blends(self, actor_info: ActorInfo, dt: float) -> None:
        """
        更新动画混合
        :param actor_info: Actor信息
        :param dt: 时间增量
        """
        actor_id = actor_info.actor_id
        
        if actor_id not in self.blend_infos:
            return
            
        # 更新所有混合
        finished_blends = []
        for blend_id, blend_info in self.blend_infos[actor_id].items():
            if not blend_info.active:
                continue
                
            blend_info.current_time += dt
            
            # 计算混合权重
            t = min(1.0, blend_info.current_time / blend_info.total_time)
            
            # 根据混合模式应用缓动函数
            if blend_info.blend_mode == BlendMode.EASE_IN:
                t = t * t
            elif blend_info.blend_mode == BlendMode.EASE_OUT:
                t = 1.0 - (1.0 - t) * (1.0 - t)
            elif blend_info.blend_mode == BlendMode.EASE_IN_OUT:
                t = t * t * (3.0 - 2.0 * t)
                
            # 更新目标动画的混合权重
            if blend_info.to_anim in actor_info.animations:
                actor_info.animations[blend_info.to_anim].blend_weight = t
                
            # 检查混合是否完成
            if blend_info.current_time >= blend_info.total_time:
                blend_info.active = False
                finished_blends.append(blend_id)
                
        # 移除已完成的混合
        for blend_id in finished_blends:
            del self.blend_infos[actor_id][blend_id]
            
    def _update_ik(self, actor_info: ActorInfo) -> None:
        """
        更新IK计算
        :param actor_info: Actor信息
        """
        actor_id = actor_info.actor_id
        
        if actor_id not in self.ik_chains:
            return
            
        # 更新所有IK链
        for chain_name, ik_chain in self.ik_chains[actor_id].items():
            if not ik_chain.enabled or not ik_chain.target_position:
                continue
                
            self._solve_ik_chain(actor_info, ik_chain)
            self.stats['ik_calculations'] += 1
            
    def _solve_ik_chain(self, actor_info: ActorInfo, ik_chain: IKChain) -> None:
        """
        解算IK链
        :param actor_info: Actor信息
        :param ik_chain: IK链信息
        """
        actor = actor_info.actor
        
        # 简化的CCD IK算法实现
        end_effector = actor.exposeJoint(None, "modelRoot", ik_chain.end_effector)
        if not end_effector:
            return
            
        target_pos = Point3(*ik_chain.target_position)
        current_pos = end_effector.getPos(actor)
        
        # 如果已经足够接近，不需要调整
        distance = (target_pos - current_pos).length()
        if distance < 0.001:
            return
            
        # CCD算法迭代
        for _ in range(ik_chain.iterations):
            # 从末端关节向前迭代调整
            # 这里简化处理，实际应该遍历整条骨骼链
            direction = target_pos - current_pos
            direction.normalize()
            
            # 简单的朝向调整
            end_effector.lookAt(target_pos)
            
            # 更新位置
            current_pos = end_effector.getPos(actor)
            distance = (target_pos - current_pos).length()
            if distance < 0.001:
                break
                
    def _update_lod(self, actor_info: ActorInfo, current_time: float) -> None:
        """
        更新LOD级别
        :param actor_info: Actor信息
        :param current_time: 当前时间
        """
        # LOD更新可以基于距离、性能或其他因素
        # 这里简化实现，实际项目中可能需要更复杂的逻辑
        pass
        
    def _update_tools(self, dt: float) -> None:
        """
        更新工具系统
        :param dt: 时间增量
        """
        # 更新性能分析器
        self.profiler.sample_performance()
        
        # 更新调试可视化
        self.visualizer.update_visualizations(self.actors)
        
    def add_ik_chain(self, actor_id: str, chain_name: str, end_effector: str,
                     pole_vector: Optional[Tuple[float, float, float]] = None,
                     iterations: int = 10) -> bool:
        """
        添加IK链
        :param actor_id: Actor标识符
        :param chain_name: 链名称
        :param end_effector: 终端效应器（骨骼名称）
        :param pole_vector: 极向量（用于控制弯曲方向）
        :param iterations: 迭代次数
        :return: 是否成功添加
        """
        if actor_id not in self.actors:
            print(f"错误: Actor {actor_id} 不存在")
            return False
            
        # 检查骨骼是否存在
        actor = self.actors[actor_id].actor
        effector_joint = actor.exposeJoint(None, "modelRoot", end_effector)
        if not effector_joint:
            print(f"错误: 未找到骨骼 {end_effector}")
            return False
            
        # 创建IK链
        ik_chain = IKChain(
            chain_name=chain_name,
            end_effector=end_effector,
            pole_vector=pole_vector,
            iterations=iterations,
            enabled=True
        )
        
        # 存储IK链
        self.ik_chains[actor_id][chain_name] = ik_chain
        print(f"添加IK链: {chain_name} -> {end_effector} (Actor: {actor_id})")
        return True
        
    def set_ik_target(self, actor_id: str, chain_name: str, target_pos: Tuple[float, float, float]) -> bool:
        """
        设置IK目标位置
        :param actor_id: Actor标识符
        :param chain_name: 链名称
        :param target_pos: 目标位置 (x, y, z)
        :return: 是否成功设置
        """
        if actor_id not in self.ik_chains or chain_name not in self.ik_chains[actor_id]:
            print(f"错误: IK链 {chain_name} 不存在于Actor {actor_id} 中")
            return False
            
        # 设置目标位置
        self.ik_chains[actor_id][chain_name].target_position = target_pos
        return True
        
    def enable_ik_chain(self, actor_id: str, chain_name: str, enabled: bool = True) -> bool:
        """
        启用/禁用IK链
        :param actor_id: Actor标识符
        :param chain_name: 链名称
        :param enabled: 是否启用
        :return: 是否成功设置
        """
        if actor_id not in self.ik_chains or chain_name not in self.ik_chains[actor_id]:
            print(f"错误: IK链 {chain_name} 不存在于Actor {actor_id} 中")
            return False
            
        self.ik_chains[actor_id][chain_name].enabled = enabled
        status = "启用" if enabled else "禁用"
        print(f"{status}IK链: {chain_name} (Actor: {actor_id})")
        return True
        
    def get_cache_stats(self) -> Dict[str, Any]:
        """
        获取缓存统计信息
        :return: 缓存统计
        """
        return self.animation_cache.get_stats()
        
    def get_system_stats(self) -> Dict[str, Any]:
        """
        获取系统统计信息
        :return: 系统统计
        """
        cache_stats = self.animation_cache.get_stats()
        return {
            'actors_count': len(self.actors),
            'animations_played': self.stats['animations_played'],
            'blends_performed': self.stats['blends_performed'],
            'ik_calculations': self.stats['ik_calculations'],
            'cache_stats': cache_stats,
            'active_actors': len([a for a in self.actors.values() if a.active_animations])
        }
        
    def start_updating(self) -> None:
        """
        开始更新动画系统
        """
        if not self.is_updating:
            self.is_updating = True
            print("动画系统更新已启动")
            
    def stop_updating(self) -> None:
        """
        停止更新动画系统
        """
        if self.is_updating:
            self.is_updating = False
            print("动画系统更新已停止")
            
    def clear_cache(self) -> None:
        """
        清空动画缓存
        """
        self.animation_cache.clear()
        print("动画缓存已清空")
        
    def reset_stats(self) -> None:
        """
        重置统计信息
        """
        self.stats = {
            'actors_loaded': 0,
            'animations_played': 0,
            'blends_performed': 0,
            'ik_calculations': 0,
            'cache_hits': 0,
            'cache_misses': 0
        }
        self.animation_cache.hits = 0
        self.animation_cache.misses = 0
        print("统计信息已重置")
        
    # 工具系统访问方法
    def get_analyzer(self) -> AnimationAnalyzer:
        """
        获取动画分析器
        :return: AnimationAnalyzer实例
        """
        return self.analyzer
        
    def get_editor(self) -> AnimationEditor:
        """
        获取动画编辑器
        :return: AnimationEditor实例
        """
        return self.editor
        
    def get_visualizer(self) -> DebugVisualizer:
        """
        获取调试可视化工具
        :return: DebugVisualizer实例
        """
        return self.visualizer
        
    def get_profiler(self) -> AnimationProfiler:
        """
        获取性能分析器
        :return: AnimationProfiler实例
        """
        return self.profiler