"""
触觉管理器模块
负责管理触觉效果的播放和设备控制
"""

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

class HapticManager:
    """
    触觉管理器
    负责管理触觉效果的播放和设备控制
    """
    
    def __init__(self, plugin):
        """
        初始化触觉管理器
        
        Args:
            plugin: 触觉反馈系统插件实例
        """
        self.plugin = plugin
        self.enabled = False
        self.initialized = False
        
        # 触觉效果播放器
        self.effect_players = {}
        self.player_counter = 0
        
        # 活跃效果列表
        self.active_effects = {}
        
        # 设备控制
        self.device_controls = {}
        
        # 配置参数
        self.haptic_config = {
            'global_intensity': 1.0,
            'frequency_scale': 1.0,
            'duration_scale': 1.0,
            'crossfade_time': 0.1,
            'max_concurrent_effects': 16,
            'default_falloff': 0.1,
            'enable_spatial_haptics': True,
            'spatial_attenuation': 0.5,
            'enable_temperature_feedback': True,
            'temperature_sensitivity': 1.0
        }
        
        # 空间触觉参数
        self.spatial_haptics = {
            'listener_position': (0.0, 0.0, 0.0),
            'listener_orientation': (0.0, 0.0, 0.0, 1.0),  # 四元数
            'distance_model': 'inverse',
            'reference_distance': 1.0,
            'max_distance': 100.0,
            'rolloff_factor': 1.0
        }
        
        # 温度反馈参数
        self.temperature_feedback = {
            'min_temperature': 20.0,  # 摄氏度
            'max_temperature': 60.0,
            'current_temperature': 25.0,
            'heating_rate': 2.0,  # 每秒升温速度
            'cooling_rate': 1.0,  # 每秒降温速度
            'thermal_inertia': 0.5  # 热惯性系数
        }
        
        # 统计信息
        self.stats = {
            'effects_played': 0,
            'effects_stopped': 0,
            'effects_paused': 0,
            'effects_resumed': 0,
            'active_effects': 0,
            'spatial_effects': 0,
            'temperature_effects': 0
        }
        
        # 线程管理
        self.update_thread = None
        self.running = False
        
        # 回调函数
        self.haptic_callbacks = {
            'effect_started': [],
            'effect_stopped': [],
            'effect_updated': [],
            'spatial_effect_processed': [],
            'temperature_effect_processed': []
        }
        
        # 效果池
        self.effect_pool = {}
        
        # 时间戳记录
        self.last_update_time = 0.0
        
        print("✓ 触觉管理器已创建")
        
    def initialize(self) -> bool:
        """
        初始化触觉管理器
        
        Returns:
            是否初始化成功
        """
        try:
            # 初始化效果池
            self._initialize_effect_pool()
            
            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
            
            # 启动更新线程
            self.update_thread = threading.Thread(target=self._update_loop, daemon=True)
            self.update_thread.start()
            
            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.update_thread and self.update_thread.is_alive():
                self.update_thread.join(timeout=1.0)
                
            # 停止所有效果
            self.stop_all_effects()
                
            print("✓ 触觉管理器已禁用")
            
        except Exception as e:
            print(f"✗ 触觉管理器禁用失败: {e}")
            import traceback
            traceback.print_exc()
            
    def finalize(self):
        """清理触觉管理器资源"""
        try:
            self.disable()
            self.effect_players.clear()
            self.active_effects.clear()
            self.device_controls.clear()
            self.haptic_callbacks.clear()
            self.effect_pool.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()
            
            # 更新温度反馈
            self._update_temperature_feedback(dt)
            
            # 更新统计信息
            self.stats['active_effects'] = len(self.active_effects)
            
            self.last_update_time = current_time
            
        except Exception as e:
            print(f"✗ 触觉管理器更新失败: {e}")
            import traceback
            traceback.print_exc()
            
    def _initialize_effect_pool(self):
        """初始化效果池"""
        try:
            # 创建常用效果的预设实例以提高性能
            base_effects = [
                'click', 'buzz', 'rumble', 'pulse', 'heartbeat',
                'explosion', 'impact', 'texture', 'wind', 'water'
            ]
            
            for effect_name in base_effects:
                self.effect_pool[effect_name] = []
                
            print("✓ 效果池初始化完成")
        except Exception as e:
            print(f"✗ 效果池初始化失败: {e}")
            
    def _update_loop(self):
        """更新循环线程"""
        try:
            update_interval = 1.0 / 120.0  # 120Hz
            
            while self.running:
                if self.enabled:
                    self._update_active_effects()
                    
                time.sleep(update_interval)
                
        except Exception as e:
            print(f"✗ 触觉管理器更新循环失败: {e}")
            
    def _update_active_effects(self):
        """更新活跃效果"""
        try:
            current_time = time.time()
            finished_effects = []
            
            # 更新所有活跃效果
            for effect_id, effect_data in list(self.active_effects.items()):
                # 检查效果是否已完成
                if effect_data['start_time'] + effect_data['duration'] <= current_time:
                    finished_effects.append(effect_id)
                else:
                    # 更新效果
                    elapsed_time = current_time - effect_data['start_time']
                    progress = elapsed_time / effect_data['duration']
                    
                    # 应用效果到设备
                    self._apply_effect_to_devices(effect_id, progress, effect_data)
                    
            # 移除已完成的效果
            for effect_id in finished_effects:
                self._finish_effect(effect_id)
                
        except Exception as e:
            print(f"✗ 活跃效果更新失败: {e}")
            
    def _apply_effect_to_devices(self, effect_id: int, progress: float, effect_data: Dict[str, Any]):
        """
        应用效果到设备
        
        Args:
            effect_id: 效果ID
            progress: 效果进度(0.0-1.0)
            effect_data: 效果数据
        """
        try:
            # 获取效果参数
            intensity = effect_data.get('intensity', 1.0)
            frequency = effect_data.get('frequency', 1.0)
            device_id = effect_data.get('device_id')
            position = effect_data.get('position')
            
            # 应用全局配置
            intensity *= self.haptic_config['global_intensity']
            frequency *= self.haptic_config['frequency_scale']
            
            # 处理空间效果
            if position and self.haptic_config['enable_spatial_haptics']:
                intensity = self._calculate_spatial_intensity(position, intensity)
                
            # 计算渐变
            if progress < 0.1:  # 淡入
                fade_factor = progress / 0.1
                intensity *= fade_factor
            elif progress > 0.9:  # 淡出
                fade_factor = (1.0 - progress) / 0.1
                intensity *= fade_factor
                
            # 处理温度反馈
            if self.haptic_config['enable_temperature_feedback']:
                temperature_effect = self._calculate_temperature_effect(effect_data)
                intensity *= temperature_effect
                
            # 发送到设备（实际实现中会调用具体设备API）
            if self.plugin.device_manager:
                self.plugin.device_manager.apply_haptic_effect(
                    device_id, intensity, frequency, progress)
                
        except Exception as e:
            print(f"✗ 效果应用到设备失败: {e}")
            
    def _calculate_spatial_intensity(self, position: tuple, base_intensity: float) -> float:
        """
        计算空间强度衰减
        
        Args:
            position: 效果位置
            base_intensity: 基础强度
            
        Returns:
            衰减后的强度
        """
        try:
            # 计算距离
            listener_pos = self.spatial_haptics['listener_position']
            dx = position[0] - listener_pos[0]
            dy = position[1] - listener_pos[1]
            dz = position[2] - listener_pos[2]
            distance = math.sqrt(dx*dx + dy*dy + dz*dz)
            
            # 根据距离模型计算衰减
            model = self.spatial_haptics['distance_model']
            ref_distance = self.spatial_haptics['reference_distance']
            max_distance = self.spatial_haptics['max_distance']
            rolloff = self.spatial_haptics['rolloff_factor']
            
            if distance > max_distance:
                return 0.0
                
            if model == 'linear':
                # 线性衰减
                attenuation = 1.0 - rolloff * (distance - ref_distance) / (max_distance - ref_distance)
            elif model == 'inverse':
                # 反比衰减
                attenuation = ref_distance / (ref_distance + rolloff * (distance - ref_distance))
            else:  # exponential
                # 指数衰减
                attenuation = math.pow(distance / ref_distance, -rolloff)
                
            # 应用空间衰减
            spatial_intensity = base_intensity * max(0.0, min(1.0, attenuation))
            
            # 触发空间效果回调
            self._trigger_haptic_callback('spatial_effect_processed', {
                'position': position,
                'distance': distance,
                'attenuation': attenuation,
                'intensity': spatial_intensity
            })
            
            self.stats['spatial_effects'] += 1
            return spatial_intensity
            
        except Exception as e:
            print(f"✗ 空间强度计算失败: {e}")
            return base_intensity
            
    def _calculate_temperature_effect(self, effect_data: Dict[str, Any]) -> float:
        """
        计算温度效果
        
        Args:
            effect_data: 效果数据
            
        Returns:
            温度系数
        """
        try:
            # 获取效果温度参数
            effect_temperature = effect_data.get('temperature', 25.0)
            current_temp = self.temperature_feedback['current_temperature']
            
            # 计算温差
            temp_diff = abs(effect_temperature - current_temp)
            sensitivity = self.haptic_config['temperature_sensitivity']
            
            # 计算温度系数 (温差越大，触觉效果越强)
            temp_factor = 1.0 + (temp_diff / 20.0) * sensitivity
            temp_factor = max(0.5, min(2.0, temp_factor))
            
            # 触发温度效果回调
            self._trigger_haptic_callback('temperature_effect_processed', {
                'effect_temperature': effect_temperature,
                'current_temperature': current_temp,
                'temperature_difference': temp_diff,
                'factor': temp_factor
            })
            
            self.stats['temperature_effects'] += 1
            return temp_factor
            
        except Exception as e:
            print(f"✗ 温度效果计算失败: {e}")
            return 1.0
            
    def _update_temperature_feedback(self, dt: float):
        """更新温度反馈"""
        try:
            temp_data = self.temperature_feedback
            target_temp = temp_data.get('target_temperature', temp_data['current_temperature'])
            
            # 根据目标温度调整当前温度
            if temp_data['current_temperature'] < target_temp:
                # 加热
                heating_rate = temp_data['heating_rate'] * temp_data['thermal_inertia']
                temp_data['current_temperature'] += heating_rate * dt
                temp_data['current_temperature'] = min(temp_data['current_temperature'], target_temp)
            elif temp_data['current_temperature'] > target_temp:
                # 冷却
                cooling_rate = temp_data['cooling_rate'] * temp_data['thermal_inertia']
                temp_data['current_temperature'] -= cooling_rate * dt
                temp_data['current_temperature'] = max(temp_data['current_temperature'], target_temp)
                
        except Exception as e:
            print(f"✗ 温度反馈更新失败: {e}")
            
    def _finish_effect(self, effect_id: int):
        """
        完成效果播放
        
        Args:
            effect_id: 效果ID
        """
        try:
            if effect_id in self.active_effects:
                effect_data = self.active_effects[effect_id]
                
                # 触发完成回调
                self._trigger_haptic_callback('effect_stopped', {
                    'effect_id': effect_id,
                    'effect_data': effect_data
                })
                
                # 移除效果
                del self.active_effects[effect_id]
                self.stats['effects_stopped'] += 1
                
                print(f"✓ 触觉效果已完成: ID {effect_id}")
                
        except Exception as e:
            print(f"✗ 效果完成处理失败: {e}")
            
    def play_effect(self, effect_type: str, device_id: int = None, 
                   intensity: float = 1.0, duration: float = 1.0,
                   frequency: float = 1.0, parameters: Dict[str, Any] = None) -> int:
        """
        播放触觉效果
        
        Args:
            effect_type: 效果类型
            device_id: 设备ID（None表示所有设备）
            intensity: 强度(0.0-1.0)
            duration: 持续时间(秒)
            frequency: 频率
            parameters: 额外参数
            
        Returns:
            效果ID
        """
        try:
            if not self.enabled:
                print("✗ 触觉管理器未启用")
                return -1
                
            # 检查并发限制
            if len(self.active_effects) >= self.haptic_config['max_concurrent_effects']:
                print("✗ 达到最大并发效果数")
                return -1
                
            # 限制参数范围
            intensity = max(0.0, min(1.0, intensity))
            duration = max(0.01, min(10.0, duration))
            frequency = max(0.1, min(1000.0, frequency))
                
            # 创建效果数据
            effect_id = int(time.time() * 1000000) % 1000000  # 简单ID生成
            
            effect_data = {
                'id': effect_id,
                'type': effect_type,
                'device_id': device_id,
                'intensity': intensity,
                'duration': duration * self.haptic_config['duration_scale'],
                'frequency': frequency * self.haptic_config['frequency_scale'],
                'parameters': parameters or {},
                'start_time': time.time(),
                'status': 'playing',
                'position': parameters.get('position') if parameters else None,
                'temperature': parameters.get('temperature', 25.0) if parameters else 25.0
            }
            
            # 添加到活跃效果列表
            self.active_effects[effect_id] = effect_data
            
            # 触发开始回调
            self._trigger_haptic_callback('effect_started', {
                'effect_id': effect_id,
                'effect_data': effect_data
            })
            
            self.stats['effects_played'] += 1
            print(f"✓ 触觉效果已播放: {effect_type} (ID: {effect_id})")
            return effect_id
            
        except Exception as e:
            print(f"✗ 触觉效果播放失败: {e}")
            return -1
            
    def stop_effect(self, effect_id: int) -> bool:
        """
        停止触觉效果
        
        Args:
            effect_id: 效果ID
            
        Returns:
            是否停止成功
        """
        try:
            if effect_id in self.active_effects:
                effect_data = self.active_effects[effect_id]
                effect_data['status'] = 'stopped'
                
                # 触发停止回调
                self._trigger_haptic_callback('effect_stopped', {
                    'effect_id': effect_id,
                    'effect_data': effect_data
                })
                
                # 移除效果
                del self.active_effects[effect_id]
                self.stats['effects_stopped'] += 1
                
                print(f"✓ 触觉效果已停止: ID {effect_id}")
                return True
            else:
                print(f"✗ 触觉效果不存在: ID {effect_id}")
                return False
                
        except Exception as e:
            print(f"✗ 触觉效果停止失败: {e}")
            return False
            
    def stop_all_effects(self) -> bool:
        """
        停止所有触觉效果
        
        Returns:
            是否停止成功
        """
        try:
            effect_ids = list(self.active_effects.keys())
            for effect_id in effect_ids:
                self.stop_effect(effect_id)
                
            print("✓ 所有触觉效果已停止")
            return True
            
        except Exception as e:
            print(f"✗ 停止所有触觉效果失败: {e}")
            return False
            
    def pause_effect(self, effect_id: int) -> bool:
        """
        暂停触觉效果
        
        Args:
            effect_id: 效果ID
            
        Returns:
            是否暂停成功
        """
        try:
            if effect_id in self.active_effects:
                self.active_effects[effect_id]['status'] = 'paused'
                self.stats['effects_paused'] += 1
                print(f"✓ 触觉效果已暂停: ID {effect_id}")
                return True
            else:
                print(f"✗ 触觉效果不存在: ID {effect_id}")
                return False
                
        except Exception as e:
            print(f"✗ 触觉效果暂停失败: {e}")
            return False
            
    def resume_effect(self, effect_id: int) -> bool:
        """
        恢复触觉效果
        
        Args:
            effect_id: 效果ID
            
        Returns:
            是否恢复成功
        """
        try:
            if effect_id in self.active_effects:
                self.active_effects[effect_id]['status'] = 'playing'
                self.stats['effects_resumed'] += 1
                print(f"✓ 触觉效果已恢复: ID {effect_id}")
                return True
            else:
                print(f"✗ 触觉效果不存在: ID {effect_id}")
                return False
                
        except Exception as e:
            print(f"✗ 触觉效果恢复失败: {e}")
            return False
            
    def get_effect_status(self, effect_id: int) -> Optional[str]:
        """
        获取效果状态
        
        Args:
            effect_id: 效果ID
            
        Returns:
            效果状态或None
        """
        try:
            if effect_id in self.active_effects:
                return self.active_effects[effect_id]['status']
            return None
        except Exception as e:
            print(f"✗ 效果状态获取失败: {e}")
            return None
            
    def set_haptic_config(self, config: Dict[str, Any]) -> bool:
        """
        设置触觉配置
        
        Args:
            config: 配置字典
            
        Returns:
            是否设置成功
        """
        try:
            self.haptic_config.update(config)
            print(f"✓ 触觉配置已更新: {self.haptic_config}")
            return True
        except Exception as e:
            print(f"✗ 触觉配置设置失败: {e}")
            return False
            
    def get_haptic_config(self) -> Dict[str, Any]:
        """
        获取触觉配置
        
        Returns:
            配置字典
        """
        return self.haptic_config.copy()
        
    def set_spatial_parameters(self, params: Dict[str, Any]) -> bool:
        """
        设置空间参数
        
        Args:
            params: 空间参数字典
            
        Returns:
            是否设置成功
        """
        try:
            self.spatial_haptics.update(params)
            print(f"✓ 空间参数已更新: {self.spatial_haptics}")
            return True
        except Exception as e:
            print(f"✗ 空间参数设置失败: {e}")
            return False
            
    def get_spatial_parameters(self) -> Dict[str, Any]:
        """
        获取空间参数
        
        Returns:
            空间参数字典
        """
        return self.spatial_haptics.copy()
        
    def set_temperature_parameters(self, params: Dict[str, Any]) -> bool:
        """
        设置温度参数
        
        Args:
            params: 温度参数字典
            
        Returns:
            是否设置成功
        """
        try:
            self.temperature_feedback.update(params)
            print(f"✓ 温度参数已更新: {self.temperature_feedback}")
            return True
        except Exception as e:
            print(f"✗ 温度参数设置失败: {e}")
            return False
            
    def get_temperature_parameters(self) -> Dict[str, Any]:
        """
        获取温度参数
        
        Returns:
            温度参数字典
        """
        return self.temperature_feedback.copy()
        
    def set_listener_position(self, position: tuple):
        """
        设置监听器位置
        
        Args:
            position: 位置坐标 (x, y, z)
        """
        try:
            self.spatial_haptics['listener_position'] = position
        except Exception as e:
            print(f"✗ 监听器位置设置失败: {e}")
            
    def set_listener_orientation(self, orientation: tuple):
        """
        设置监听器方向
        
        Args:
            orientation: 方向四元数 (x, y, z, w)
        """
        try:
            self.spatial_haptics['listener_orientation'] = orientation
        except Exception as e:
            print(f"✗ 监听器方向设置失败: {e}")
            
    def _trigger_haptic_callback(self, callback_type: str, data: Dict[str, Any]):
        """
        触发触觉回调
        
        Args:
            callback_type: 回调类型
            data: 回调数据
        """
        try:
            if callback_type in self.haptic_callbacks:
                for callback in self.haptic_callbacks[callback_type]:
                    try:
                        callback(data)
                    except Exception as e:
                        print(f"✗ 触觉回调执行失败: {e}")
        except Exception as e:
            print(f"✗ 触觉回调触发失败: {e}")
            
    def register_haptic_callback(self, callback_type: str, callback: callable):
        """
        注册触觉回调
        
        Args:
            callback_type: 回调类型
            callback: 回调函数
        """
        try:
            if callback_type in self.haptic_callbacks:
                self.haptic_callbacks[callback_type].append(callback)
                print(f"✓ 触觉回调已注册: {callback_type}")
            else:
                print(f"✗ 无效的回调类型: {callback_type}")
        except Exception as e:
            print(f"✗ 触觉回调注册失败: {e}")
            
    def unregister_haptic_callback(self, callback_type: str, callback: callable):
        """
        注销触觉回调
        
        Args:
            callback_type: 回调类型
            callback: 回调函数
        """
        try:
            if callback_type in self.haptic_callbacks:
                if callback in self.haptic_callbacks[callback_type]:
                    self.haptic_callbacks[callback_type].remove(callback)
                    print(f"✓ 触觉回调已注销: {callback_type}")
        except Exception as e:
            print(f"✗ 触觉回调注销失败: {e}")
            
    def get_stats(self) -> Dict[str, int]:
        """
        获取统计信息
        
        Returns:
            统计信息字典
        """
        return self.stats.copy()
        
    def reset_stats(self):
        """重置统计信息"""
        try:
            self.stats = {
                'effects_played': 0,
                'effects_stopped': 0,
                'effects_paused': 0,
                'effects_resumed': 0,
                'active_effects': 0,
                'spatial_effects': 0,
                'temperature_effects': 0
            }
            print("✓ 触觉管理器统计信息已重置")
        except Exception as e:
            print(f"✗ 触觉管理器统计信息重置失败: {e}")