"""
设备校准模块
负责处理各种输入设备的校准和配置
"""

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

class DeviceCalibrator:
    """
    设备校准器
    负责处理各种输入设备的校准和配置
    """
    
    def __init__(self, plugin):
        """
        初始化设备校准器
        
        Args:
            plugin: 多平台输入支持插件实例
        """
        self.plugin = plugin
        self.enabled = False
        self.initialized = False
        
        # 校准配置
        self.calibration_config = {
            'auto_calibration': True,
            'calibration_interval': 300.0,  # 5分钟
            'sensitivity_threshold': 0.01,
            'deadzone_calibration': True,
            'range_calibration': True,
            'center_calibration': True,
            'drift_correction': True
        }
        
        # 设备校准数据
        self.calibration_data = {}
        
        # 校准状态
        self.calibration_state = {
            'is_calibrating': False,
            'current_device': None,
            'calibration_step': 0,
            'total_steps': 0,
            'progress': 0.0
        }
        
        # 校准历史
        self.calibration_history = {}
        
        # 回调函数
        self.calibration_callbacks = {
            'calibration_started': [],
            'calibration_progress': [],
            'calibration_completed': [],
            'calibration_failed': []
        }
        
        # 统计信息
        self.calibration_stats = {
            'calibrations_performed': 0,
            'calibrations_successful': 0,
            'calibrations_failed': 0,
            'auto_calibrations': 0,
            'manual_calibrations': 0
        }
        
        # 线程管理
        self.calibration_thread = None
        self.running = False
        
        # 时间戳记录
        self.last_auto_calibration = {}
        self.calibration_start_time = 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
            self.running = 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
            self.running = False
            
            # 停止正在进行的校准
            if self.calibration_state['is_calibrating']:
                self.cancel_calibration()
                
            print("✓ 设备校准器已禁用")
            
        except Exception as e:
            print(f"✗ 设备校准器禁用失败: {e}")
            import traceback
            traceback.print_exc()
            
    def finalize(self):
        """清理设备校准器资源"""
        try:
            self.disable()
            self.calibration_data.clear()
            self.calibration_history.clear()
            self.calibration_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
                
            # 检查自动校准
            if self.calibration_config['auto_calibration']:
                self._check_auto_calibration()
                
        except Exception as e:
            print(f"✗ 设备校准器更新失败: {e}")
            import traceback
            traceback.print_exc()
            
    def _check_auto_calibration(self):
        """检查自动校准"""
        try:
            current_time = time.time()
            
            # 检查是否需要自动校准
            if self.plugin.device_manager:
                devices = self.plugin.device_manager.get_connected_devices()
                for device_id, device_info in devices.items():
                    last_calibration = self.last_auto_calibration.get(device_id, 0.0)
                    if current_time - last_calibration >= self.calibration_config['calibration_interval']:
                        # 执行自动校准
                        self.start_auto_calibration(device_id)
                        self.calibration_stats['auto_calibrations'] += 1
                        
        except Exception as e:
            print(f"✗ 自动校准检查失败: {e}")
            
    def start_calibration(self, device_id: int, calibration_type: str = "full") -> bool:
        """
        开始设备校准
        
        Args:
            device_id: 设备ID
            calibration_type: 校准类型 ("full", "deadzone", "range", "center")
            
        Returns:
            是否开始成功
        """
        try:
            if not self.enabled:
                print("✗ 设备校准器未启用")
                return False
                
            if self.calibration_state['is_calibrating']:
                print("✗ 校准已在进行中")
                return False
                
            # 检查设备是否存在
            if not self.plugin.device_manager or not self.plugin.device_manager.get_device(device_id):
                print(f"✗ 设备不存在: ID {device_id}")
                return False
                
            # 设置校准状态
            self.calibration_state['is_calibrating'] = True
            self.calibration_state['current_device'] = device_id
            self.calibration_state['calibration_step'] = 0
            
            # 根据校准类型设置步骤数
            if calibration_type == "full":
                self.calibration_state['total_steps'] = 4
            elif calibration_type in ["deadzone", "range", "center"]:
                self.calibration_state['total_steps'] = 1
            else:
                self.calibration_state['total_steps'] = 1
                
            self.calibration_start_time = time.time()
            
            # 初始化校准数据
            if device_id not in self.calibration_data:
                self.calibration_data[device_id] = {}
                
            self.calibration_data[device_id]['type'] = calibration_type
            self.calibration_data[device_id]['start_time'] = self.calibration_start_time
            self.calibration_data[device_id]['samples'] = []
            
            # 触发开始回调
            self._trigger_calibration_callback('calibration_started', {
                'device_id': device_id,
                'calibration_type': calibration_type,
                'total_steps': self.calibration_state['total_steps']
            })
            
            print(f"✓ 设备校准已开始: ID {device_id}, 类型 {calibration_type}")
            self.calibration_stats['manual_calibrations'] += 1
            return True
            
        except Exception as e:
            print(f"✗ 设备校准开始失败: {e}")
            import traceback
            traceback.print_exc()
            return False
            
    def start_auto_calibration(self, device_id: int) -> bool:
        """
        开始自动校准
        
        Args:
            device_id: 设备ID
            
        Returns:
            是否开始成功
        """
        try:
            result = self.start_calibration(device_id, "full")
            if result:
                print(f"✓ 自动校准已开始: ID {device_id}")
            return result
        except Exception as e:
            print(f"✗ 自动校准开始失败: {e}")
            return False
            
    def update_calibration(self, sample_data: Dict[str, Any]) -> bool:
        """
        更新校准数据
        
        Args:
            sample_data: 采样数据
            
        Returns:
            是否更新成功
        """
        try:
            if not self.calibration_state['is_calibrating']:
                print("✗ 没有正在进行的校准")
                return False
                
            device_id = self.calibration_state['current_device']
            if device_id not in self.calibration_data:
                print("✗ 校准数据不存在")
                return False
                
            # 添加采样数据
            self.calibration_data[device_id]['samples'].append(sample_data)
            
            # 更新进度
            self.calibration_state['calibration_step'] += 1
            progress = self.calibration_state['calibration_step'] / self.calibration_state['total_steps']
            self.calibration_state['progress'] = min(1.0, progress)
            
            # 触进进度回调
            self._trigger_calibration_callback('calibration_progress', {
                'device_id': device_id,
                'step': self.calibration_state['calibration_step'],
                'total_steps': self.calibration_state['total_steps'],
                'progress': self.calibration_state['progress'],
                'sample_data': sample_data
            })
            
            # 检查是否完成
            if self.calibration_state['calibration_step'] >= self.calibration_state['total_steps']:
                self._complete_calibration()
                
            return True
            
        except Exception as e:
            print(f"✗ 校准数据更新失败: {e}")
            return False
            
    def _complete_calibration(self):
        """完成校准"""
        try:
            device_id = self.calibration_state['current_device']
            calibration_data = self.calibration_data[device_id]
            
            # 分析采样数据
            calibration_result = self._analyze_calibration_samples(calibration_data)
            
            # 应用校准结果
            self._apply_calibration_result(device_id, calibration_result)
            
            # 记录校准历史
            self._record_calibration_history(device_id, calibration_result)
            
            # 更新时间戳
            self.last_auto_calibration[device_id] = time.time()
            
            # 重置校准状态
            self.calibration_state['is_calibrating'] = False
            self.calibration_state['current_device'] = None
            self.calibration_state['calibration_step'] = 0
            self.calibration_state['total_steps'] = 0
            self.calibration_state['progress'] = 0.0
            
            # 更新统计信息
            self.calibration_stats['calibrations_performed'] += 1
            self.calibration_stats['calibrations_successful'] += 1
            
            # 触发完成回调
            self._trigger_calibration_callback('calibration_completed', {
                'device_id': device_id,
                'result': calibration_result,
                'duration': time.time() - self.calibration_start_time
            })
            
            print(f"✓ 设备校准已完成: ID {device_id}")
            
        except Exception as e:
            print(f"✗ 校准完成处理失败: {e}")
            self._handle_calibration_failure()
            
    def _analyze_calibration_samples(self, calibration_data: Dict[str, Any]) -> Dict[str, Any]:
        """
        分析校准采样数据
        
        Args:
            calibration_data: 校准数据
            
        Returns:
            分析结果
        """
        try:
            samples = calibration_data.get('samples', [])
            if not samples:
                return {}
                
            result = {
                'sample_count': len(samples),
                'analysis_time': time.time()
            }
            
            # 分析不同类型的输入数据
            axis_data = {}
            button_data = {}
            
            for sample in samples:
                for key, value in sample.items():
                    if isinstance(value, (int, float)):
                        # 轴数据
                        if key not in axis_data:
                            axis_data[key] = []
                        axis_data[key].append(value)
                    elif isinstance(value, bool):
                        # 按钮数据
                        if key not in button_data:
                            button_data[key] = []
                        button_data[key].append(value)
                        
            # 计算轴统计数据
            axis_stats = {}
            for axis_name, values in axis_data.items():
                if values:
                    axis_stats[axis_name] = {
                        'min': min(values),
                        'max': max(values),
                        'mean': sum(values) / len(values),
                        'median': sorted(values)[len(values) // 2],
                        'std_dev': math.sqrt(sum((x - sum(values) / len(values)) ** 2 for x in values) / len(values))
                    }
                    
            result['axis_stats'] = axis_stats
            result['button_stats'] = button_data
            
            # 计算死区、范围和中心点
            deadzones = {}
            ranges = {}
            centers = {}
            
            for axis_name, stats in axis_stats.items():
                # 死区计算（基于标准差）
                deadzones[axis_name] = max(self.calibration_config['sensitivity_threshold'], 
                                         stats['std_dev'] * 2)
                                         
                # 范围计算
                ranges[axis_name] = {
                    'min': stats['min'],
                    'max': stats['max']
                }
                
                # 中心点计算
                centers[axis_name] = stats['mean']
                
            result['deadzones'] = deadzones
            result['ranges'] = ranges
            result['centers'] = centers
            
            return result
            
        except Exception as e:
            print(f"✗ 校准数据分析失败: {e}")
            return {}
            
    def _apply_calibration_result(self, device_id: int, calibration_result: Dict[str, Any]):
        """
        应用校准结果
        
        Args:
            device_id: 设备ID
            calibration_result: 校准结果
        """
        try:
            # 应用死区设置
            if 'deadzones' in calibration_result and self.calibration_config['deadzone_calibration']:
                deadzones = calibration_result['deadzones']
                for axis_name, deadzone in deadzones.items():
                    # 在实际实现中，这里会更新设备的死区设置
                    print(f"  应用死区设置 {axis_name}: {deadzone}")
                    
            # 应用范围设置
            if 'ranges' in calibration_result and self.calibration_config['range_calibration']:
                ranges = calibration_result['ranges']
                for axis_name, range_data in ranges.items():
                    # 在实际实现中，这里会更新设备的范围设置
                    print(f"  应用范围设置 {axis_name}: {range_data}")
                    
            # 应用中心点设置
            if 'centers' in calibration_result and self.calibration_config['center_calibration']:
                centers = calibration_result['centers']
                for axis_name, center in centers.items():
                    # 在实际实现中，这里会更新设备的中心点设置
                    print(f"  应用中心点设置 {axis_name}: {center}")
                    
            # 保存校准配置
            self._save_calibration_config(device_id, calibration_result)
            
        except Exception as e:
            print(f"✗ 校准结果应用失败: {e}")
            
    def _save_calibration_config(self, device_id: int, calibration_result: Dict[str, Any]):
        """
        保存校准配置
        
        Args:
            device_id: 设备ID
            calibration_result: 校准结果
        """
        try:
            # 在实际实现中，这里会将校准结果保存到配置文件或数据库
            print(f"  校准配置已保存: 设备 {device_id}")
        except Exception as e:
            print(f"✗ 校准配置保存失败: {e}")
            
    def _record_calibration_history(self, device_id: int, calibration_result: Dict[str, Any]):
        """
        记录校准历史
        
        Args:
            device_id: 设备ID
            calibration_result: 校准结果
        """
        try:
            if device_id not in self.calibration_history:
                self.calibration_history[device_id] = []
                
            history_entry = {
                'timestamp': time.time(),
                'result': calibration_result,
                'duration': time.time() - self.calibration_start_time
            }
            
            self.calibration_history[device_id].append(history_entry)
            
            # 保持历史记录大小
            if len(self.calibration_history[device_id]) > 50:
                self.calibration_history[device_id].pop(0)
                
        except Exception as e:
            print(f"✗ 校准历史记录失败: {e}")
            
    def _handle_calibration_failure(self):
        """处理校准失败"""
        try:
            device_id = self.calibration_state['current_device']
            
            # 重置校准状态
            self.calibration_state['is_calibrating'] = False
            self.calibration_state['current_device'] = None
            self.calibration_state['calibration_step'] = 0
            self.calibration_state['total_steps'] = 0
            self.calibration_state['progress'] = 0.0
            
            # 更新统计信息
            self.calibration_stats['calibrations_performed'] += 1
            self.calibration_stats['calibrations_failed'] += 1
            
            # 触发失败回调
            self._trigger_calibration_callback('calibration_failed', {
                'device_id': device_id,
                'error': 'Calibration process failed'
            })
            
            print(f"✗ 设备校准失败: ID {device_id}")
            
        except Exception as e:
            print(f"✗ 校准失败处理失败: {e}")
            
    def cancel_calibration(self) -> bool:
        """
        取消校准
        
        Returns:
            是否取消成功
        """
        try:
            if not self.calibration_state['is_calibrating']:
                print("✗ 没有正在进行的校准")
                return False
                
            device_id = self.calibration_state['current_device']
            
            # 重置校准状态
            self.calibration_state['is_calibrating'] = False
            self.calibration_state['current_device'] = None
            self.calibration_state['calibration_step'] = 0
            self.calibration_state['total_steps'] = 0
            self.calibration_state['progress'] = 0.0
            
            print(f"✓ 设备校准已取消: ID {device_id}")
            return True
            
        except Exception as e:
            print(f"✗ 校准取消失败: {e}")
            return False
            
    def get_calibration_status(self) -> Dict[str, Any]:
        """
        获取校准状态
        
        Returns:
            校准状态字典
        """
        return self.calibration_state.copy()
        
    def get_calibration_data(self, device_id: int) -> Optional[Dict[str, Any]]:
        """
        获取设备校准数据
        
        Args:
            device_id: 设备ID
            
        Returns:
            校准数据字典或None
        """
        return self.calibration_data.get(device_id)
        
    def get_calibration_history(self, device_id: int, limit: int = None) -> List[Dict[str, Any]]:
        """
        获取设备校准历史
        
        Args:
            device_id: 设备ID
            limit: 返回记录数量限制
            
        Returns:
            校准历史列表
        """
        try:
            history = self.calibration_history.get(device_id, []).copy()
            if limit:
                history = history[-limit:]
            return history
        except Exception as e:
            print(f"✗ 校准历史获取失败: {e}")
            return []
            
    def clear_calibration_history(self, device_id: int = None):
        """
        清空校准历史
        
        Args:
            device_id: 设备ID（None表示清空所有）
        """
        try:
            if device_id is None:
                self.calibration_history.clear()
                print("✓ 所有校准历史已清空")
            else:
                if device_id in self.calibration_history:
                    del self.calibration_history[device_id]
                    print(f"✓ 设备校准历史已清空: ID {device_id}")
        except Exception as e:
            print(f"✗ 校准历史清空失败: {e}")
            
    def _trigger_calibration_callback(self, callback_type: str, data: Dict[str, Any]):
        """
        触发校准回调
        
        Args:
            callback_type: 回调类型
            data: 回调数据
        """
        try:
            if callback_type in self.calibration_callbacks:
                for callback in self.calibration_callbacks[callback_type]:
                    try:
                        callback(data)
                    except Exception as e:
                        print(f"✗ 校准回调执行失败: {e}")
        except Exception as e:
            print(f"✗ 校准回调触发失败: {e}")
            
    def register_calibration_callback(self, callback_type: str, callback: Callable):
        """
        注册校准回调
        
        Args:
            callback_type: 回调类型
            callback: 回调函数
        """
        try:
            if callback_type in self.calibration_callbacks:
                self.calibration_callbacks[callback_type].append(callback)
                print(f"✓ 校准回调已注册: {callback_type}")
            else:
                print(f"✗ 无效的回调类型: {callback_type}")
        except Exception as e:
            print(f"✗ 校准回调注册失败: {e}")
            
    def unregister_calibration_callback(self, callback_type: str, callback: Callable):
        """
        注销校准回调
        
        Args:
            callback_type: 回调类型
            callback: 回调函数
        """
        try:
            if callback_type in self.calibration_callbacks:
                if callback in self.calibration_callbacks[callback_type]:
                    self.calibration_callbacks[callback_type].remove(callback)
                    print(f"✓ 校准回调已注销: {callback_type}")
        except Exception as e:
            print(f"✗ 校准回调注销失败: {e}")
            
    def set_calibration_config(self, config: Dict[str, Any]) -> bool:
        """
        设置校准配置
        
        Args:
            config: 校准配置字典
            
        Returns:
            是否设置成功
        """
        try:
            self.calibration_config.update(config)
            print(f"✓ 校准配置已更新: {self.calibration_config}")
            return True
        except Exception as e:
            print(f"✗ 校准配置设置失败: {e}")
            return False
            
    def get_calibration_config(self) -> Dict[str, Any]:
        """
        获取校准配置
        
        Returns:
            校准配置字典
        """
        return self.calibration_config.copy()
        
    def get_calibration_stats(self) -> Dict[str, int]:
        """
        获取校准统计信息
        
        Returns:
            校准统计字典
        """
        return self.calibration_stats.copy()
        
    def reset_calibration_stats(self):
        """重置校准统计信息"""
        try:
            self.calibration_stats = {
                'calibrations_performed': 0,
                'calibrations_successful': 0,
                'calibrations_failed': 0,
                'auto_calibrations': 0,
                'manual_calibrations': 0
            }
            print("✓ 校准统计信息已重置")
        except Exception as e:
            print(f"✗ 校准统计信息重置失败: {e}")
            
    def is_device_calibrated(self, device_id: int) -> bool:
        """
        检查设备是否已校准
        
        Args:
            device_id: 设备ID
            
        Returns:
            是否已校准
        """
        try:
            return device_id in self.calibration_data
        except Exception as e:
            print(f"✗ 设备校准状态检查失败: {e}")
            return False
            
    def get_calibration_quality(self, device_id: int) -> float:
        """
        获取设备校准质量
        
        Args:
            device_id: 设备ID
            
        Returns:
            校准质量评分 (0.0-1.0)
        """
        try:
            if device_id not in self.calibration_data:
                return 0.0
                
            # 基于校准历史和统计数据计算质量评分
            history = self.calibration_history.get(device_id, [])
            if not history:
                return 0.5  # 默认评分
                
            # 简化的质量评分计算
            recent_calibrations = min(5, len(history))
            quality_score = min(1.0, recent_calibrations / 5.0)
            
            return quality_score
            
        except Exception as e:
            print(f"✗ 校准质量评估失败: {e}")
            return 0.0