"""
手势识别器模块
负责识别和处理各种手势输入
"""

import time
from typing import Dict, Any, List, Optional, Callable, Tuple
from enum import Enum
import math

class GestureType(Enum):
    """手势类型枚举"""
    TAP = "tap"
    DOUBLE_TAP = "double_tap"
    LONG_PRESS = "long_press"
    SWIPE = "swipe"
    PINCH = "pinch"
    ROTATE = "rotate"
    DRAG = "drag"
    FLICK = "flick"
    CIRCLE = "circle"
    SHAKE = "shake"
    CUSTOM = "custom"

class GestureState(Enum):
    """手势状态枚举"""
    STARTED = "started"
    UPDATED = "updated"
    ENDED = "ended"
    CANCELLED = "cancelled"
    RECOGNIZED = "recognized"

class GestureRecognizer:
    """
    手势识别器
    负责识别和处理各种手势输入
    """
    
    def __init__(self, plugin):
        """
        初始化手势识别器
        
        Args:
            plugin: 多平台输入支持插件实例
        """
        self.plugin = plugin
        self.enabled = False
        self.initialized = False
        
        # 手势配置
        self.gesture_config = {
            'tap_max_duration': 0.3,        # 点击最大持续时间(秒)
            'tap_max_distance': 20.0,       # 点击最大移动距离(像素)
            'double_tap_timeout': 0.3,      # 双击超时时间(秒)
            'long_press_duration': 0.5,     # 长按持续时间(秒)
            'swipe_min_distance': 50.0,     # 滑动最小距离(像素)
            'swipe_max_duration': 0.5,      # 滑动最大持续时间(秒)
            'pinch_threshold': 20.0,        # 捏合阈值(像素)
            'rotate_threshold': 10.0,       # 旋转阈值(度)
            'flick_min_velocity': 100.0,    # 轻拂最小速度(像素/秒)
            'circle_min_radius': 30.0,      # 圆形最小半径(像素)
            'circle_tolerance': 0.3,        # 圆形容差
            'shake_threshold': 20.0,        # 摇晃阈值(像素)
            'shake_count': 3,               # 摇晃次数阈值
            'update_interval': 0.016        # 更新间隔(秒)
        }
        
        # 当前手势状态
        self.active_gestures = {}
        self.gesture_counter = 0
        
        # 触摸点跟踪
        self.touch_points = {}
        self.touch_counter = 0
        
        # 手势历史
        self.gesture_history = []
        
        # 回调函数
        self.gesture_callbacks = {}
        
        # 统计信息
        self.gesture_stats = {
            'gestures_started': 0,
            'gestures_recognized': 0,
            'gestures_cancelled': 0,
            'gestures_failed': 0,
            'active_gestures': 0
        }
        
        # 时间戳记录
        self.last_gesture_time = {}
        self.gesture_start_time = {}
        
        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.active_gestures.clear()
            self.touch_points.clear()
            self.gesture_history.clear()
            self.gesture_callbacks.clear()
            self.last_gesture_time.clear()
            self.gesture_start_time.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_active_gestures(dt)
            
        except Exception as e:
            print(f"✗ 手势识别器更新失败: {e}")
            import traceback
            traceback.print_exc()
            
    def _update_active_gestures(self, dt: float):
        """更新活动手势"""
        try:
            current_time = time.time()
            
            # 检查超时的手势
            timed_out_gestures = []
            for gesture_id, gesture_data in self.active_gestures.items():
                start_time = self.gesture_start_time.get(gesture_id, current_time)
                if current_time - start_time > 5.0:  # 5秒超时
                    timed_out_gestures.append(gesture_id)
                    
            # 取消超时手势
            for gesture_id in timed_out_gestures:
                self._cancel_gesture(gesture_id)
                
        except Exception as e:
            print(f"✗ 活动手势更新失败: {e}")
            
    def start_touch(self, touch_id: int, x: float, y: float, timestamp: float = None):
        """
        开始触摸
        
        Args:
            touch_id: 触摸点ID
            x: X坐标
            y: Y坐标
            timestamp: 时间戳
        """
        try:
            if not self.enabled:
                return
                
            if timestamp is None:
                timestamp = time.time()
                
            # 记录触摸点
            self.touch_points[touch_id] = {
                'id': touch_id,
                'start_x': x,
                'start_y': y,
                'current_x': x,
                'current_y': y,
                'start_time': timestamp,
                'last_update': timestamp,
                'path': [(x, y, timestamp)]
            }
            
            # 如果是第一个触摸点，开始新的手势
            if len(self.touch_points) == 1:
                self._start_new_gesture(touch_id, x, y, timestamp)
                
        except Exception as e:
            print(f"✗ 触摸开始处理失败: {e}")
            
    def update_touch(self, touch_id: int, x: float, y: float, timestamp: float = None):
        """
        更新触摸
        
        Args:
            touch_id: 触摸点ID
            x: X坐标
            y: Y坐标
            timestamp: 时间戳
        """
        try:
            if not self.enabled:
                return
                
            if timestamp is None:
                timestamp = time.time()
                
            # 更新触摸点
            if touch_id in self.touch_points:
                touch_data = self.touch_points[touch_id]
                touch_data['current_x'] = x
                touch_data['current_y'] = y
                touch_data['last_update'] = timestamp
                touch_data['path'].append((x, y, timestamp))
                
                # 保持路径大小
                if len(touch_data['path']) > 50:
                    touch_data['path'].pop(0)
                    
                # 更新活动手势
                self._update_gesture(touch_id, x, y, timestamp)
                
        except Exception as e:
            print(f"✗ 触摸更新处理失败: {e}")
            
    def end_touch(self, touch_id: int, timestamp: float = None):
        """
        结束触摸
        
        Args:
            touch_id: 触摸点ID
            timestamp: 时间戳
        """
        try:
            if not self.enabled:
                return
                
            if timestamp is None:
                timestamp = time.time()
                
            # 更新触摸点
            if touch_id in self.touch_points:
                touch_data = self.touch_points[touch_id]
                touch_data['last_update'] = timestamp
                
                # 结束手势
                self._end_gesture(touch_id, timestamp)
                
                # 移除触摸点
                del self.touch_points[touch_id]
                
        except Exception as e:
            print(f"✗ 触摸结束处理失败: {e}")
            
    def cancel_touch(self, touch_id: int, timestamp: float = None):
        """
        取消触摸
        
        Args:
            touch_id: 触摸点ID
            timestamp: 时间戳
        """
        try:
            if not self.enabled:
                return
                
            if timestamp is None:
                timestamp = time.time()
                
            # 取消手势
            if touch_id in self.touch_points:
                self._cancel_gesture(touch_id)
                del self.touch_points[touch_id]
                
        except Exception as e:
            print(f"✗ 触摸取消处理失败: {e}")
            
    def _start_new_gesture(self, touch_id: int, x: float, y: float, timestamp: float):
        """
        开始新手势
        
        Args:
            touch_id: 触摸点ID
            x: X坐标
            y: Y坐标
            timestamp: 时间戳
        """
        try:
            gesture_id = self.gesture_counter
            self.gesture_counter += 1
            
            gesture_data = {
                'id': gesture_id,
                'type': None,
                'state': GestureState.STARTED,
                'start_x': x,
                'start_y': y,
                'current_x': x,
                'current_y': y,
                'start_time': timestamp,
                'last_update': timestamp,
                'touch_points': [touch_id],
                'parameters': {}
            }
            
            self.active_gestures[gesture_id] = gesture_data
            self.gesture_start_time[gesture_id] = timestamp
            self.gesture_stats['gestures_started'] += 1
            
            # 触发手势开始事件
            self._trigger_gesture_event(gesture_id, GestureState.STARTED, gesture_data)
            
        except Exception as e:
            print(f"✗ 新手势开始失败: {e}")
            
    def _update_gesture(self, touch_id: int, x: float, y: float, timestamp: float):
        """
        更新手势
        
        Args:
            touch_id: 触摸点ID
            x: X坐标
            y: Y坐标
            timestamp: 时间戳
        """
        try:
            # 更新所有包含此触摸点的活动手势
            for gesture_id, gesture_data in self.active_gestures.items():
                if touch_id in gesture_data['touch_points']:
                    gesture_data['current_x'] = x
                    gesture_data['current_y'] = y
                    gesture_data['last_update'] = timestamp
                    
                    # 尝试识别手势
                    self._recognize_gesture(gesture_id, gesture_data, timestamp)
                    
                    # 触发手势更新事件
                    self._trigger_gesture_event(gesture_id, GestureState.UPDATED, gesture_data)
                    
        except Exception as e:
            print(f"✗ 手势更新失败: {e}")
            
    def _end_gesture(self, touch_id: int, timestamp: float):
        """
        结束手势
        
        Args:
            touch_id: 触摸点ID
            timestamp: 时间戳
        """
        try:
            # 结束所有包含此触摸点的活动手势
            finished_gestures = []
            for gesture_id, gesture_data in self.active_gestures.items():
                if touch_id in gesture_data['touch_points']:
                    # 从触摸点列表中移除
                    gesture_data['touch_points'].remove(touch_id)
                    
                    # 如果没有触摸点了，结束手势
                    if not gesture_data['touch_points']:
                        finished_gestures.append(gesture_id)
                        
                        # 如果手势已被识别，触发结束事件
                        if gesture_data['state'] == GestureState.RECOGNIZED:
                            self._trigger_gesture_event(gesture_id, GestureState.ENDED, gesture_data)
                        else:
                            # 尝试最后一次识别
                            self._recognize_gesture(gesture_id, gesture_data, timestamp)
                            if gesture_data['state'] == GestureState.RECOGNIZED:
                                self._trigger_gesture_event(gesture_id, GestureState.ENDED, gesture_data)
                            else:
                                self._cancel_gesture(gesture_id)
                                
            # 移除已完成的手势
            for gesture_id in finished_gestures:
                if gesture_id in self.active_gestures:
                    del self.active_gestures[gesture_id]
                    
        except Exception as e:
            print(f"✗ 手势结束失败: {e}")
            
    def _cancel_gesture(self, gesture_id: int):
        """
        取消手势
        
        Args:
            gesture_id: 手势ID
        """
        try:
            if gesture_id in self.active_gestures:
                gesture_data = self.active_gestures[gesture_id]
                gesture_data['state'] = GestureState.CANCELLED
                
                self._trigger_gesture_event(gesture_id, GestureState.CANCELLED, gesture_data)
                self.gesture_stats['gestures_cancelled'] += 1
                
                del self.active_gestures[gesture_id]
                
        except Exception as e:
            print(f"✗ 手势取消失败: {e}")
            
    def _recognize_gesture(self, gesture_id: int, gesture_data: Dict[str, Any], timestamp: float):
        """
        识别手势
        
        Args:
            gesture_id: 手势ID
            gesture_data: 手势数据
            timestamp: 时间戳
        """
        try:
            # 根据触摸点数量选择识别器
            touch_count = len(gesture_data['touch_points'])
            
            if touch_count == 1:
                self._recognize_single_touch_gesture(gesture_id, gesture_data, timestamp)
            elif touch_count == 2:
                self._recognize_two_touch_gesture(gesture_id, gesture_data, timestamp)
            else:
                self._recognize_multi_touch_gesture(gesture_id, gesture_data, timestamp)
                
        except Exception as e:
            print(f"✗ 手势识别失败: {e}")
            
    def _recognize_single_touch_gesture(self, gesture_id: int, gesture_data: Dict[str, Any], timestamp: float):
        """
        识别单点触摸手势
        
        Args:
            gesture_id: 手势ID
            gesture_data: 手势数据
            timestamp: 时间戳
        """
        try:
            start_x = gesture_data['start_x']
            start_y = gesture_data['start_y']
            current_x = gesture_data['current_x']
            current_y = gesture_data['current_y']
            start_time = gesture_data['start_time']
            
            # 计算距离和持续时间
            distance = math.sqrt((current_x - start_x)**2 + (current_y - start_y)**2)
            duration = timestamp - start_time
            
            # 检查是否为点击
            if duration <= self.gesture_config['tap_max_duration'] and \
               distance <= self.gesture_config['tap_max_distance']:
                
                # 检查是否为双击
                last_tap_time = self.last_gesture_time.get('tap', 0)
                if timestamp - last_tap_time <= self.gesture_config['double_tap_timeout']:
                    # 双击
                    gesture_data['type'] = GestureType.DOUBLE_TAP
                    gesture_data['state'] = GestureState.RECOGNIZED
                    gesture_data['parameters'] = {
                        'position': (current_x, current_y),
                        'duration': duration
                    }
                    self.gesture_stats['gestures_recognized'] += 1
                    self.last_gesture_time['tap'] = timestamp
                    return
                    
                # 单击
                gesture_data['type'] = GestureType.TAP
                gesture_data['state'] = GestureState.RECOGNIZED
                gesture_data['parameters'] = {
                    'position': (current_x, current_y),
                    'duration': duration
                }
                self.gesture_stats['gestures_recognized'] += 1
                self.last_gesture_time['tap'] = timestamp
                return
                
            # 检查是否为长按
            if duration >= self.gesture_config['long_press_duration'] and \
               distance <= self.gesture_config['tap_max_distance']:
                gesture_data['type'] = GestureType.LONG_PRESS
                gesture_data['state'] = GestureState.RECOGNIZED
                gesture_data['parameters'] = {
                    'position': (current_x, current_y),
                    'duration': duration
                }
                self.gesture_stats['gestures_recognized'] += 1
                return
                
            # 检查是否为滑动
            if duration <= self.gesture_config['swipe_max_duration'] and \
               distance >= self.gesture_config['swipe_min_distance']:
                # 计算滑动方向
                dx = current_x - start_x
                dy = current_y - start_y
                angle = math.degrees(math.atan2(dy, dx))
                
                gesture_data['type'] = GestureType.SWIPE
                gesture_data['state'] = GestureState.RECOGNIZED
                gesture_data['parameters'] = {
                    'start_position': (start_x, start_y),
                    'end_position': (current_x, current_y),
                    'distance': distance,
                    'angle': angle,
                    'duration': duration
                }
                self.gesture_stats['gestures_recognized'] += 1
                return
                
            # 检查是否为拖拽
            if duration > self.gesture_config['tap_max_duration'] and \
               distance > self.gesture_config['tap_max_distance']:
                gesture_data['type'] = GestureType.DRAG
                gesture_data['state'] = GestureState.RECOGNIZED
                gesture_data['parameters'] = {
                    'start_position': (start_x, start_y),
                    'end_position': (current_x, current_y),
                    'distance': distance,
                    'duration': duration
                }
                self.gesture_stats['gestures_recognized'] += 1
                return
                
        except Exception as e:
            print(f"✗ 单点手势识别失败: {e}")
            
    def _recognize_two_touch_gesture(self, gesture_id: int, gesture_data: Dict[str, Any], timestamp: float):
        """
        识别两点触摸手势
        
        Args:
            gesture_id: 手势ID
            gesture_data: 手势数据
            timestamp: 时间戳
        """
        try:
            # 获取两个触摸点
            if len(gesture_data['touch_points']) >= 2:
                touch_ids = list(gesture_data['touch_points'])[:2]
                touch1 = self.touch_points.get(touch_ids[0])
                touch2 = self.touch_points.get(touch_ids[1])
                
                if touch1 and touch2:
                    # 计算初始和当前的两点距离
                    start_distance = math.sqrt(
                        (touch1['start_x'] - touch2['start_x'])**2 + 
                        (touch1['start_y'] - touch2['start_y'])**2
                    )
                    
                    current_distance = math.sqrt(
                        (touch1['current_x'] - touch2['current_x'])**2 + 
                        (touch1['current_y'] - touch2['current_y'])**2
                    )
                    
                    # 计算初始和当前的角度
                    start_angle = math.degrees(math.atan2(
                        touch2['start_y'] - touch1['start_y'],
                        touch2['start_x'] - touch1['start_x']
                    ))
                    
                    current_angle = math.degrees(math.atan2(
                        touch2['current_y'] - touch1['current_y'],
                        touch2['current_x'] - touch1['current_x']
                    ))
                    
                    # 检查是否为捏合
                    distance_change = abs(current_distance - start_distance)
                    if distance_change >= self.gesture_config['pinch_threshold']:
                        gesture_data['type'] = GestureType.PINCH
                        gesture_data['state'] = GestureState.RECOGNIZED
                        gesture_data['parameters'] = {
                            'start_distance': start_distance,
                            'current_distance': current_distance,
                            'scale': current_distance / start_distance if start_distance > 0 else 1.0,
                            'center': (
                                (touch1['current_x'] + touch2['current_x']) / 2,
                                (touch1['current_y'] + touch2['current_y']) / 2
                            )
                        }
                        self.gesture_stats['gestures_recognized'] += 1
                        return
                        
                    # 检查是否为旋转
                    angle_change = abs(current_angle - start_angle)
                    if angle_change >= self.gesture_config['rotate_threshold']:
                        gesture_data['type'] = GestureType.ROTATE
                        gesture_data['state'] = GestureState.RECOGNIZED
                        gesture_data['parameters'] = {
                            'start_angle': start_angle,
                            'current_angle': current_angle,
                            'rotation': current_angle - start_angle,
                            'center': (
                                (touch1['current_x'] + touch2['current_x']) / 2,
                                (touch1['current_y'] + touch2['current_y']) / 2
                            )
                        }
                        self.gesture_stats['gestures_recognized'] += 1
                        return
                        
        except Exception as e:
            print(f"✗ 两点手势识别失败: {e}")
            
    def _recognize_multi_touch_gesture(self, gesture_id: int, gesture_data: Dict[str, Any], timestamp: float):
        """
        识别多点触摸手势
        
        Args:
            gesture_id: 手势ID
            gesture_data: 手势数据
            timestamp: 时间戳
        """
        try:
            # 多点手势可以在这里扩展实现
            # 例如：三指滑动、四指捏合等
            pass
        except Exception as e:
            print(f"✗ 多点手势识别失败: {e}")
            
    def _trigger_gesture_event(self, gesture_id: int, state: GestureState, gesture_data: Dict[str, Any]):
        """
        触发手势事件
        
        Args:
            gesture_id: 手势ID
            state: 手势状态
            gesture_data: 手势数据
        """
        try:
            # 记录手势历史
            if state == GestureState.RECOGNIZED:
                self.gesture_history.append({
                    'id': gesture_id,
                    'type': gesture_data['type'].value if gesture_data['type'] else 'unknown',
                    'state': state.value,
                    'parameters': gesture_data['parameters'],
                    'timestamp': time.time()
                })
                
                # 保持历史记录大小
                if len(self.gesture_history) > 100:
                    self.gesture_history.pop(0)
                    
            # 调用手势回调
            gesture_type = gesture_data.get('type')
            if gesture_type and gesture_type in self.gesture_callbacks:
                callback = self.gesture_callbacks[gesture_type]
                try:
                    callback({
                        'gesture_id': gesture_id,
                        'type': gesture_type.value,
                        'state': state.value,
                        'parameters': gesture_data['parameters']
                    })
                except Exception as e:
                    print(f"✗ 手势回调执行失败: {e}")
                    
        except Exception as e:
            print(f"✗ 手势事件触发失败: {e}")
            
    def register_gesture_callback(self, gesture_type: GestureType, callback: Callable):
        """
        注册手势回调
        
        Args:
            gesture_type: 手势类型
            callback: 回调函数
        """
        try:
            self.gesture_callbacks[gesture_type] = callback
            print(f"✓ 手势回调已注册: {gesture_type.value}")
        except Exception as e:
            print(f"✗ 手势回调注册失败: {e}")
            
    def unregister_gesture_callback(self, gesture_type: GestureType):
        """
        注销手势回调
        
        Args:
            gesture_type: 手势类型
        """
        try:
            if gesture_type in self.gesture_callbacks:
                del self.gesture_callbacks[gesture_type]
                print(f"✓ 手势回调已注销: {gesture_type.value}")
        except Exception as e:
            print(f"✗ 手势回调注销失败: {e}")
            
    def get_gesture_history(self, limit: int = None) -> List[Dict[str, Any]]:
        """
        获取手势历史记录
        
        Args:
            limit: 返回记录数量限制
            
        Returns:
            手势历史列表
        """
        try:
            history = self.gesture_history.copy()
            if limit:
                history = history[-limit:]
            return history
        except Exception as e:
            print(f"✗ 手势历史获取失败: {e}")
            return []
            
    def clear_gesture_history(self):
        """清空手势历史"""
        try:
            self.gesture_history.clear()
            print("✓ 手势历史已清空")
        except Exception as e:
            print(f"✗ 手势历史清空失败: {e}")
            
    def set_gesture_config(self, config: Dict[str, Any]):
        """
        设置手势配置
        
        Args:
            config: 手势配置字典
        """
        try:
            self.gesture_config.update(config)
            print(f"✓ 手势配置已更新: {self.gesture_config}")
        except Exception as e:
            print(f"✗ 手势配置设置失败: {e}")
            
    def get_gesture_config(self) -> Dict[str, Any]:
        """
        获取手势配置
        
        Returns:
            手势配置字典
        """
        return self.gesture_config.copy()
        
    def get_gesture_stats(self) -> Dict[str, int]:
        """
        获取手势统计信息
        
        Returns:
            手势统计字典
        """
        return self.gesture_stats.copy()
        
    def reset_gesture_stats(self):
        """重置手势统计信息"""
        try:
            self.gesture_stats = {
                'gestures_started': 0,
                'gestures_recognized': 0,
                'gestures_cancelled': 0,
                'gestures_failed': 0,
                'active_gestures': 0
            }
            print("✓ 手势统计信息已重置")
        except Exception as e:
            print(f"✗ 手势统计信息重置失败: {e}")
            
    def get_active_gestures(self) -> Dict[int, Dict[str, Any]]:
        """
        获取活动手势
        
        Returns:
            活动手势字典
        """
        return self.active_gestures.copy()
        
    def get_touch_points(self) -> Dict[int, Dict[str, Any]]:
        """
        获取触摸点信息
        
        Returns:
            触摸点字典
        """
        return self.touch_points.copy()