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

import json
import hashlib
from typing import Dict, List, Optional, Any, Callable
from dataclasses import dataclass, field
from enum import Enum

from panda3d.core import *
from direct.distributed.ClockDelta import globalClockDelta
from direct.showbase.DirectObject import DirectObject

# 定义常量
NETWORK_SETTINGS = {
    'enable_sync': True,
    'sync_interval': 0.1,  # 同步间隔（秒）
    'interpolation_mode': 'linear',  # 插值模式
    'extrapolation_limit': 0.5,  # 外推限制（秒）
    'compression_enabled': True,
    'delta_compression': True
}

# 枚举定义
class NetworkMode(Enum):
    """网络模式枚举"""
    DISABLED = 0
    SERVER = 1
    CLIENT = 2
    PEER_TO_PEER = 3

class SyncMode(Enum):
    """同步模式枚举"""
    STATE_SYNC = 0  # 状态同步
    INPUT_SYNC = 1  # 输入同步
    INTERPOLATION = 2  # 插值同步

@dataclass
class NetworkActorState:
    """网络Actor状态数据类"""
    actor_id: str
    position: Tuple[float, float, float]
    rotation: Tuple[float, float, float]
    scale: Tuple[float, float, float]
    active_animations: Dict[str, Dict[str, Any]]
    timestamp: float
    network_id: str = ""
    checksum: str = ""

@dataclass
class NetworkSyncConfig:
    """网络同步配置数据类"""
    mode: NetworkMode = NetworkMode.DISABLED
    sync_mode: SyncMode = SyncMode.STATE_SYNC
    sync_interval: float = 0.1
    interpolation_mode: str = 'linear'
    enable_compression: bool = True
    max_buffer_size: int = 100
    update_rate: int = 20  # 每秒更新次数

class NetworkSyncBuffer:
    """网络同步缓冲区"""
    
    def __init__(self, max_size: int = 100):
        self.max_size = max_size
        self.buffer: List[NetworkActorState] = []
        self.last_processed_time = 0.0
        
    def add_state(self, state: NetworkActorState) -> None:
        """添加状态到缓冲区"""
        self.buffer.append(state)
        # 保持缓冲区大小
        if len(self.buffer) > self.max_size:
            self.buffer.pop(0)
            
    def get_interpolated_state(self, target_time: float) -> Optional[NetworkActorState]:
        """
        获取插值状态
        :param target_time: 目标时间
        :return: 插值状态
        """
        if len(self.buffer) < 2:
            return self.buffer[-1] if self.buffer else None
            
        # 找到时间范围内的两个状态
        prev_state = None
        next_state = None
        
        for state in self.buffer:
            if state.timestamp <= target_time:
                prev_state = state
            else:
                next_state = state
                break
                
        if not prev_state or not next_state:
            return self.buffer[-1] if self.buffer else None
            
        # 计算插值因子
        time_range = next_state.timestamp - prev_state.timestamp
        if time_range <= 0:
            return prev_state
            
        t = (target_time - prev_state.timestamp) / time_range
        
        # 执行线性插值
        interpolated_pos = tuple(
            prev_state.position[i] + t * (next_state.position[i] - prev_state.position[i])
            for i in range(3)
        )
        
        interpolated_rot = tuple(
            prev_state.rotation[i] + t * (next_state.rotation[i] - prev_state.rotation[i])
            for i in range(3)
        )
        
        interpolated_scale = tuple(
            prev_state.scale[i] + t * (next_state.scale[i] - prev_state.scale[i])
            for i in range(3)
        )
        
        # 创建插值状态
        interpolated_state = NetworkActorState(
            actor_id=prev_state.actor_id,
            position=interpolated_pos,
            rotation=interpolated_rot,
            scale=interpolated_scale,
            active_animations=prev_state.active_animations,  # 简化处理
            timestamp=target_time,
            network_id=prev_state.network_id
        )
        
        return interpolated_state
        
    def clear(self) -> None:
        """清空缓冲区"""
        self.buffer.clear()

class AnimationNetworkSync(DirectObject):
    """
    动画网络同步系统
    支持多人环境中动画状态的同步
    """
    
    def __init__(self, world, core_system):
        """
        初始化网络同步系统
        :param world: 世界对象
        :param core_system: 核心动画系统
        """
        super().__init__()
        self.world = world
        self.core_system = core_system
        self.config = NetworkSyncConfig()
        self.network_states: Dict[str, NetworkActorState] = {}
        self.state_buffers: Dict[str, NetworkSyncBuffer] = {}
        self.sync_callbacks: Dict[str, List[Callable]] = {}
        self.is_connected = False
        self.last_sync_time = 0.0
        self.sync_task = None
        self.network_id_counter = 0
        
        print("动画网络同步系统初始化完成")
        
    def set_network_mode(self, mode: NetworkMode) -> None:
        """
        设置网络模式
        :param mode: 网络模式
        """
        self.config.mode = mode
        if mode != NetworkMode.DISABLED:
            self.is_connected = True
            self.start_sync_task()
        else:
            self.is_connected = False
            self.stop_sync_task()
        print(f"网络模式设置为: {mode.name}")
        
    def set_sync_mode(self, mode: SyncMode) -> None:
        """
        设置同步模式
        :param mode: 同步模式
        """
        self.config.sync_mode = mode
        print(f"同步模式设置为: {mode.name}")
        
    def configure_sync(self, sync_interval: float = 0.1, interpolation_mode: str = 'linear',
                      enable_compression: bool = True) -> None:
        """
        配置同步参数
        :param sync_interval: 同步间隔
        :param interpolation_mode: 插值模式
        :param enable_compression: 是否启用压缩
        """
        self.config.sync_interval = sync_interval
        self.config.interpolation_mode = interpolation_mode
        self.config.enable_compression = enable_compression
        print(f"同步配置更新: 间隔={sync_interval}s, 插值={interpolation_mode}, 压缩={enable_compression}")
        
    def register_actor_for_sync(self, actor_id: str, network_id: Optional[str] = None) -> str:
        """
        注册Actor以进行网络同步
        :param actor_id: Actor ID
        :param network_id: 网络ID，如果为None则自动生成
        :return: 网络ID
        """
        if network_id is None:
            network_id = f"net_{self.network_id_counter}"
            self.network_id_counter += 1
            
        # 初始化状态缓冲区
        self.state_buffers[actor_id] = NetworkSyncBuffer(self.config.max_buffer_size)
        
        print(f"Actor {actor_id} 已注册网络同步 (网络ID: {network_id})")
        return network_id
        
    def unregister_actor_from_sync(self, actor_id: str) -> None:
        """
        取消Actor的网络同步注册
        :param actor_id: Actor ID
        """
        if actor_id in self.state_buffers:
            self.state_buffers[actor_id].clear()
            del self.state_buffers[actor_id]
            
        if actor_id in self.network_states:
            del self.network_states[actor_id]
            
        print(f"Actor {actor_id} 已取消网络同步注册")
        
    def _capture_actor_state(self, actor_id: str) -> Optional[NetworkActorState]:
        """
        捕获Actor当前状态
        :param actor_id: Actor ID
        :return: 状态数据
        """
        actor_info = self.core_system.actors.get(actor_id)
        if not actor_info:
            return None
            
        actor = actor_info.actor
        
        # 获取基本变换
        position = actor.getPos().toTuple()
        rotation = actor.getHpr().toTuple()
        scale = actor.getScale().toTuple()
        
        # 获取活动动画状态
        active_animations = {}
        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
                
                active_animations[anim_name] = {
                    'frame': anim_info.current_frame,
                    'play_rate': anim_info.play_rate,
                    'loop': anim_info.loop,
                    'state': anim_info.state.name,
                    'blend_weight': anim_info.blend_weight
                }
                
        # 创建状态对象
        state = NetworkActorState(
            actor_id=actor_id,
            position=position,
            rotation=rotation,
            scale=scale,
            active_animations=active_animations,
            timestamp=globalClock.getRealTime()
        )
        
        # 计算校验和
        state.checksum = self._calculate_checksum(state)
        
        return state
        
    def _calculate_checksum(self, state: NetworkActorState) -> str:
        """
        计算状态校验和
        :param state: 状态数据
        :return: 校验和
        """
        # 创建用于校验的数据
        checksum_data = {
            'position': state.position,
            'rotation': state.rotation,
            'scale': state.scale,
            'active_animations': state.active_animations,
            'timestamp': state.timestamp
        }
        
        # 生成JSON字符串并计算MD5
        data_str = json.dumps(checksum_data, sort_keys=True)
        return hashlib.md5(data_str.encode()).hexdigest()
        
    def _validate_checksum(self, state: NetworkActorState) -> bool:
        """
        验证状态校验和
        :param state: 状态数据
        :return: 是否有效
        """
        expected_checksum = state.checksum
        state.checksum = ""  # 临时清空校验和
        actual_checksum = self._calculate_checksum(state)
        state.checksum = expected_checksum  # 恢复校验和
        return expected_checksum == actual_checksum
        
    def send_actor_state(self, actor_id: str) -> None:
        """
        发送Actor状态（服务器模式）
        :param actor_id: Actor ID
        """
        if not self.is_connected or self.config.mode != NetworkMode.SERVER:
            return
            
        # 捕获当前状态
        state = self._capture_actor_state(actor_id)
        if not state:
            return
            
        # 发送状态（在实际实现中，这里会通过网络发送）
        self._broadcast_actor_state(state)
        
    def _broadcast_actor_state(self, state: NetworkActorState) -> None:
        """
        广播Actor状态
        :param state: 状态数据
        """
        # 在实际实现中，这里会通过网络发送数据
        # 为简化，我们直接更新本地网络状态
        self.network_states[state.actor_id] = state
        
        # 添加到缓冲区用于插值
        if state.actor_id in self.state_buffers:
            self.state_buffers[state.actor_id].add_state(state)
            
        print(f"广播Actor {state.actor_id} 状态更新 (时间: {state.timestamp:.3f})")
        
    def receive_actor_state(self, state_data: Dict[str, Any]) -> None:
        """
        接收Actor状态（客户端模式）
        :param state_data: 状态数据
        """
        if not self.is_connected or self.config.mode != NetworkMode.CLIENT:
            return
            
        # 反序列化状态
        state = NetworkActorState(
            actor_id=state_data['actor_id'],
            position=tuple(state_data['position']),
            rotation=tuple(state_data['rotation']),
            scale=tuple(state_data['scale']),
            active_animations=state_data['active_animations'],
            timestamp=state_data['timestamp'],
            network_id=state_data.get('network_id', ''),
            checksum=state_data.get('checksum', '')
        )
        
        # 验证校验和
        if not self._validate_checksum(state):
            print(f"警告: Actor {state.actor_id} 状态校验和不匹配，丢弃数据")
            return
            
        # 存储接收到的状态
        self.network_states[state.actor_id] = state
        
        # 添加到缓冲区用于插值
        if state.actor_id in self.state_buffers:
            self.state_buffers[state.actor_id].add_state(state)
            
        print(f"接收Actor {state.actor_id} 状态更新 (时间: {state.timestamp:.3f})")
        
    def _apply_actor_state(self, actor_id: str, state: NetworkActorState) -> None:
        """
        应用Actor状态
        :param actor_id: Actor ID
        :param state: 状态数据
        """
        actor_info = self.core_system.actors.get(actor_id)
        if not actor_info:
            return
            
        actor = actor_info.actor
        
        # 应用变换
        actor.setPos(*state.position)
        actor.setHpr(*state.rotation)
        actor.setScale(*state.scale)
        
        # 应用动画状态
        for anim_name, anim_state in state.active_animations.items():
            if anim_name in actor.getAnimNames():
                # 设置动画帧
                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)
                    
                # 恢复播放状态
                if anim_state.get('state') in ['PLAYING', 'LOOPING']:
                    if anim_state.get('loop', False):
                        actor.loop(anim_name, restart=False)
                    else:
                        actor.play(anim_name)
                        
        print(f"应用Actor {actor_id} 网络状态 (时间: {state.timestamp:.3f})")
        
    def _apply_interpolated_state(self, actor_id: str, target_time: float) -> None:
        """
        应用插值状态
        :param actor_id: Actor ID
        :param target_time: 目标时间
        """
        if actor_id not in self.state_buffers:
            return
            
        # 获取插值状态
        interpolated_state = self.state_buffers[actor_id].get_interpolated_state(target_time)
        if interpolated_state:
            self._apply_actor_state(actor_id, interpolated_state)
            
    def update_network_sync(self, task) -> int:
        """
        更新网络同步
        :param task: 任务对象
        """
        current_time = globalClock.getRealTime()
        
        # 检查同步间隔
        if current_time - self.last_sync_time < self.config.sync_interval:
            return task.cont
            
        self.last_sync_time = current_time
        
        if self.config.mode == NetworkMode.SERVER:
            # 服务器：发送本地Actor状态
            for actor_id in self.core_system.actors.keys():
                self.send_actor_state(actor_id)
                
        elif self.config.mode == NetworkMode.CLIENT:
            # 客户端：应用接收到的状态
            current_network_time = globalClock.getRealTime()
            
            # 根据同步模式应用状态
            if self.config.sync_mode == SyncMode.INTERPOLATION:
                # 使用插值
                for actor_id in self.network_states.keys():
                    self._apply_interpolated_state(actor_id, current_network_time)
            else:
                # 直接应用最新状态
                for actor_id, state in self.network_states.items():
                    self._apply_actor_state(actor_id, state)
                    
        return task.cont
        
    def start_sync_task(self) -> None:
        """
        启动同步任务
        """
        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) -> None:
        """
        停止同步任务
        """
        if self.sync_task:
            self.world.taskMgr.remove(self.sync_task)
            self.sync_task = None
            print("动画网络同步任务已停止")
            
    def get_network_stats(self) -> Dict[str, Any]:
        """
        获取网络同步统计信息
        :return: 统计信息
        """
        return {
            'mode': self.config.mode.name,
            'sync_mode': self.config.sync_mode.name,
            'connected': self.is_connected,
            'sync_interval': self.config.sync_interval,
            'interpolation_mode': self.config.interpolation_mode,
            'compression_enabled': self.config.enable_compression,
            'network_actors': len(self.network_states),
            'buffered_states': sum(len(buffer.buffer) for buffer in self.state_buffers.values())
        }
        
    def add_sync_callback(self, actor_id: str, callback: Callable) -> None:
        """
        添加同步回调
        :param actor_id: Actor ID
        :param callback: 回调函数
        """
        if actor_id not in self.sync_callbacks:
            self.sync_callbacks[actor_id] = []
        self.sync_callbacks[actor_id].append(callback)
        
    def remove_sync_callback(self, actor_id: str, callback: Callable) -> None:
        """
        移除同步回调
        :param actor_id: Actor ID
        :param callback: 回调函数
        """
        if actor_id in self.sync_callbacks and callback in self.sync_callbacks[actor_id]:
            self.sync_callbacks[actor_id].remove(callback)
            
    def _trigger_sync_callbacks(self, actor_id: str, state: NetworkActorState) -> None:
        """
        触发同步回调
        :param actor_id: Actor ID
        :param state: 状态数据
        """
        if actor_id in self.sync_callbacks:
            for callback in self.sync_callbacks[actor_id]:
                try:
                    callback(actor_id, state)
                except Exception as e:
                    print(f"执行同步回调失败: {e}")

# 使用示例和测试代码
def example_network_sync_usage(world, core_system):
    """
    网络同步使用示例
    """
    print("=== 动画网络同步使用示例 ===")
    
    # 创建网络同步系统
    network_sync = AnimationNetworkSync(world, core_system)
    
    # 设置为服务器模式
    network_sync.set_network_mode(NetworkMode.SERVER)
    network_sync.set_sync_mode(SyncMode.STATE_SYNC)
    network_sync.configure_sync(sync_interval=0.05, interpolation_mode='linear')
    
    # 获取网络统计
    stats = network_sync.get_network_stats()
    print(f"网络统计: {stats}")
    
    print("网络同步示例完成")
    return network_sync

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