"""
语音合成器模块
负责文字转语音功能
"""

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

class SpeechSynthesizer:
    """
    语音合成器
    负责文字转语音功能
    """
    
    def __init__(self, plugin):
        """
        初始化语音合成器
        
        Args:
            plugin: 语音控制插件实例
        """
        self.plugin = plugin
        self.enabled = False
        self.initialized = False
        
        # 音频输出配置
        self.audio_config = {
            'sample_rate': 22050,
            'channels': 1,
            'format': 'int16',
            'buffer_size': 4096
        }
        
        # 合成配置
        self.synthesis_config = {
            'language': 'zh-CN',
            'voice': 'default',
            'speed': 1.0,
            'volume': 1.0,
            'pitch': 1.0,
            'enable_ssml': False,
            'output_device': 'default'
        }
        
        # 合成队列
        self.synthesis_queue = queue.Queue(maxsize=10)
        self.playback_queue = queue.Queue(maxsize=5)
        
        # 合成状态
        self.synthesis_state = {
            'is_synthesizing': False,
            'is_playing': False,
            'current_text': '',
            'progress': 0.0,
            'last_synthesis_time': 0.0
        }
        
        # 音频输出管理
        self.audio_output = None
        self.audio_stream = None
        
        # 线程管理
        self.synthesis_thread = None
        self.playback_thread = None
        self.running = False
        
        # 语音库
        self.voice_library = {}
        
        # 统计信息
        self.stats = {
            'texts_synthesized': 0,
            'synthesis_attempts': 0,
            'successful_syntheses': 0,
            'failed_syntheses': 0,
            'playback_count': 0,
            'synthesis_time_total': 0.0
        }
        
        # 回调函数
        self.synthesis_callbacks = {
            'synthesis_started': [],
            'synthesis_completed': [],
            'synthesis_error': [],
            'playback_started': [],
            'playback_completed': [],
            'playback_error': []
        }
        
        # 时间戳记录
        self.last_synthesis_time = 0.0
        self.last_playback_time = 0.0
        
        print("✓ 语音合成器已创建")
        
    def initialize(self) -> bool:
        """
        初始化语音合成器
        
        Returns:
            是否初始化成功
        """
        try:
            # 初始化音频输出设备
            self._initialize_audio_output()
            
            # 初始化语音库
            self._initialize_voice_library()
            
            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.synthesis_thread = threading.Thread(target=self._synthesis_loop, daemon=True)
            self.synthesis_thread.start()
            
            # 启动播放线程
            self.playback_thread = threading.Thread(target=self._playback_loop, daemon=True)
            self.playback_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.synthesis_thread and self.synthesis_thread.is_alive():
                self.synthesis_thread.join(timeout=2.0)
                
            if self.playback_thread and self.playback_thread.is_alive():
                self.playback_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.synthesis_callbacks.clear()
            
            # 清理队列
            while not self.synthesis_queue.empty():
                try:
                    self.synthesis_queue.get_nowait()
                except queue.Empty:
                    break
                    
            while not self.playback_queue.empty():
                try:
                    self.playback_queue.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_synthesis_time = current_time
            
        except Exception as e:
            print(f"✗ 语音合成器更新失败: {e}")
            import traceback
            traceback.print_exc()
            
    def _initialize_audio_output(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 _initialize_voice_library(self):
        """初始化语音库"""
        try:
            # 创建模拟语音库
            self.voice_library = {
                'default': {
                    'name': '默认语音',
                    'language': 'zh-CN',
                    'gender': 'neutral',
                    'description': '系统默认语音'
                },
                'male': {
                    'name': '男声',
                    'language': 'zh-CN',
                    'gender': 'male',
                    'description': '标准男声'
                },
                'female': {
                    'name': '女声',
                    'language': 'zh-CN',
                    'gender': 'female',
                    'description': '标准女声'
                },
                'child': {
                    'name': '童声',
                    'language': 'zh-CN',
                    'gender': 'child',
                    'description': '儿童语音'
                }
            }
            
            print("✓ 语音库初始化完成")
            print(f"  可用语音: {list(self.voice_library.keys())}")
            
        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 _synthesis_loop(self):
        """合成循环线程"""
        try:
            # 启动音频流
            if not self._start_audio_stream():
                return
                
            while self.running and self.enabled:
                try:
                    # 从队列获取合成任务
                    if not self.synthesis_queue.empty():
                        synthesis_task = self.synthesis_queue.get_nowait()
                        self._process_synthesis_task(synthesis_task)
                        
                    # 控制处理频率
                    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 _playback_loop(self):
        """播放循环线程"""
        try:
            while self.running and self.enabled:
                try:
                    # 从队列获取播放任务
                    if not self.playback_queue.empty():
                        playback_task = self.playback_queue.get_nowait()
                        self._process_playback_task(playback_task)
                        
                    # 控制播放频率
                    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 _process_synthesis_task(self, task: Dict[str, Any]):
        """
        处理合成任务
        
        Args:
            task: 合成任务字典
        """
        try:
            start_time = time.time()
            
            text = task.get('text', '')
            speed = task.get('speed', 1.0)
            volume = task.get('volume', 1.0)
            blocking = task.get('blocking', False)
            
            # 更新合成状态
            self.synthesis_state['is_synthesizing'] = True
            self.synthesis_state['current_text'] = text
            self.synthesis_state['last_synthesis_time'] = start_time
            
            # 触发合成开始回调
            self._trigger_synthesis_callback('synthesis_started', {
                'text': text,
                'speed': speed,
                'volume': volume
            })
            
            # 模拟语音合成过程
            synthesized_audio = self._synthesize_text(text, speed, volume)
            
            if synthesized_audio is not None:
                # 添加到播放队列
                try:
                    self.playback_queue.put_nowait({
                        'audio': synthesized_audio,
                        'text': text,
                        'blocking': blocking,
                        'timestamp': time.time()
                    })
                    
                    # 更新统计信息
                    self.stats['successful_syntheses'] += 1
                    
                    # 触发合成完成回调
                    self._trigger_synthesis_callback('synthesis_completed', {
                        'text': text,
                        'audio_length': len(synthesized_audio),
                        'synthesis_time': time.time() - start_time
                    })
                    
                except queue.Full:
                    print("✗ 播放队列已满，丢弃合成结果")
                    self.stats['failed_syntheses'] += 1
                    
                    # 触发合成错误回调
                    self._trigger_synthesis_callback('synthesis_error', {
                        'text': text,
                        'error': 'Playback queue full'
                    })
            else:
                self.stats['failed_syntheses'] += 1
                
                # 触发合成错误回调
                self._trigger_synthesis_callback('synthesis_error', {
                    'text': text,
                    'error': 'Synthesis failed'
                })
                
            # 更新统计信息
            synthesis_time = time.time() - start_time
            self.stats['synthesis_time_total'] += synthesis_time
            self.stats['synthesis_attempts'] += 1
            self.last_synthesis_time = time.time()
            
        except Exception as e:
            print(f"✗ 合成任务处理失败: {e}")
            self.stats['failed_syntheses'] += 1
            
        finally:
            # 重置合成状态
            self.synthesis_state['is_synthesizing'] = False
            self.synthesis_state['progress'] = 0.0
            
    def _process_playback_task(self, task: Dict[str, Any]):
        """
        处理播放任务
        
        Args:
            task: 播放任务字典
        """
        try:
            audio_data = task.get('audio', b'')
            text = task.get('text', '')
            blocking = task.get('blocking', False)
            
            # 更新播放状态
            self.synthesis_state['is_playing'] = True
            self.synthesis_state['current_text'] = text
            
            # 触发播放开始回调
            self._trigger_synthesis_callback('playback_started', {
                'text': text,
                'audio_length': len(audio_data)
            })
            
            # 模拟音频播放
            playback_success = self._play_audio(audio_data, blocking)
            
            if playback_success:
                self.stats['playback_count'] += 1
                
                # 触发播放完成回调
                self._trigger_synthesis_callback('playback_completed', {
                    'text': text,
                    'playback_time': len(audio_data) / self.audio_config['sample_rate']
                })
            else:
                # 触发播放错误回调
                self._trigger_synthesis_callback('playback_error', {
                    'text': text,
                    'error': 'Playback failed'
                })
                
            self.last_playback_time = time.time()
            
        except Exception as e:
            print(f"✗ 播放任务处理失败: {e}")
            
            # 触发播放错误回调
            self._trigger_synthesis_callback('playback_error', {
                'text': task.get('text', ''),
                'error': str(e)
            })
            
        finally:
            # 重置播放状态
            self.synthesis_state['is_playing'] = False
            
    def _synthesize_text(self, text: str, speed: float, volume: float) -> Optional[bytes]:
        """
        合成文本为音频
        
        Args:
            text: 要合成的文本
            speed: 语速
            volume: 音量
            
        Returns:
            音频数据或None
        """
        try:
            # 模拟文本到语音的转换过程
            import random
            import struct
            
            # 根据文本长度计算音频长度
            char_count = len(text)
            # 假设每个字符大约需要0.1秒
            duration_seconds = char_count * 0.1 * (1.0 / speed)
            
            # 计算样本数
            sample_rate = self.audio_config['sample_rate']
            total_samples = int(duration_seconds * sample_rate)
            
            # 生成模拟的音频数据
            audio_data = bytearray()
            
            # 生成简单的正弦波作为语音模拟
            frequency = 440.0  # A音
            for i in range(total_samples):
                # 添加一些变化使声音更自然
                t = i / sample_rate
                wave_value = math.sin(2 * math.pi * frequency * t)
                
                # 添加谐波
                wave_value += 0.3 * math.sin(2 * math.pi * frequency * 2 * t)
                wave_value += 0.2 * math.sin(2 * math.pi * frequency * 3 * t)
                
                # 应用音量
                wave_value *= volume
                
                # 转换为16位整数
                sample = int(wave_value * 32767 * 0.3)  # 降低整体音量
                audio_data.extend(struct.pack('<h', sample))
                
            return bytes(audio_data)
            
        except Exception as e:
            print(f"✗ 文本合成失败: {e}")
            return None
            
    def _play_audio(self, audio_data: bytes, blocking: bool = False) -> bool:
        """
        播放音频数据
        
        Args:
            audio_data: 音频数据
            blocking: 是否阻塞等待播放完成
            
        Returns:
            是否播放成功
        """
        try:
            # 模拟音频播放
            import time
            import math
            
            # 计算播放时间
            sample_count = len(audio_data) // 2  # 16位音频
            duration = sample_count / self.audio_config['sample_rate']
            
            print(f"✓ 播放音频: {duration:.2f}秒")
            
            # 如果是阻塞模式，等待播放完成
            if blocking:
                time.sleep(duration)
                
            return True
            
        except Exception as e:
            print(f"✗ 音频播放失败: {e}")
            return False
            
    def synthesize_speech(self, text: str, blocking: bool = False, 
                         speed: float = 1.0, volume: float = 1.0) -> bool:
        """
        合成并播放语音
        
        Args:
            text: 要合成的文本
            blocking: 是否阻塞等待播放完成
            speed: 语速(0.5-2.0)
            volume: 音量(0.0-1.0)
            
        Returns:
            是否合成成功
        """
        try:
            if not self.enabled:
                print("✗ 语音合成器未启用")
                return False
                
            # 限制参数范围
            speed = max(0.5, min(2.0, speed))
            volume = max(0.0, min(1.0, volume))
            
            # 创建合成任务
            synthesis_task = {
                'text': text,
                'speed': speed,
                'volume': volume,
                'blocking': blocking,
                'timestamp': time.time()
            }
            
            # 添加到合成队列
            try:
                self.synthesis_queue.put_nowait(synthesis_task)
                self.stats['texts_synthesized'] += 1
                return True
            except queue.Full:
                print("✗ 合成队列已满")
                return False
                
        except Exception as e:
            print(f"✗ 语音合成失败: {e}")
            self.stats['failed_syntheses'] += 1
            return False
            
    def stop_speech(self) -> bool:
        """
        停止当前语音播放
        
        Returns:
            是否停止成功
        """
        try:
            # 清空播放队列
            while not self.playback_queue.empty():
                try:
                    self.playback_queue.get_nowait()
                except queue.Empty:
                    break
                    
            # 重置播放状态
            self.synthesis_state['is_playing'] = False
            self.synthesis_state['current_text'] = ''
            
            print("✓ 语音播放已停止")
            return True
            
        except Exception as e:
            print(f"✗ 语音播放停止失败: {e}")
            return False
            
    def get_available_voices(self) -> Dict[str, Dict[str, Any]]:
        """
        获取可用语音列表
        
        Returns:
            语音信息字典
        """
        return self.voice_library.copy()
        
    def set_voice(self, voice_name: str) -> bool:
        """
        设置语音
        
        Args:
            voice_name: 语音名称
            
        Returns:
            是否设置成功
        """
        try:
            if voice_name in self.voice_library:
                self.synthesis_config['voice'] = voice_name
                print(f"✓ 语音已设置为: {voice_name}")
                return True
            else:
                print(f"✗ 语音不存在: {voice_name}")
                return False
        except Exception as e:
            print(f"✗ 语音设置失败: {e}")
            return False
            
    def set_synthesis_config(self, config: Dict[str, Any]) -> bool:
        """
        设置合成配置
        
        Args:
            config: 配置字典
            
        Returns:
            是否设置成功
        """
        try:
            self.synthesis_config.update(config)
            print(f"✓ 合成配置已更新: {self.synthesis_config}")
            return True
        except Exception as e:
            print(f"✗ 合成配置设置失败: {e}")
            return False
            
    def get_synthesis_config(self) -> Dict[str, Any]:
        """
        获取合成配置
        
        Returns:
            配置字典
        """
        return self.synthesis_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 is_speaking(self) -> bool:
        """
        检查是否正在播放语音
        
        Returns:
            是否正在播放语音
        """
        return self.synthesis_state['is_playing']
        
    def is_synthesizing(self) -> bool:
        """
        检查是否正在合成语音
        
        Returns:
            是否正在合成语音
        """
        return self.synthesis_state['is_synthesizing']
        
    def get_synthesis_progress(self) -> float:
        """
        获取合成进度
        
        Returns:
            合成进度(0.0-1.0)
        """
        return self.synthesis_state['progress']
        
    def _trigger_synthesis_callback(self, callback_type: str, data: Dict[str, Any]):
        """
        触发合成回调
        
        Args:
            callback_type: 回调类型
            data: 回调数据
        """
        try:
            if callback_type in self.synthesis_callbacks:
                for callback in self.synthesis_callbacks[callback_type]:
                    try:
                        callback(data)
                    except Exception as e:
                        print(f"✗ 合成回调执行失败: {e}")
        except Exception as e:
            print(f"✗ 合成回调触发失败: {e}")
            
    def register_synthesis_callback(self, callback_type: str, callback: callable):
        """
        注册合成回调
        
        Args:
            callback_type: 回调类型
            callback: 回调函数
        """
        try:
            if callback_type in self.synthesis_callbacks:
                self.synthesis_callbacks[callback_type].append(callback)
                print(f"✓ 合成回调已注册: {callback_type}")
            else:
                print(f"✗ 无效的回调类型: {callback_type}")
        except Exception as e:
            print(f"✗ 合成回调注册失败: {e}")
            
    def unregister_synthesis_callback(self, callback_type: str, callback: callable):
        """
        注销合成回调
        
        Args:
            callback_type: 回调类型
            callback: 回调函数
        """
        try:
            if callback_type in self.synthesis_callbacks:
                if callback in self.synthesis_callbacks[callback_type]:
                    self.synthesis_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_syntheses'] > 0:
            stats['average_synthesis_time'] = (
                self.stats['synthesis_time_total'] / self.stats['successful_syntheses']
            )
        else:
            stats['average_synthesis_time'] = 0.0
        return stats
        
    def reset_stats(self):
        """重置统计信息"""
        try:
            self.stats = {
                'texts_synthesized': 0,
                'synthesis_attempts': 0,
                'successful_syntheses': 0,
                'failed_syntheses': 0,
                'playback_count': 0,
                'synthesis_time_total': 0.0
            }
            print("✓ 语音合成器统计信息已重置")
        except Exception as e:
            print(f"✗ 语音合成器统计信息重置失败: {e}")

# 导入math模块用于正弦波计算
import math