"""
物理引擎集成模块
负责将物理引擎中的碰撞和力反馈转换为触觉效果
"""

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

class PhysicsIntegration:
    """
    物理引擎集成
    负责将物理引擎中的碰撞和力反馈转换为触觉效果
    """
    
    def __init__(self, plugin):
        """
        初始化物理引擎集成
        
        Args:
            plugin: 触觉反馈系统插件实例
        """
        self.plugin = plugin
        self.enabled = False
        self.initialized = False
        
        # 物理事件监听器
        self.physics_listeners = {}
        
        # 碰撞效果配置
        self.collision_config = {
            'enable_collision_feedback': True,
            'min_impulse_threshold': 0.1,
            'max_impulse_threshold': 100.0,
            'intensity_scale': 1.0,
            'frequency_scale': 1.0,
            'duration_scale': 1.0,
            'effect_type': 'impulse'
        }
        
        # 力反馈配置
        self.force_config = {
            'enable_force_feedback': True,
            'min_force_threshold': 0.01,
            'max_force_threshold': 10.0,
            'intensity_scale': 1.0,
            'frequency_scale': 1.0,
            'smoothing_factor': 0.1
        }
        
        # 摩擦效果配置
        self.friction_config = {
            'enable_friction_feedback': True,
            'min_velocity_threshold': 0.1,
            'texture_sensitivity': 1.0,
            'vibration_frequency': 20.0
        }
        
        # 材质反馈配置
        self.material_config = {
            'enable_material_feedback': True,
            'material_effects': {
                'metal': {'intensity': 0.8, 'frequency': 60.0, 'type': 'buzz'},
                'wood': {'intensity': 0.6, 'frequency': 30.0, 'type': 'rumble'},
                'stone': {'intensity': 0.9, 'frequency': 80.0, 'type': 'click'},
                'fabric': {'intensity': 0.3, 'frequency': 15.0, 'type': 'soft_rumble'},
                'rubber': {'intensity': 0.5, 'frequency': 25.0, 'type': 'bounce'}
            }
        }
        
        # 状态跟踪
        self.contact_points = {}
        self.force_feedback_state = {}
        self.friction_state = {}
        
        # 统计信息
        self.stats = {
            'collisions_detected': 0,
            'forces_processed': 0,
            'friction_effects': 0,
            'material_effects': 0,
            'haptic_effects_generated': 0
        }
        
        # 回调函数
        self.physics_callbacks = {
            'collision_detected': [],
            'force_applied': [],
            'friction_updated': [],
            'haptic_effect_generated': []
        }
        
        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.physics_listeners.clear()
            self.contact_points.clear()
            self.force_feedback_state.clear()
            self.friction_state.clear()
            self.physics_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
                
            # 更新摩擦状态
            self._update_friction_state(dt)
            
            # 更新力反馈状态
            self._update_force_feedback_state(dt)
            
        except Exception as e:
            print(f"✗ 物理引擎集成更新失败: {e}")
            import traceback
            traceback.print_exc()
            
    def _update_friction_state(self, dt: float):
        """更新摩擦状态"""
        try:
            # 减少摩擦状态值（衰减）
            decay_rate = 0.95
            keys_to_remove = []
            
            for key, state in self.friction_state.items():
                state['intensity'] *= decay_rate
                if state['intensity'] < 0.01:
                    keys_to_remove.append(key)
                    
            # 移除已衰减完毕的状态
            for key in keys_to_remove:
                del self.friction_state[key]
                
        except Exception as e:
            print(f"✗ 摩擦状态更新失败: {e}")
            
    def _update_force_feedback_state(self, dt: float):
        """更新力反馈状态"""
        try:
            # 减少力反馈状态值（平滑）
            smoothing = self.force_config['smoothing_factor']
            keys_to_remove = []
            
            for key, state in self.force_feedback_state.items():
                state['current_force'] = (
                    state['current_force'] * (1 - smoothing) + 
                    state['target_force'] * smoothing
                )
                if abs(state['current_force']) < 0.001:
                    keys_to_remove.append(key)
                    
            # 移除已平滑完毕的状态
            for key in keys_to_remove:
                del self.force_feedback_state[key]
                
        except Exception as e:
            print(f"✗ 力反馈状态更新失败: {e}")
            
    def process_collision(self, collision_data: Dict[str, Any]) -> bool:
        """
        处理碰撞事件并生成触觉效果
        
        Args:
            collision_data: 碰撞数据
            
        Returns:
            是否处理成功
        """
        try:
            if not self.enabled or not self.collision_config['enable_collision_feedback']:
                return False
                
            # 提取碰撞信息
            impulse = collision_data.get('impulse', 0.0)
            contact_point = collision_data.get('contact_point', (0, 0, 0))
            object_a = collision_data.get('object_a', 'unknown')
            object_b = collision_data.get('object_b', 'unknown')
            material_a = collision_data.get('material_a', 'default')
            material_b = collision_data.get('material_b', 'default')
            device_id = collision_data.get('device_id')
            
            # 检查冲量阈值
            if impulse < self.collision_config['min_impulse_threshold']:
                return False
                
            if impulse > self.collision_config['max_impulse_threshold']:
                impulse = self.collision_config['max_impulse_threshold']
                
            # 计算触觉效果强度
            intensity = (
                impulse / self.collision_config['max_impulse_threshold'] * 
                self.collision_config['intensity_scale']
            )
            intensity = max(0.0, min(1.0, intensity))
            
            # 计算频率
            frequency = 20.0 + (impulse * self.collision_config['frequency_scale'])
            frequency = max(1.0, min(100.0, frequency))
            
            # 计算持续时间
            duration = 0.05 + (impulse * 0.01 * self.collision_config['duration_scale'])
            duration = max(0.01, min(1.0, duration))
            
            # 获取材质效果
            material_effect = self._get_material_effect(material_a, material_b)
            
            # 生成触觉效果
            effect_type = self.collision_config['effect_type']
            if material_effect:
                effect_type = material_effect.get('type', effect_type)
                intensity *= material_effect.get('intensity', 1.0)
                frequency = material_effect.get('frequency', frequency)
                
            # 播放触觉效果
            if self.plugin.haptic_manager:
                effect_id = self.plugin.haptic_manager.play_effect(
                    effect_type=effect_type,
                    device_id=device_id,
                    intensity=intensity,
                    duration=duration,
                    frequency=frequency,
                    parameters={
                        'collision_impulse': impulse,
                        'contact_point': contact_point,
                        'objects': [object_a, object_b],
                        'materials': [material_a, material_b]
                    }
                )
                
                if effect_id >= 0:
                    # 触发效果生成回调
                    self._trigger_physics_callback('haptic_effect_generated', {
                        'effect_id': effect_id,
                        'effect_type': effect_type,
                        'source': 'collision',
                        'intensity': intensity,
                        'frequency': frequency,
                        'duration': duration
                    })
                    
                    self.stats['haptic_effects_generated'] += 1
                    self.stats['collisions_detected'] += 1
                    
                    print(f"✓ 碰撞触觉效果已生成: {effect_type}")
                    return True
                    
            return False
            
        except Exception as e:
            print(f"✗ 碰撞处理失败: {e}")
            return False
            
    def process_force_feedback(self, force_data: Dict[str, Any]) -> bool:
        """
        处理力反馈并生成连续触觉效果
        
        Args:
            force_data: 力反馈数据
            
        Returns:
            是否处理成功
        """
        try:
            if not self.enabled or not self.force_config['enable_force_feedback']:
                return False
                
            # 提取力反馈信息
            force = force_data.get('force', 0.0)
            force_direction = force_data.get('direction', (0, 0, 0))
            object_id = force_data.get('object_id', 'unknown')
            device_id = force_data.get('device_id')
            
            # 检查力阈值
            if abs(force) < self.force_config['min_force_threshold']:
                return False
                
            if abs(force) > self.force_config['max_force_threshold']:
                force = math.copysign(self.force_config['max_force_threshold'], force)
                
            # 计算触觉效果强度
            intensity = (
                abs(force) / self.force_config['max_force_threshold'] * 
                self.force_config['intensity_scale']
            )
            intensity = max(0.0, min(1.0, intensity))
            
            # 计算频率
            frequency = 10.0 + (abs(force) * self.force_config['frequency_scale'])
            frequency = max(1.0, min(100.0, frequency))
            
            # 更新力反馈状态
            state_key = f"force_{object_id}"
            if state_key not in self.force_feedback_state:
                self.force_feedback_state[state_key] = {
                    'current_force': 0.0,
                    'target_force': force
                }
            else:
                self.force_feedback_state[state_key]['target_force'] = force
                
            # 生成连续触觉效果
            if self.plugin.haptic_manager:
                # 播放连续效果
                effect_id = self.plugin.haptic_manager.play_effect(
                    effect_type='periodic',
                    device_id=device_id,
                    intensity=intensity,
                    duration=0.1,  # 短持续时间，循环播放
                    frequency=frequency,
                    parameters={
                        'force': force,
                        'direction': force_direction,
                        'object_id': object_id
                    }
                )
                
                if effect_id >= 0:
                    # 触发效果生成回调
                    self._trigger_physics_callback('haptic_effect_generated', {
                        'effect_id': effect_id,
                        'effect_type': 'periodic',
                        'source': 'force',
                        'intensity': intensity,
                        'frequency': frequency
                    })
                    
                    self.stats['haptic_effects_generated'] += 1
                    self.stats['forces_processed'] += 1
                    
                    print(f"✓ 力反馈触觉效果已生成: 强度 {intensity:.2f}")
                    return True
                    
            return False
            
        except Exception as e:
            print(f"✗ 力反馈处理失败: {e}")
            return False
            
    def process_friction(self, friction_data: Dict[str, Any]) -> bool:
        """
        处理摩擦并生成纹理触觉效果
        
        Args:
            friction_data: 摩擦数据
            
        Returns:
            是否处理成功
        """
        try:
            if not self.enabled or not self.friction_config['enable_friction_feedback']:
                return False
                
            # 提取摩擦信息
            velocity = friction_data.get('velocity', 0.0)
            surface_normal = friction_data.get('normal', (0, 0, 1))
            object_id = friction_data.get('object_id', 'unknown')
            material = friction_data.get('material', 'default')
            device_id = friction_data.get('device_id')
            
            # 检查速度阈值
            if abs(velocity) < self.friction_config['min_velocity_threshold']:
                return False
                
            # 计算触觉效果强度
            intensity = min(1.0, abs(velocity) * 0.1 * self.friction_config['texture_sensitivity'])
            
            # 获取材质效果
            material_effect = self._get_material_effect(material)
            
            # 计算频率
            frequency = self.friction_config['vibration_frequency']
            if material_effect:
                frequency = material_effect.get('frequency', frequency)
                
            # 更新摩擦状态
            state_key = f"friction_{object_id}"
            if state_key not in self.friction_state:
                self.friction_state[state_key] = {
                    'intensity': intensity,
                    'velocity': velocity
                }
            else:
                self.friction_state[state_key]['intensity'] = max(
                    self.friction_state[state_key]['intensity'],
                    intensity
                )
                
            # 生成摩擦触觉效果
            if self.plugin.haptic_manager:
                effect_id = self.plugin.haptic_manager.play_effect(
                    effect_type='noise',
                    device_id=device_id,
                    intensity=intensity,
                    duration=0.05,
                    frequency=frequency,
                    parameters={
                        'velocity': velocity,
                        'material': material,
                        'object_id': object_id
                    }
                )
                
                if effect_id >= 0:
                    # 触发效果生成回调
                    self._trigger_physics_callback('haptic_effect_generated', {
                        'effect_id': effect_id,
                        'effect_type': 'noise',
                        'source': 'friction',
                        'intensity': intensity,
                        'frequency': frequency
                    })
                    
                    self.stats['haptic_effects_generated'] += 1
                    self.stats['friction_effects'] += 1
                    
                    print(f"✓ 摩擦触觉效果已生成: 强度 {intensity:.2f}")
                    return True
                    
            return False
            
        except Exception as e:
            print(f"✗ 摩擦处理失败: {e}")
            return False
            
    def _get_material_effect(self, *materials) -> Optional[Dict[str, Any]]:
        """
        获取材质效果配置
        
        Args:
            *materials: 材质名称
            
        Returns:
            材质效果配置或None
        """
        try:
            if not self.material_config['enable_material_feedback']:
                return None
                
            material_effects = self.material_config['material_effects']
            
            # 尝试匹配每个材质
            for material in materials:
                if material in material_effects:
                    return material_effects[material]
                    
            return None
        except Exception as e:
            print(f"✗ 材质效果获取失败: {e}")
            return None
            
    def register_physics_listener(self, event_type: str, callback: callable):
        """
        注册物理事件监听器
        
        Args:
            event_type: 事件类型
            callback: 回调函数
        """
        try:
            if event_type in self.physics_listeners:
                self.physics_listeners[event_type].append(callback)
            else:
                self.physics_listeners[event_type] = [callback]
                
            print(f"✓ 物理事件监听器已注册: {event_type}")
        except Exception as e:
            print(f"✗ 物理事件监听器注册失败: {e}")
            
    def unregister_physics_listener(self, event_type: str, callback: callable):
        """
        注销物理事件监听器
        
        Args:
            event_type: 事件类型
            callback: 回调函数
        """
        try:
            if event_type in self.physics_listeners:
                if callback in self.physics_listeners[event_type]:
                    self.physics_listeners[event_type].remove(callback)
                    print(f"✓ 物理事件监听器已注销: {event_type}")
        except Exception as e:
            print(f"✗ 物理事件监听器注销失败: {e}")
            
    def _trigger_physics_callback(self, callback_type: str, data: Dict[str, Any]):
        """
        触发物理回调
        
        Args:
            callback_type: 回调类型
            data: 回调数据
        """
        try:
            if callback_type in self.physics_callbacks:
                for callback in self.physics_callbacks[callback_type]:
                    try:
                        callback(data)
                    except Exception as e:
                        print(f"✗ 物理回调执行失败: {e}")
        except Exception as e:
            print(f"✗ 物理回调触发失败: {e}")
            
    def register_physics_callback(self, callback_type: str, callback: callable):
        """
        注册物理回调
        
        Args:
            callback_type: 回调类型
            callback: 回调函数
        """
        try:
            if callback_type in self.physics_callbacks:
                self.physics_callbacks[callback_type].append(callback)
                print(f"✓ 物理回调已注册: {callback_type}")
            else:
                print(f"✗ 无效的回调类型: {callback_type}")
        except Exception as e:
            print(f"✗ 物理回调注册失败: {e}")
            
    def unregister_physics_callback(self, callback_type: str, callback: callable):
        """
        注销物理回调
        
        Args:
            callback_type: 回调类型
            callback: 回调函数
        """
        try:
            if callback_type in self.physics_callbacks:
                if callback in self.physics_callbacks[callback_type]:
                    self.physics_callbacks[callback_type].remove(callback)
                    print(f"✓ 物理回调已注销: {callback_type}")
        except Exception as e:
            print(f"✗ 物理回调注销失败: {e}")
            
    def set_collision_config(self, config: Dict[str, Any]) -> bool:
        """
        设置碰撞配置
        
        Args:
            config: 配置字典
            
        Returns:
            是否设置成功
        """
        try:
            self.collision_config.update(config)
            print(f"✓ 碰撞配置已更新: {self.collision_config}")
            return True
        except Exception as e:
            print(f"✗ 碰撞配置设置失败: {e}")
            return False
            
    def set_force_config(self, config: Dict[str, Any]) -> bool:
        """
        设置力反馈配置
        
        Args:
            config: 配置字典
            
        Returns:
            是否设置成功
        """
        try:
            self.force_config.update(config)
            print(f"✓ 力反馈配置已更新: {self.force_config}")
            return True
        except Exception as e:
            print(f"✗ 力反馈配置设置失败: {e}")
            return False
            
    def set_friction_config(self, config: Dict[str, Any]) -> bool:
        """
        设置摩擦配置
        
        Args:
            config: 配置字典
            
        Returns:
            是否设置成功
        """
        try:
            self.friction_config.update(config)
            print(f"✓ 摩擦配置已更新: {self.friction_config}")
            return True
        except Exception as e:
            print(f"✗ 摩擦配置设置失败: {e}")
            return False
            
    def set_material_config(self, config: Dict[str, Any]) -> bool:
        """
        设置材质配置
        
        Args:
            config: 配置字典
            
        Returns:
            是否设置成功
        """
        try:
            self.material_config.update(config)
            print(f"✓ 材质配置已更新: {self.material_config}")
            return True
        except Exception as e:
            print(f"✗ 材质配置设置失败: {e}")
            return False
            
    def get_collision_config(self) -> Dict[str, Any]:
        """
        获取碰撞配置
        
        Returns:
            配置字典
        """
        return self.collision_config.copy()
        
    def get_force_config(self) -> Dict[str, Any]:
        """
        获取力反馈配置
        
        Returns:
            配置字典
        """
        return self.force_config.copy()
        
    def get_friction_config(self) -> Dict[str, Any]:
        """
        获取摩擦配置
        
        Returns:
            配置字典
        """
        return self.friction_config.copy()
        
    def get_material_config(self) -> Dict[str, Any]:
        """
        获取材质配置
        
        Returns:
            配置字典
        """
        return self.material_config.copy()
        
    def get_stats(self) -> Dict[str, int]:
        """
        获取统计信息
        
        Returns:
            统计信息字典
        """
        return self.stats.copy()
        
    def reset_stats(self):
        """重置统计信息"""
        try:
            self.stats = {
                'collisions_detected': 0,
                'forces_processed': 0,
                'friction_effects': 0,
                'material_effects': 0,
                'haptic_effects_generated': 0
            }
            print("✓ 物理引擎集成统计信息已重置")
        except Exception as e:
            print(f"✗ 物理引擎集成统计信息重置失败: {e}")