"""
时钟同步模块
负责客户端与服务器之间的时间同步
"""

import time
from typing import Dict, Any, List, Optional
import threading

class ClockSync:
    """
    时钟同步器
    负责客户端与服务器之间的时间同步
    """
    
    def __init__(self, plugin):
        """
        初始化时钟同步器
        
        Args:
            plugin: 网络同步插件实例
        """
        self.plugin = plugin
        self.enabled = False
        self.initialized = False
        
        # 时钟同步配置
        self.clock_config = {
            'sync_interval': 5.0,        # 同步间隔（秒）
            'samples_per_sync': 10,      # 每次同步的样本数
            'max_offset_samples': 100,   # 最大偏移样本数
            'enable_interpolation': True, # 启用时间插值
            'interpolation_rate': 60.0,   # 插值更新频率
            'max_drift_correction': 0.1,  # 最大漂移校正（秒/秒）
            'min_sync_quality': 0.8,     # 最小同步质量
            'timeout': 10.0              # 同步超时时间
        }
        
        # 时钟状态
        self.clock_state = {
            'is_synchronized': False,
            'time_offset': 0.0,          # 本地时间与服务器时间的偏移
            'time_drift': 0.0,           # 时间漂移率
            'last_sync_time': 0.0,       # 最后同步时间
            'sync_quality': 0.0,         # 同步质量
            'round_trip_time': 0.0,      # 往返时间
            'sync_samples': []           # 同步样本
        }
        
        # 插值状态
        self.interpolation_state = {
            'interpolated_time': 0.0,
            'target_time': 0.0,
            'interpolation_start': 0.0,
            'interpolation_duration': 0.0
        }
        
        # 时钟统计
        self.clock_stats = {
            'sync_attempts': 0,
            'successful_syncs': 0,
            'failed_syncs': 0,
            'average_rtt': 0.0,
            'min_rtt': float('inf'),
            'max_rtt': 0.0,
            'sync_errors': 0
        }
        
        # 同步请求队列
        self.sync_requests = []
        self.sync_lock = threading.Lock()
        
        # 回调函数
        self.clock_callbacks = {
            'sync_started': [],
            'sync_completed': [],
            'sync_failed': [],
            'time_updated': [],
            'sync_quality_changed': []
        }
        
        # 时间戳记录
        self.last_sync_attempt = 0.0
        self.last_time_update = 0.0
        self.last_interpolation_update = 0.0
        
        print("✓ 时钟同步器已创建")
        
    def initialize(self) -> bool:
        """
        初始化时钟同步器
        
        Returns:
            是否初始化成功
        """
        try:
            self.initialized = True
            print("✓ 时钟同步器初始化完成")
            return True
            
        except Exception as e:
            print(f"✗ 时钟同步器初始化失败: {e}")
            import traceback
            traceback.print_exc()
            return False
            
    def enable(self) -> bool:
        """
        启用时钟同步器
        
        Returns:
            是否启用成功
        """
        try:
            if not self.initialized:
                print("✗ 时钟同步器未初始化")
                return False
                
            self.enabled = True
            print("✓ 时钟同步器已启用")
            return True
            
        except Exception as e:
            print(f"✗ 时钟同步器启用失败: {e}")
            import traceback
            traceback.print_exc()
            return False
            
    def disable(self):
        """禁用时钟同步器"""
        try:
            self.enabled = False
            print("✓ 时钟同步器已禁用")
            
        except Exception as e:
            print(f"✗ 时钟同步器禁用失败: {e}")
            import traceback
            traceback.print_exc()
            
    def finalize(self):
        """清理时钟同步器资源"""
        try:
            self.disable()
            self.sync_requests.clear()
            self.clock_callbacks.clear()
            self.initialized = False
            print("✓ 时钟同步器资源已清理")
            
        except Exception as e:
            print(f"✗ 时钟同步器资源清理失败: {e}")
            import traceback
            traceback.print_exc()
            
    def update(self, dt: float):
        """
        更新时钟同步器状态
        
        Args:
            dt: 时间增量
        """
        try:
            if not self.enabled:
                return
                
            current_time = time.time()
            
            # 定期发起时钟同步
            if current_time - self.last_sync_attempt >= self.clock_config['sync_interval']:
                self._request_time_sync()
                self.last_sync_attempt = current_time
                
            # 更新时间插值
            if self.clock_config['enable_interpolation']:
                self._update_time_interpolation(current_time)
                
            self.last_time_update = current_time
            
        except Exception as e:
            print(f"✗ 时钟同步器更新失败: {e}")
            import traceback
            traceback.print_exc()
            
    def _request_time_sync(self):
        """请求时间同步"""
        try:
            if not self.plugin.network_manager or not self.plugin.protocol_handler:
                return
                
            # 增加同步尝试计数
            self.clock_stats['sync_attempts'] += 1
            
            # 触发同步开始回调
            self._trigger_clock_callback('sync_started', {
                'timestamp': time.time()
            })
            
            # 发送时间同步请求
            sync_data = {
                'client_time': time.time(),
                'request_id': f"sync_{int(time.time() * 1000000)}"
            }
            
            success = self.plugin.protocol_handler.send_message('SYNC_REQUEST', sync_data)
            if success:
                # 记录同步请求
                with self.sync_lock:
                    self.sync_requests.append({
                        'request_id': sync_data['request_id'],
                        'send_time': time.time(),
                        'completed': False
                    })
            else:
                self.clock_stats['failed_syncs'] += 1
                self._trigger_clock_callback('sync_failed', {
                    'reason': 'send_failed',
                    'timestamp': time.time()
                })
                
        except Exception as e:
            print(f"✗ 时间同步请求失败: {e}")
            self.clock_stats['sync_errors'] += 1
            
    def handle_sync_request(self, data: Dict[str, Any], client_id: str = None):
        """
        处理时间同步请求
        
        Args:
            data: 同步请求数据
            client_id: 客户端ID
        """
        try:
            # 构造同步响应
            response_data = {
                'client_time': data.get('client_time', 0),
                'server_time': time.time(),
                'request_id': data.get('request_id', ''),
                'client_id': client_id
            }
            
            # 发送同步响应
            if self.plugin.protocol_handler:
                self.plugin.protocol_handler.send_message('SYNC_RESPONSE', response_data, client_id)
                
        except Exception as e:
            print(f"✗ 时间同步请求处理失败: {e}")
            
    def handle_sync_response(self, data: Dict[str, Any]):
        """
        处理时间同步响应
        
        Args:
            data: 同步响应数据
        """
        try:
            client_send_time = data.get('client_time', 0)
            server_time = data.get('server_time', 0)
            request_id = data.get('request_id', '')
            receive_time = time.time()
            
            # 计算往返时间
            rtt = receive_time - client_send_time
            
            # 计算时间偏移（假设网络延迟对称）
            time_offset = server_time - (client_send_time + rtt / 2)
            
            # 更新统计信息
            self.clock_stats['successful_syncs'] += 1
            self.clock_stats['average_rtt'] = (
                (self.clock_stats['average_rtt'] * (self.clock_stats['successful_syncs'] - 1) + rtt) / 
                self.clock_stats['successful_syncs']
            )
            self.clock_stats['min_rtt'] = min(self.clock_stats['min_rtt'], rtt)
            self.clock_stats['max_rtt'] = max(self.clock_stats['max_rtt'], rtt)
            
            # 添加同步样本
            sample = {
                'offset': time_offset,
                'rtt': rtt,
                'timestamp': receive_time
            }
            
            with self.sync_lock:
                self.clock_state['sync_samples'].append(sample)
                
                # 保持样本数量在限制范围内
                if len(self.clock_state['sync_samples']) > self.clock_config['max_offset_samples']:
                    self.clock_state['sync_samples'].pop(0)
                    
            # 更新时钟状态
            self._update_clock_state()
            
            # 标记请求完成
            with self.sync_lock:
                for request in self.sync_requests:
                    if request['request_id'] == request_id:
                        request['completed'] = True
                        break
                        
            # 触发同步完成回调
            self._trigger_clock_callback('sync_completed', {
                'offset': time_offset,
                'rtt': rtt,
                'quality': self.clock_state['sync_quality'],
                'timestamp': receive_time
            })
            
            self.clock_state['last_sync_time'] = receive_time
            
        except Exception as e:
            print(f"✗ 时间同步响应处理失败: {e}")
            self.clock_stats['sync_errors'] += 1
            self._trigger_clock_callback('sync_failed', {
                'reason': 'process_failed',
                'error': str(e),
                'timestamp': time.time()
            })
            
    def _update_clock_state(self):
        """更新时钟状态"""
        try:
            with self.sync_lock:
                if not self.clock_state['sync_samples']:
                    return
                    
                # 计算平均时间偏移
                offsets = [sample['offset'] for sample in self.clock_state['sync_samples']]
                avg_offset = sum(offsets) / len(offsets)
                
                # 计算时间偏移的标准差（用于质量评估）
                if len(offsets) > 1:
                    variance = sum((offset - avg_offset) ** 2 for offset in offsets) / (len(offsets) - 1)
                    std_dev = variance ** 0.5
                else:
                    std_dev = 0.0
                    
                # 计算同步质量（基于标准差和RTT）
                if std_dev < 0.001:  # 小于1毫秒的标准差
                    quality = 1.0
                else:
                    # 质量与标准差成反比
                    quality = max(0.0, 1.0 - (std_dev * 1000))  # 转换为毫秒
                    
                # 计算平均RTT
                rtts = [sample['rtt'] for sample in self.clock_state['sync_samples']]
                avg_rtt = sum(rtts) / len(rtts)
                
                # 更新时钟状态
                self.clock_state['time_offset'] = avg_offset
                self.clock_state['round_trip_time'] = avg_rtt
                self.clock_state['sync_quality'] = quality
                self.clock_state['is_synchronized'] = quality >= self.clock_config['min_sync_quality']
                
                # 触发同步质量变化回调
                self._trigger_clock_callback('sync_quality_changed', {
                    'quality': quality,
                    'offset': avg_offset,
                    'rtt': avg_rtt
                })
                
        except Exception as e:
            print(f"✗ 时钟状态更新失败: {e}")
            
    def _update_time_interpolation(self, current_time: float):
        """
        更新时间插值
        
        Args:
            current_time: 当前时间
        """
        try:
            if not self.clock_config['enable_interpolation']:
                return
                
            # 计算插值时间
            server_time = self.get_server_time()
            
            if self.interpolation_state['interpolated_time'] == 0.0:
                # 初始化插值
                self.interpolation_state['interpolated_time'] = server_time
                self.interpolation_state['target_time'] = server_time
            else:
                # 更新目标时间
                self.interpolation_state['target_time'] = server_time
                
                # 执行插值
                if self.interpolation_state['interpolated_time'] != self.interpolation_state['target_time']:
                    interpolation_speed = self.clock_config['interpolation_rate']
                    time_diff = self.interpolation_state['target_time'] - self.interpolation_state['interpolated_time']
                    max_step = interpolation_speed * (1.0 / 60.0)  # 假设60FPS
                    
                    if abs(time_diff) > max_step:
                        # 逐步接近目标时间
                        step = max_step if time_diff > 0 else -max_step
                        self.interpolation_state['interpolated_time'] += step
                    else:
                        # 直接设置为目标时间
                        self.interpolation_state['interpolated_time'] = self.interpolation_state['target_time']
                        
            # 触发时间更新回调
            self._trigger_clock_callback('time_updated', {
                'server_time': server_time,
                'interpolated_time': self.interpolation_state['interpolated_time'],
                'local_time': current_time
            })
            
            self.last_interpolation_update = current_time
            
        except Exception as e:
            print(f"✗ 时间插值更新失败: {e}")
            
    def get_server_time(self) -> float:
        """
        获取服务器时间
        
        Returns:
            服务器时间戳
        """
        try:
            local_time = time.time()
            return local_time + self.clock_state['time_offset']
        except Exception as e:
            print(f"✗ 服务器时间获取失败: {e}")
            return time.time()
            
    def get_interpolated_time(self) -> float:
        """
        获取插值时间
        
        Returns:
            插值时间戳
        """
        try:
            if self.clock_config['enable_interpolation'] and self.interpolation_state['interpolated_time'] != 0.0:
                return self.interpolation_state['interpolated_time']
            else:
                return self.get_server_time()
        except Exception as e:
            print(f"✗ 插值时间获取失败: {e}")
            return time.time()
            
    def get_time_offset(self) -> float:
        """
        获取时间偏移
        
        Returns:
            时间偏移值
        """
        return self.clock_state['time_offset']
        
    def get_sync_quality(self) -> float:
        """
        获取同步质量
        
        Returns:
            同步质量值 (0.0-1.0)
        """
        return self.clock_state['sync_quality']
        
    def is_synchronized(self) -> bool:
        """
        检查是否已同步
        
        Returns:
            是否已同步
        """
        return self.clock_state['is_synchronized']
        
    def get_round_trip_time(self) -> float:
        """
        获取往返时间
        
        Returns:
            往返时间（秒）
        """
        return self.clock_state['round_trip_time']
        
    def get_clock_stats(self) -> Dict[str, Any]:
        """
        获取时钟统计信息
        
        Returns:
            时钟统计字典
        """
        return self.clock_stats.copy()
        
    def reset_clock_stats(self):
        """重置时钟统计信息"""
        try:
            self.clock_stats = {
                'sync_attempts': 0,
                'successful_syncs': 0,
                'failed_syncs': 0,
                'average_rtt': 0.0,
                'min_rtt': float('inf'),
                'max_rtt': 0.0,
                'sync_errors': 0
            }
            print("✓ 时钟统计信息已重置")
        except Exception as e:
            print(f"✗ 时钟统计信息重置失败: {e}")
            
    def force_sync(self) -> bool:
        """
        强制进行时钟同步
        
        Returns:
            是否成功发起同步
        """
        try:
            self._request_time_sync()
            self.last_sync_attempt = time.time()
            print("✓ 强制时钟同步已发起")
            return True
        except Exception as e:
            print(f"✗ 强制时钟同步失败: {e}")
            return False
            
    def reset_sync(self):
        """重置时钟同步状态"""
        try:
            with self.sync_lock:
                self.clock_state = {
                    'is_synchronized': False,
                    'time_offset': 0.0,
                    'time_drift': 0.0,
                    'last_sync_time': 0.0,
                    'sync_quality': 0.0,
                    'round_trip_time': 0.0,
                    'sync_samples': []
                }
                
                self.interpolation_state = {
                    'interpolated_time': 0.0,
                    'target_time': 0.0,
                    'interpolation_start': 0.0,
                    'interpolation_duration': 0.0
                }
                
                self.sync_requests.clear()
                
            print("✓ 时钟同步状态已重置")
        except Exception as e:
            print(f"✗ 时钟同步状态重置失败: {e}")
            
    def set_clock_config(self, config: Dict[str, Any]) -> bool:
        """
        设置时钟配置
        
        Args:
            config: 时钟配置字典
            
        Returns:
            是否设置成功
        """
        try:
            self.clock_config.update(config)
            print(f"✓ 时钟配置已更新: {self.clock_config}")
            return True
        except Exception as e:
            print(f"✗ 时钟配置设置失败: {e}")
            return False
            
    def get_clock_config(self) -> Dict[str, Any]:
        """
        获取时钟配置
        
        Returns:
            时钟配置字典
        """
        return self.clock_config.copy()
        
    def _trigger_clock_callback(self, callback_type: str, data: Dict[str, Any]):
        """
        触发时钟回调
        
        Args:
            callback_type: 回调类型
            data: 回调数据
        """
        try:
            if callback_type in self.clock_callbacks:
                for callback in self.clock_callbacks[callback_type]:
                    try:
                        callback(data)
                    except Exception as e:
                        print(f"✗ 时钟回调执行失败: {e}")
        except Exception as e:
            print(f"✗ 时钟回调触发失败: {e}")
            
    def register_clock_callback(self, callback_type: str, callback: callable):
        """
        注册时钟回调
        
        Args:
            callback_type: 回调类型
            callback: 回调函数
        """
        try:
            if callback_type in self.clock_callbacks:
                self.clock_callbacks[callback_type].append(callback)
                print(f"✓ 时钟回调已注册: {callback_type}")
            else:
                print(f"✗ 无效的回调类型: {callback_type}")
        except Exception as e:
            print(f"✗ 时钟回调注册失败: {e}")
            
    def unregister_clock_callback(self, callback_type: str, callback: callable):
        """
        注销时钟回调
        
        Args:
            callback_type: 回调类型
            callback: 回调函数
        """
        try:
            if callback_type in self.clock_callbacks:
                if callback in self.clock_callbacks[callback_type]:
                    self.clock_callbacks[callback_type].remove(callback)
                    print(f"✓ 时钟回调已注销: {callback_type}")
        except Exception as e:
            print(f"✗ 时钟回调注销失败: {e}")