"""
骨骼动画系统插件 - 网络同步模块
提供动画状态网络同步、多人协作等功能
"""

from panda3d.core import *
from direct.distributed.ClockDelta import *
from direct.showbase.DirectObject import DirectObject
import json
import hashlib


class AnimationNetworkSync(DirectObject):
    """
    动画网络同步系统
    支持多人环境中动画状态的同步
    """
    
    def __init__(self, world):
        self.world = world
        self.network_settings = {
            'enable_sync': True,
            'sync_interval': 0.1,  # 同步间隔（秒）
            'interpolation_mode': 'linear',  # 插值模式
            'extrapolation_limit': 0.5,  # 外推限制（秒）
            'compression_enabled': True,
            'delta_compression': True
        }
        
        # 网络状态
        self.is_server = False
        self.is_client = False
        self.connected = False
        self.network_actor_states = {}  # {actor_id: state_data}
        self.local_actor_states = {}    # {actor_id: state_data}
        self.actor_sync_callbacks = {}  # {actor_id: callback_func}
        
        # 同步定时器
        self.sync_task = None
        self.last_sync_time = 0
        
    def enable_server_mode(self):
        """
        启用服务器模式
        """
        self.is_server = True
        self.is_client = False
        self.connected = True
        print("动画网络同步系统 - 服务器模式已启用")
        
    def enable_client_mode(self):
        """
        启用客户端模式
        """
        self.is_server = False
        self.is_client = True
        self.connected = True
        print("动画网络同步系统 - 客户端模式已启用")
        
    def disable_network_sync(self):
        """
        禁用网络同步
        """
        self.is_server = False
        self.is_client = False
        self.connected = False
        print("动画网络同步系统已禁用")
        
    def register_actor_for_sync(self, actor_id, actor, sync_callback=None):
        """
        注册Actor以进行网络同步
        :param actor_id: Actor ID
        :param actor: Actor对象
        :param sync_callback: 同步回调函数
        """
        self.local_actor_states[actor_id] = {
            'actor': actor,
            'last_state': self._capture_actor_state(actor),
            'last_update': globalClock.getRealTime(),
            'sync_callback': sync_callback
        }
        
        if sync_callback:
            self.actor_sync_callbacks[actor_id] = sync_callback
            
        print(f"Actor {actor_id} 已注册网络同步")
        
    def unregister_actor_from_sync(self, actor_id):
        """
        取消Actor的网络同步注册
        :param actor_id: Actor ID
        """
        if actor_id in self.local_actor_states:
            del self.local_actor_states[actor_id]
        if actor_id in self.actor_sync_callbacks:
            del self.actor_sync_callbacks[actor_id]
        if actor_id in self.network_actor_states:
            del self.network_actor_states[actor_id]
            
        print(f"Actor {actor_id} 已取消网络同步注册")
        
    def _capture_actor_state(self, actor):
        """
        捕获Actor当前状态
        :param actor: Actor对象
        :return: 状态数据
        """
        state = {
            'position': actor.getPos().toTuple(),
            'rotation': actor.getHpr().toTuple(),
            'scale': actor.getScale().toTuple(),
            'active_animations': {},
            'timestamp': globalClock.getRealTime()
        }
        
        # 捕获活动动画状态
        for anim_name in actor.getAnimNames():
            control = actor.getAnimControl(anim_name)
            if control and control.isPlaying():
                state['active_animations'][anim_name] = {
                    'frame': actor.getCurrentFrame(anim_name),
                    'play_rate': actor.getPlayRate(anim_name),
                    'is_looping': control.getLoop()
                }
                
        return state
        
    def _apply_actor_state(self, actor, state_data):
        """
        应用Actor状态
        :param actor: Actor对象
        :param state_data: 状态数据
        """
        # 应用变换
        if 'position' in state_data:
            actor.setPos(*state_data['position'])
        if 'rotation' in state_data:
            actor.setHpr(*state_data['rotation'])
        if 'scale' in state_data:
            actor.setScale(*state_data['scale'])
            
        # 应用动画状态
        if 'active_animations' in state_data:
            for anim_name, anim_state in state_data['active_animations'].items():
                if anim_name in actor.getAnimNames():
                    # 停止当前动画
                    actor.stop(anim_name)
                    
                    # 设置到指定帧
                    if 'frame' in anim_state:
                        actor.pose(anim_name, anim_state['frame'])
                        
                    # 设置播放速度
                    if 'play_rate' in anim_state:
                        actor.setPlayRate(anim_state['play_rate'], anim_name)
                        
        # 调用自定义同步回调
        actor_id = actor.getName()  # 简化获取ID的方法
        if actor_id in self.actor_sync_callbacks:
            self.actor_sync_callbacks[actor_id](actor, state_data)
            
    def send_actor_state(self, actor_id):
        """
        发送Actor状态（服务器模式）
        :param actor_id: Actor ID
        """
        if not self.is_server or not self.connected:
            return
            
        if actor_id not in self.local_actor_states:
            return
            
        actor_state = self.local_actor_states[actor_id]
        actor = actor_state['actor']
        current_state = self._capture_actor_state(actor)
        
        # 检查状态是否发生变化
        if self._has_state_changed(actor_state['last_state'], current_state):
            # 发送状态更新
            self._broadcast_actor_state(actor_id, current_state)
            
            # 更新最后状态
            actor_state['last_state'] = current_state
            actor_state['last_update'] = globalClock.getRealTime()
            
    def _has_state_changed(self, old_state, new_state, threshold=0.001):
        """
        检查状态是否发生变化
        :param old_state: 旧状态
        :param new_state: 新状态
        :param threshold: 变化阈值
        :return: 是否发生变化
        """
        # 检查位置变化
        if 'position' in old_state and 'position' in new_state:
            old_pos = Vec3(*old_state['position'])
            new_pos = Vec3(*new_state['position'])
            if (old_pos - new_pos).length() > threshold:
                return True
                
        # 检查旋转变化
        if 'rotation' in old_state and 'rotation' in new_state:
            old_hpr = Vec3(*old_state['rotation'])
            new_hpr = Vec3(*new_state['rotation'])
            if (old_hpr - new_hpr).length() > threshold:
                return True
                
        # 检查动画状态变化
        if 'active_animations' in old_state and 'active_animations' in new_state:
            if old_state['active_animations'] != new_state['active_animations']:
                return True
                
        return False
        
    def _broadcast_actor_state(self, actor_id, state_data):
        """
        广播Actor状态
        :param actor_id: Actor ID
        :param state_data: 状态数据
        """
        # 在实际实现中，这里会通过网络发送数据
        # 为简化，我们直接更新网络状态
        self.network_actor_states[actor_id] = state_data
        print(f"广播Actor {actor_id} 状态更新")
        
    def receive_actor_state(self, actor_id, state_data):
        """
        接收Actor状态（客户端模式）
        :param actor_id: Actor ID
        :param state_data: 状态数据
        """
        if not self.is_client or not self.connected:
            return
            
        # 存储接收到的状态
        self.network_actor_states[actor_id] = {
            'state': state_data,
            'receive_time': globalClock.getRealTime(),
            'interpolated': False
        }
        
        print(f"接收Actor {actor_id} 状态更新")
        
    def update_network_sync(self, task):
        """
        更新网络同步
        """
        current_time = globalClock.getRealTime()
        
        # 检查同步间隔
        if current_time - self.last_sync_time < self.network_settings['sync_interval']:
            return task.cont
            
        self.last_sync_time = current_time
        
        if self.is_server:
            # 服务器：发送本地Actor状态
            for actor_id in list(self.local_actor_states.keys()):
                self.send_actor_state(actor_id)
                
        elif self.is_client:
            # 客户端：应用接收到的状态
            self._apply_network_states()
            
        return task.cont
        
    def _apply_network_states(self):
        """
        应用网络状态
        """
        current_time = globalClock.getRealTime()
        
        for actor_id, state_info in self.network_actor_states.items():
            state_data = state_info['state']
            receive_time = state_info['receive_time']
            
            # 查找对应的Actor
            actor_np = self.world.render.find(f"**/{actor_id}")
            if actor_np and actor_np.node():
                actor = actor_np.node()
                if isinstance(actor, Actor):
                    # 时间补偿插值
                    if self.network_settings['interpolation_mode'] == 'linear':
                        # 简单线性插值
                        self._apply_actor_state(actor, state_data)
                    else:
                        # 直接应用状态
                        self._apply_actor_state(actor, state_data)
                        
    def start_sync_task(self):
        """
        启动同步任务
        """
        if self.sync_task is None:
            self.sync_task = self.world.taskMgr.add(
                self.update_network_sync, 
                "animationNetworkSyncTask",
                sort=40  # 确保在网络更新之后执行
            )
            print("动画网络同步任务已启动")
            
    def stop_sync_task(self):
        """
        停止同步任务
        """
        if self.sync_task:
            self.world.taskMgr.remove(self.sync_task)
            self.sync_task = None
            print("动画网络同步任务已停止")
            
    def get_network_stats(self):
        """
        获取网络同步统计信息
        :return: 统计信息
        """
        return {
            'is_server': self.is_server,
            'is_client': self.is_client,
            'connected': self.connected,
            'local_actors': len(self.local_actor_states),
            'network_actors': len(self.network_actor_states),
            'sync_enabled': self.network_settings['enable_sync'],
            'sync_interval': self.network_settings['sync_interval']
        }


class DistributedAnimationManager:
    """
    分布式动画管理器
    管理网络环境中的动画同步
    """
    
    def __init__(self, world):
        self.world = world
        self.network_sync = AnimationNetworkSync(world)
        self.distributed_actors = {}  # {actor_id: distributed_data}
        self.master_slave_relations = {}  # {slave_actor_id: master_actor_id}
        
    def enable_distributed_mode(self, mode='server'):
        """
        启用分布式模式
        :param mode: 模式 ('server' 或 'client')
        """
        if mode == 'server':
            self.network_sync.enable_server_mode()
        else:
            self.network_sync.enable_client_mode()
            
        self.network_sync.start_sync_task()
        print(f"分布式动画管理器已启用 ({mode} 模式)")
        
    def disable_distributed_mode(self):
        """
        禁用分布式模式
        """
        self.network_sync.stop_sync_task()
        self.network_sync.disable_network_sync()
        print("分布式动画管理器已禁用")
        
    def create_distributed_actor(self, actor_id, model_path, anim_dict=None):
        """
        创建分布式Actor
        :param actor_id: Actor ID
        :param model_path: 模型路径
        :param anim_dict: 动画字典
        :return: Actor对象
        """
        from direct.actor.Actor import Actor
        
        # 创建Actor
        if anim_dict:
            actor = Actor(model_path, anim_dict)
        else:
            actor = Actor(model_path)
            
        # 添加到场景
        actor.reparentTo(self.world.render)
        actor.setName(actor_id)
        
        # 注册网络同步
        self.network_sync.register_actor_for_sync(actor_id, actor)
        
        # 存储分布式数据
        self.distributed_actors[actor_id] = {
            'actor': actor,
            'model_path': model_path,
            'anim_dict': anim_dict,
            'is_distributed': True
        }
        
        print(f"分布式Actor已创建: {actor_id}")
        return actor
        
    def set_master_slave_relation(self, master_id, slave_id):
        """
        设置主从关系
        :param master_id: 主Actor ID
        :param slave_id: 从Actor ID
        """
        if master_id in self.distributed_actors and slave_id in self.distributed_actors:
            self.master_slave_relations[slave_id] = master_id
            print(f"设置主从关系: {master_id} -> {slave_id}")
            
    def sync_actor_animation(self, actor_id, anim_name, play=True, loop=False, play_rate=1.0):
        """
        同步Actor动画
        :param actor_id: Actor ID
        :param anim_name: 动画名称
        :param play: 是否播放
        :param loop: 是否循环
        :param play_rate: 播放速度
        """
        if actor_id not in self.distributed_actors:
            return
            
        actor_data = self.distributed_actors[actor_id]
        actor = actor_data['actor']
        
        if play:
            actor.play(anim_name)
            if loop:
                actor.loop(anim_name, restart=False)
            actor.setPlayRate(play_rate, anim_name)
        else:
            actor.stop(anim_name)
            
        print(f"同步Actor {actor_id} 动画: {anim_name}")
        
    def get_distributed_stats(self):
        """
        获取分布式统计信息
        :return: 统计信息
        """
        network_stats = self.network_sync.get_network_stats()
        return {
            'network_stats': network_stats,
            'distributed_actors': len(self.distributed_actors),
            'master_slave_relations': len(self.master_slave_relations)
        }


class AnimationStateSerializer:
    """
    动画状态序列化器
    支持动画状态的序列化和反序列化
    """
    
    def __init__(self):
        self.serialization_settings = {
            'compress_data': True,
            'include_bone_transforms': True,
            'include_animation_state': True,
            'include_custom_properties': True
        }
        
    def serialize_actor_state(self, actor, include_animations=True):
        """
        序列化Actor状态
        :param actor: Actor对象
        :param include_animations: 是否包含动画状态
        :return: 序列化数据
        """
        state_data = {
            'name': actor.getName() if hasattr(actor, 'getName') else 'Unknown',
            'position': actor.getPos().toTuple(),
            'rotation': actor.getHpr().toTuple(),
            'scale': actor.getScale().toTuple(),
            'timestamp': globalClock.getRealTime()
        }
        
        if include_animations:
            state_data['animations'] = self._serialize_animation_state(actor)
            
        if self.serialization_settings['include_bone_transforms']:
            state_data['bone_transforms'] = self._serialize_bone_transforms(actor)
            
        # 计算数据校验和
        state_data['checksum'] = self._calculate_checksum(state_data)
        
        return state_data
        
    def _serialize_animation_state(self, actor):
        """
        序列化动画状态
        :param actor: Actor对象
        :return: 动画状态数据
        """
        anim_state = {
            'current_animations': [],
            'animation_rates': {},
            'animation_frames': {}
        }
        
        for anim_name in actor.getAnimNames():
            control = actor.getAnimControl(anim_name)
            if control and control.isPlaying():
                anim_state['current_animations'].append(anim_name)
                anim_state['animation_rates'][anim_name] = actor.getPlayRate(anim_name)
                anim_state['animation_frames'][anim_name] = actor.getCurrentFrame(anim_name)
                
        return anim_state
        
    def _serialize_bone_transforms(self, actor):
        """
        序列化骨骼变换
        :param actor: Actor对象
        :return: 骨骼变换数据
        """
        bone_transforms = {}
        
        # 获取骨骼信息
        bundle_dict = actor.getPartBundleDict()
        for bundle_name, bundle in bundle_dict.items():
            bone_transforms[bundle_name] = self._extract_bundle_transforms(bundle)
            
        return bone_transforms
        
    def _extract_bundle_transforms(self, bundle):
        """
        提取绑定变换
        :param bundle: PartBundle对象
        :return: 变换数据
        """
        transforms = {}
        
        # 遍历子节点
        for i in range(bundle.getNumChildren()):
            child = bundle.getChild(i)
            if hasattr(child, 'getName'):
                bone_name = child.getName()
                # 注意：这里简化处理，实际项目中需要更复杂的骨骼数据提取
                transforms[bone_name] = {
                    'transform': 'dummy_transform_data'
                }
                
        return transforms
        
    def _calculate_checksum(self, data):
        """
        计算数据校验和
        :param data: 数据
        :return: 校验和
        """
        # 简化实现，实际项目中应使用更安全的哈希算法
        data_str = json.dumps(data, sort_keys=True)
        return hashlib.md5(data_str.encode()).hexdigest()
        
    def deserialize_actor_state(self, actor, state_data):
        """
        反序列化Actor状态
        :param actor: Actor对象
        :param state_data: 状态数据
        """
        # 验证校验和
        if 'checksum' in state_data:
            expected_checksum = state_data['checksum']
            data_to_check = state_data.copy()
            del data_to_check['checksum']
            actual_checksum = self._calculate_checksum(data_to_check)
            
            if expected_checksum != actual_checksum:
                print("警告: 数据校验和不匹配")
                
        # 应用变换
        if 'position' in state_data:
            actor.setPos(*state_data['position'])
        if 'rotation' in state_data:
            actor.setHpr(*state_data['rotation'])
        if 'scale' in state_data:
            actor.setScale(*state_data['scale'])
            
        # 应用动画状态
        if 'animations' in state_data:
            self._deserialize_animation_state(actor, state_data['animations'])
            
    def _deserialize_animation_state(self, actor, anim_state):
        """
        反序列化动画状态
        :param actor: Actor对象
        :param anim_state: 动画状态数据
        """
        # 停止所有当前动画
        actor.stop()
        
        # 播放指定动画
        for anim_name in anim_state.get('current_animations', []):
            if anim_name in actor.getAnimNames():
                frame = anim_state.get('animation_frames', {}).get(anim_name, 0)
                rate = anim_state.get('animation_rates', {}).get(anim_name, 1.0)
                
                actor.pose(anim_name, frame)
                actor.setPlayRate(rate, anim_name)
                
    def save_state_to_file(self, actor, file_path, include_animations=True):
        """
        保存状态到文件
        :param actor: Actor对象
        :param file_path: 文件路径
        :param include_animations: 是否包含动画状态
        """
        state_data = self.serialize_actor_state(actor, include_animations)
        
        try:
            with open(file_path, 'w') as f:
                json.dump(state_data, f, indent=2)
            print(f"Actor状态已保存到: {file_path}")
        except Exception as e:
            print(f"保存状态失败: {e}")
            
    def load_state_from_file(self, actor, file_path):
        """
        从文件加载状态
        :param actor: Actor对象
        :param file_path: 文件路径
        """
        try:
            with open(file_path, 'r') as f:
                state_data = json.load(f)
            self.deserialize_actor_state(actor, state_data)
            print(f"Actor状态已从 {file_path} 加载")
        except Exception as e:
            print(f"加载状态失败: {e}")


# 使用示例
def example_network_sync_usage(world):
    """
    网络同步使用示例
    """
    print("=== 动画网络同步使用示例 ===")
    
    # 创建网络同步系统
    network_sync = AnimationNetworkSync(world)
    
    # 模拟服务器模式
    network_sync.enable_server_mode()
    
    # 获取网络统计
    stats = network_sync.get_network_stats()
    print(f"网络统计: {stats}")
    
    print("网络同步示例完成")


def example_distributed_usage(world):
    """
    分布式动画使用示例
    """
    print("=== 分布式动画使用示例 ===")
    
    # 创建分布式管理器
    dist_manager = DistributedAnimationManager(world)
    
    # 启用服务器模式
    dist_manager.enable_distributed_mode('server')
    
    # 获取分布式统计
    stats = dist_manager.get_distributed_stats()
    print(f"分布式统计: {stats}")
    
    print("分布式动画示例完成")


def example_serialization_usage(actor):
    """
    状态序列化使用示例
    """
    print("=== 动画状态序列化使用示例 ===")
    
    # 创建序列化器
    serializer = AnimationStateSerializer()
    
    # 序列化Actor状态
    state_data = serializer.serialize_actor_state(actor)
    print(f"序列化状态大小: {len(json.dumps(state_data))} 字符")
    
    # 保存到文件
    serializer.save_state_to_file(actor, "actor_state.json")
    
    print("状态序列化示例完成")


if __name__ == "__main__":
    print("动画网络同步模块加载完成")