"""
语音识别器模块
负责实时语音识别功能
"""

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

class SpeechRecognizer:
    """
    语音识别器
    负责实时语音识别功能
    """
    
    def __init__(self, plugin):
        """
        初始化语音识别器
        
        Args:
            plugin: 语音控制插件实例
        """
        self.plugin = plugin
        self.enabled = False
        self.initialized = False
        
        # 音频输入配置
        self.audio_config = {
            'sample_rate': 16000,
            'channels': 1,
            'format': 'int16',
            'chunk_size': 1024,
            'buffer_size': 4096
        }
        
        # 识别配置
        self.recognition_config = {
            'language': 'zh-CN',
            'enable_keyword_spotting': True,
            'enable_continuous_recognition': True,
            'silence_threshold': 0.01,
            'speech_threshold': 0.02,
            'silence_duration': 1.0,
            'max_recording_duration': 10.0
        }
        
        # 音频缓冲区
        self.audio_buffer = queue.Queue(maxsize=100)
        self.processed_buffer = queue.Queue(maxsize=10)
        
        # 识别状态
        self.recognition_state = {
            'is_recording': False,
            'is_processing': False,
            'is_speech_detected': False,
            'last_speech_time': 0.0,
            'recording_start_time': 0.0,
            'audio_level': 0.0
        }
        
        # 麦克风管理
        self.microphone = None
        self.audio_stream = None
        
        # 线程管理
        self.recording_thread = None
        self.processing_thread = None
        self.running = False
        
        # 统计信息
        self.stats = {
            'audio_chunks_processed': 0,
            'speech_segments_detected': 0,
            'recognition_attempts': 0,
            'successful_recognitions': 0,
            'failed_recognitions': 0,
            'processing_time_total': 0.0
        }
        
        # 回调函数
        self.recognition_callbacks = {
            'audio_chunk_received': [],
            'speech_detected': [],
            'silence_detected': [],
            'recognition_result': [],
            'recognition_error': []
        }
        
        # 时间戳记录
        self.last_processing_time = 0.0
        self.last_recognition_time = 0.0
        
        print("✓ 语音识别器已创建")
        
    def initialize(self) -> bool:
        """
        初始化语音识别器
        
        Returns:
            是否初始化成功
        """
        try:
            # 初始化音频输入设备
            self._initialize_audio_input()
            
            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.recording_thread = threading.Thread(target=self._recording_loop, daemon=True)
            self.recording_thread.start()
            
            # 启动处理线程
            self.processing_thread = threading.Thread(target=self._processing_loop, daemon=True)
            self.processing_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.recording_thread and self.recording_thread.is_alive():
                self.recording_thread.join(timeout=2.0)
                
            if self.processing_thread and self.processing_thread.is_alive():
                self.processing_thread.join(timeout=2.0)
                
            # 停止音频流
            self._stop_audio_stream()
                
            print("✓ 语音识别器已禁用")
            
        except Exception as e:
            print(f"✗ 语音识别器禁用失败: {e}")
            import traceback
            traceback.print_exc()
            
    def finalize(self):
        """清理语音识别器资源"""
        try:
            self.disable()
            self.recognition_callbacks.clear()
            
            # 清理音频缓冲区
            while not self.audio_buffer.empty():
                try:
                    self.audio_buffer.get_nowait()
                except queue.Empty:
                    break
                    
            while not self.processed_buffer.empty():
                try:
                    self.processed_buffer.get_nowait()
                except queue.Empty:
                    break
                    
            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.last_processing_time = current_time
            
        except Exception as e:
            print(f"✗ 语音识别器更新失败: {e}")
            import traceback
            traceback.print_exc()
            
    def _initialize_audio_input(self):
        """初始化音频输入设备"""
        try:
            # 这里应该初始化实际的音频输入设备
            # 由于这是一个模拟实现，我们只打印信息
            print("✓ 音频输入设备初始化完成")
            print(f"  采样率: {self.audio_config['sample_rate']} Hz")
            print(f"  声道数: {self.audio_config['channels']}")
            print(f"  格式: {self.audio_config['format']}")
            
        except Exception as e:
            print(f"✗ 音频输入设备初始化失败: {e}")
            
    def _start_audio_stream(self) -> bool:
        """
        启动音频流
        
        Returns:
            是否启动成功
        """
        try:
            # 这里应该启动实际的音频流
            # 由于这是一个模拟实现，我们只设置状态
            self.audio_stream = "simulated_audio_stream"
            print("✓ 音频流已启动")
            return True
        except Exception as e:
            print(f"✗ 音频流启动失败: {e}")
            return False
            
    def _stop_audio_stream(self):
        """停止音频流"""
        try:
            # 这里应该停止实际的音频流
            self.audio_stream = None
            print("✓ 音频流已停止")
        except Exception as e:
            print(f"✗ 音频流停止失败: {e}")
            
    def _recording_loop(self):
        """录音循环线程"""
        try:
            # 启动音频流
            if not self._start_audio_stream():
                return
                
            chunk_duration = self.audio_config['chunk_size'] / self.audio_config['sample_rate']
            
            while self.running and self.enabled:
                try:
                    # 模拟读取音频数据
                    audio_chunk = self._read_audio_chunk()
                    if audio_chunk is not None:
                        # 计算音频级别
                        audio_level = self._calculate_audio_level(audio_chunk)
                        
                        # 更新状态
                        self.recognition_state['audio_level'] = audio_level
                        
                        # 检测语音活动
                        is_speech = audio_level > self.recognition_config['speech_threshold']
                        was_speech = self.recognition_state['is_speech_detected']
                        
                        # 更新语音检测状态
                        self.recognition_state['is_speech_detected'] = is_speech
                        if is_speech:
                            self.recognition_state['last_speech_time'] = time.time()
                            
                        # 触发回调
                        self._trigger_recognition_callback('audio_chunk_received', {
                            'audio_chunk': audio_chunk,
                            'audio_level': audio_level,
                            'is_speech': is_speech
                        })
                        
                        # 检测语音/静音转换
                        if is_speech and not was_speech:
                            self._trigger_recognition_callback('speech_detected', {
                                'audio_level': audio_level
                            })
                        elif not is_speech and was_speech:
                            self._trigger_recognition_callback('silence_detected', {
                                'audio_level': audio_level
                            })
                        
                        # 添加到缓冲区
                        try:
                            self.audio_buffer.put_nowait({
                                'data': audio_chunk,
                                'level': audio_level,
                                'timestamp': time.time()
                            })
                            self.stats['audio_chunks_processed'] += 1
                        except queue.Full:
                            # 缓冲区满，丢弃最旧的数据
                            try:
                                self.audio_buffer.get_nowait()
                                self.audio_buffer.put_nowait({
                                    'data': audio_chunk,
                                    'level': audio_level,
                                    'timestamp': time.time()
                                })
                            except queue.Empty:
                                pass
                                
                    # 控制录音频率
                    time.sleep(chunk_duration)
                    
                except Exception as e:
                    print(f"✗ 录音循环错误: {e}")
                    time.sleep(0.1)
                    
        except Exception as e:
            print(f"✗ 录音循环失败: {e}")
            
    def _processing_loop(self):
        """处理循环线程"""
        try:
            while self.running and self.enabled:
                try:
                    # 从缓冲区获取音频数据
                    if not self.audio_buffer.empty():
                        audio_data = self.audio_buffer.get_nowait()
                        self._process_audio_chunk(audio_data)
                        
                    # 控制处理频率
                    time.sleep(0.01)
                    
                except queue.Empty:
                    time.sleep(0.01)
                except Exception as e:
                    print(f"✗ 处理循环错误: {e}")
                    time.sleep(0.1)
                    
        except Exception as e:
            print(f"✗ 处理循环失败: {e}")
            
    def _read_audio_chunk(self) -> Optional[bytes]:
        """
        读取音频块
        
        Returns:
            音频数据或None
        """
        try:
            # 模拟生成音频数据
            import random
            import struct
            
            chunk_size = self.audio_config['chunk_size']
            audio_data = bytearray()
            
            for _ in range(chunk_size):
                # 生成模拟的音频样本
                sample = int(random.randint(-32768, 32767) * 0.1)
                audio_data.extend(struct.pack('<h', sample))
                
            return bytes(audio_data)
        except Exception as e:
            print(f"✗ 音频块读取失败: {e}")
            return None
            
    def _calculate_audio_level(self, audio_chunk: bytes) -> float:
        """
        计算音频级别
        
        Args:
            audio_chunk: 音频数据块
            
        Returns:
            音频级别(0.0-1.0)
        """
        try:
            import struct
            
            # 解析音频数据
            samples = struct.unpack(f'<{len(audio_chunk)//2}h', audio_chunk)
            
            # 计算RMS
            if len(samples) > 0:
                rms = math.sqrt(sum(sample**2 for sample in samples) / len(samples))
                # 归一化到0-1范围(假设16位音频)
                level = rms / 32768.0
                return min(1.0, level)
            else:
                return 0.0
                
        except Exception as e:
            print(f"✗ 音频级别计算失败: {e}")
            return 0.0
            
    def _process_audio_chunk(self, audio_data: Dict[str, Any]):
        """
        处理音频块
        
        Args:
            audio_data: 音频数据字典
        """
        try:
            start_time = time.time()
            
            # 模拟语音识别处理
            processing_result = self._simulate_recognition(audio_data)
            
            if processing_result:
                # 添加到处理结果缓冲区
                try:
                    self.processed_buffer.put_nowait(processing_result)
                except queue.Full:
                    try:
                        self.processed_buffer.get_nowait()
                        self.processed_buffer.put_nowait(processing_result)
                    except queue.Empty:
                        pass
                        
                # 触发识别结果回调
                self._trigger_recognition_callback('recognition_result', processing_result)
                
                # 传递给语音管理器处理
                if self.plugin.voice_manager:
                    self.plugin.voice_manager.process_speech(
                        processing_result['text'],
                        processing_result['confidence']
                    )
                    
                self.stats['successful_recognitions'] += 1
                
            # 更新统计信息
            processing_time = time.time() - start_time
            self.stats['processing_time_total'] += processing_time
            self.stats['recognition_attempts'] += 1
            self.last_recognition_time = time.time()
            
        except Exception as e:
            print(f"✗ 音频块处理失败: {e}")
            self.stats['failed_recognitions'] += 1
            
            # 触发错误回调
            self._trigger_recognition_callback('recognition_error', {
                'error': str(e),
                'timestamp': time.time()
            })
            
    def _simulate_recognition(self, audio_data: Dict[str, Any]) -> Optional[Dict[str, Any]]:
        """
        模拟语音识别
        
        Args:
            audio_data: 音频数据
            
        Returns:
            识别结果或None
        """
        try:
            # 基于音频级别和时间模拟识别结果
            audio_level = audio_data.get('level', 0.0)
            timestamp = audio_data.get('timestamp', time.time())
            
            # 只有在音频级别足够高时才模拟识别
            if audio_level > self.recognition_config['speech_threshold']:
                import random
                
                # 模拟识别文本
                sample_texts = [
                    "前进", "后退", "左转", "右转", "停止",
                    "打开灯光", "关闭灯光", "增加音量", "减少音量",
                    "播放音乐", "暂停播放", "下一首", "上一首",
                    "你好", "谢谢", "再见", "帮助"
                ]
                
                # 根据音频级别设置置信度
                confidence = min(1.0, audio_level * 2)  # 简单映射
                
                # 有一定概率生成识别结果
                if random.random() < 0.1:  # 10%概率
                    text = random.choice(sample_texts)
                    return {
                        'text': text,
                        'confidence': confidence,
                        'timestamp': timestamp,
                        'audio_level': audio_level
                    }
                    
            return None
            
        except Exception as e:
            print(f"✗ 识别模拟失败: {e}")
            return None
            
    def start_recording(self) -> bool:
        """
        开始录音
        
        Returns:
            是否开始成功
        """
        try:
            if not self.enabled:
                print("✗ 语音识别器未启用")
                return False
                
            self.recognition_state['is_recording'] = True
            self.recognition_state['recording_start_time'] = time.time()
            
            print("✓ 录音已开始")
            return True
            
        except Exception as e:
            print(f"✗ 录音开始失败: {e}")
            return False
            
    def stop_recording(self) -> bool:
        """
        停止录音
        
        Returns:
            是否停止成功
        """
        try:
            self.recognition_state['is_recording'] = False
            print("✓ 录音已停止")
            return True
            
        except Exception as e:
            print(f"✗ 录音停止失败: {e}")
            return False
            
    def is_recording(self) -> bool:
        """
        检查是否正在录音
        
        Returns:
            是否正在录音
        """
        return self.recognition_state['is_recording']
        
    def is_speech_detected(self) -> bool:
        """
        检查是否检测到语音
        
        Returns:
            是否检测到语音
        """
        return self.recognition_state['is_speech_detected']
        
    def get_audio_level(self) -> float:
        """
        获取当前音频级别
        
        Returns:
            音频级别(0.0-1.0)
        """
        return self.recognition_state['audio_level']
        
    def set_recognition_config(self, config: Dict[str, Any]) -> bool:
        """
        设置识别配置
        
        Args:
            config: 配置字典
            
        Returns:
            是否设置成功
        """
        try:
            self.recognition_config.update(config)
            print(f"✓ 识别配置已更新: {self.recognition_config}")
            return True
        except Exception as e:
            print(f"✗ 识别配置设置失败: {e}")
            return False
            
    def get_recognition_config(self) -> Dict[str, Any]:
        """
        获取识别配置
        
        Returns:
            配置字典
        """
        return self.recognition_config.copy()
        
    def set_audio_config(self, config: Dict[str, Any]) -> bool:
        """
        设置音频配置
        
        Args:
            config: 配置字典
            
        Returns:
            是否设置成功
        """
        try:
            self.audio_config.update(config)
            print(f"✓ 音频配置已更新: {self.audio_config}")
            return True
        except Exception as e:
            print(f"✗ 音频配置设置失败: {e}")
            return False
            
    def get_audio_config(self) -> Dict[str, Any]:
        """
        获取音频配置
        
        Returns:
            配置字典
        """
        return self.audio_config.copy()
        
    def _trigger_recognition_callback(self, callback_type: str, data: Dict[str, Any]):
        """
        触发识别回调
        
        Args:
            callback_type: 回调类型
            data: 回调数据
        """
        try:
            if callback_type in self.recognition_callbacks:
                for callback in self.recognition_callbacks[callback_type]:
                    try:
                        callback(data)
                    except Exception as e:
                        print(f"✗ 识别回调执行失败: {e}")
        except Exception as e:
            print(f"✗ 识别回调触发失败: {e}")
            
    def register_recognition_callback(self, callback_type: str, callback: callable):
        """
        注册识别回调
        
        Args:
            callback_type: 回调类型
            callback: 回调函数
        """
        try:
            if callback_type in self.recognition_callbacks:
                self.recognition_callbacks[callback_type].append(callback)
                print(f"✓ 识别回调已注册: {callback_type}")
            else:
                print(f"✗ 无效的回调类型: {callback_type}")
        except Exception as e:
            print(f"✗ 识别回调注册失败: {e}")
            
    def unregister_recognition_callback(self, callback_type: str, callback: callable):
        """
        注销识别回调
        
        Args:
            callback_type: 回调类型
            callback: 回调函数
        """
        try:
            if callback_type in self.recognition_callbacks:
                if callback in self.recognition_callbacks[callback_type]:
                    self.recognition_callbacks[callback_type].remove(callback)
                    print(f"✓ 识别回调已注销: {callback_type}")
        except Exception as e:
            print(f"✗ 识别回调注销失败: {e}")
            
    def get_stats(self) -> Dict[str, Any]:
        """
        获取统计信息
        
        Returns:
            统计信息字典
        """
        stats = self.stats.copy()
        if self.stats['successful_recognitions'] > 0:
            stats['average_processing_time'] = (
                self.stats['processing_time_total'] / self.stats['successful_recognitions']
            )
        else:
            stats['average_processing_time'] = 0.0
        return stats
        
    def reset_stats(self):
        """重置统计信息"""
        try:
            self.stats = {
                'audio_chunks_processed': 0,
                'speech_segments_detected': 0,
                'recognition_attempts': 0,
                'successful_recognitions': 0,
                'failed_recognitions': 0,
                'processing_time_total': 0.0
            }
            print("✓ 语音识别器统计信息已重置")
        except Exception as e:
            print(f"✗ 语音识别器统计信息重置失败: {e}")