"""
音频源管理器
管理3D空间音效的音频源创建、播放和控制
"""

import uuid
from typing import Dict, Optional, Any, Tuple
from panda3d.core import AudioSound, NodePath
import os

class AudioSourceManager:
    """
    音频源管理器
    管理3D空间音效的音频源创建、播放和控制
    """
    
    def __init__(self, plugin):
        """
        初始化音频源管理器
        
        Args:
            plugin: 3D音频插件实例
        """
        self.plugin = plugin
        self.audio_sources: Dict[str, Dict[str, Any]] = {}
        self.stats = {
            'total_created': 0,
            'currently_playing': 0,
            'total_played': 0
        }
        
    def create_3d_sound(self, filepath: str, position: Tuple[float, float, float] = (0, 0, 0),
                       loop: bool = False, volume: float = 1.0) -> Optional[str]:
        """
        创建3D音效
        
        Args:
            filepath: 音频文件路径
            position: 音源位置 (x, y, z)
            loop: 是否循环播放
            volume: 音量 (0.0-1.0)
            
        Returns:
            音源ID，如果创建失败则返回None
        """
        try:
            # 检查文件是否存在
            if not os.path.exists(filepath):
                print(f"✗ 音频文件不存在: {filepath}")
                return None
                
            # 创建音源节点
            sound_node = NodePath(f"sound_{uuid.uuid4()}")
            sound_node.reparentTo(self.plugin.plugin_manager.world.render)
            sound_node.setPos(position[0], position[1], position[2])
            
            # 加载音频文件
            audio_manager = self.plugin.audio_manager
            sound = audio_manager.loadSfx(filepath)
            
            if not sound:
                print(f"✗ 无法加载音频文件: {filepath}")
                sound_node.removeNode()
                return None
                
            # 设置音频属性
            sound.setLoop(loop)
            sound.setVolume(volume)
            
            # 将音源附加到节点
            sound_node.setSound(sound)
            
            # 生成唯一ID
            sound_id = str(uuid.uuid4())
            
            # 存储音源信息
            self.audio_sources[sound_id] = {
                'sound': sound,
                'node': sound_node,
                'type': '3d',
                'loop': loop,
                'volume': volume,
                'position': position,
                'filepath': filepath
            }
            
            # 更新统计信息
            self.stats['total_created'] += 1
            
            print(f"✓ 3D音效创建成功: {sound_id} ({filepath})")
            return sound_id
            
        except Exception as e:
            print(f"✗ 创建3D音效失败: {e}")
            return None
            
    def create_2d_sound(self, filepath: str, loop: bool = False, volume: float = 1.0) -> Optional[str]:
        """
        创建2D音效
        
        Args:
            filepath: 音频文件路径
            loop: 是否循环播放
            volume: 音量 (0.0-1.0)
            
        Returns:
            音源ID，如果创建失败则返回None
        """
        try:
            # 检查文件是否存在
            if not os.path.exists(filepath):
                print(f"✗ 音频文件不存在: {filepath}")
                return None
                
            # 加载音频文件
            audio_manager = self.plugin.audio_manager
            sound = audio_manager.loadSfx(filepath)
            
            if not sound:
                print(f"✗ 无法加载音频文件: {filepath}")
                return None
                
            # 设置音频属性
            sound.setLoop(loop)
            sound.setVolume(volume)
            
            # 生成唯一ID
            sound_id = str(uuid.uuid4())
            
            # 存储音源信息
            self.audio_sources[sound_id] = {
                'sound': sound,
                'node': None,
                'type': '2d',
                'loop': loop,
                'volume': volume,
                'position': (0, 0, 0),
                'filepath': filepath
            }
            
            # 更新统计信息
            self.stats['total_created'] += 1
            
            print(f"✓ 2D音效创建成功: {sound_id} ({filepath})")
            return sound_id
            
        except Exception as e:
            print(f"✗ 创建2D音效失败: {e}")
            return None
            
    def play_sound(self, sound_id: str) -> bool:
        """
        播放音效
        
        Args:
            sound_id: 音源ID
            
        Returns:
            是否播放成功
        """
        if sound_id not in self.audio_sources:
            print(f"✗ 音源不存在: {sound_id}")
            return False
            
        try:
            sound_info = self.audio_sources[sound_id]
            sound = sound_info['sound']
            
            # 检查音效状态
            if sound.status() == AudioSound.PLAYING:
                print(f"⚠ 音效已在播放中: {sound_id}")
                return True
                
            # 播放音效
            sound.play()
            
            # 更新统计信息
            self.stats['currently_playing'] += 1
            self.stats['total_played'] += 1
            
            print(f"✓ 音效开始播放: {sound_id}")
            return True
            
        except Exception as e:
            print(f"✗ 播放音效失败: {e}")
            return False
            
    def stop_sound(self, sound_id: str) -> bool:
        """
        停止音效
        
        Args:
            sound_id: 音源ID
            
        Returns:
            是否停止成功
        """
        if sound_id not in self.audio_sources:
            print(f"✗ 音源不存在: {sound_id}")
            return False
            
        try:
            sound_info = self.audio_sources[sound_id]
            sound = sound_info['sound']
            
            # 停止音效
            sound.stop()
            
            # 更新统计信息
            if sound.status() == AudioSound.PLAYING:
                self.stats['currently_playing'] -= 1
            
            print(f"✓ 音效已停止: {sound_id}")
            return True
            
        except Exception as e:
            print(f"✗ 停止音效失败: {e}")
            return False
            
    def pause_sound(self, sound_id: str) -> bool:
        """
        暂停音效
        
        Args:
            sound_id: 音源ID
            
        Returns:
            是否暂停成功
        """
        if sound_id not in self.audio_sources:
            print(f"✗ 音源不存在: {sound_id}")
            return False
            
        try:
            sound_info = self.audio_sources[sound_id]
            sound = sound_info['sound']
            
            # 暂停音效
            sound.setActive(False)
            
            # 更新统计信息
            if sound.status() == AudioSound.PLAYING:
                self.stats['currently_playing'] -= 1
            
            print(f"✓ 音效已暂停: {sound_id}")
            return True
            
        except Exception as e:
            print(f"✗ 暂停音效失败: {e}")
            return False
            
    def resume_sound(self, sound_id: str) -> bool:
        """
        恢复音效
        
        Args:
            sound_id: 音源ID
            
        Returns:
            是否恢复成功
        """
        if sound_id not in self.audio_sources:
            print(f"✗ 音源不存在: {sound_id}")
            return False
            
        try:
            sound_info = self.audio_sources[sound_id]
            sound = sound_info['sound']
            
            # 恢复音效
            sound.setActive(True)
            
            # 更新统计信息
            if sound.status() != AudioSound.PLAYING:
                self.stats['currently_playing'] += 1
            
            print(f"✓ 音效已恢复: {sound_id}")
            return True
            
        except Exception as e:
            print(f"✗ 恢复音效失败: {e}")
            return False
            
    def set_sound_position(self, sound_id: str, position: Tuple[float, float, float]) -> bool:
        """
        设置音源位置
        
        Args:
            sound_id: 音源ID
            position: 位置 (x, y, z)
            
        Returns:
            是否设置成功
        """
        if sound_id not in self.audio_sources:
            print(f"✗ 音源不存在: {sound_id}")
            return False
            
        try:
            sound_info = self.audio_sources[sound_id]
            
            # 检查是否为3D音效
            if sound_info['type'] != '3d':
                print(f"✗ 只有3D音效可以设置位置: {sound_id}")
                return False
                
            node = sound_info['node']
            node.setPos(position[0], position[1], position[2])
            sound_info['position'] = position
            
            print(f"✓ 音源位置已设置: {sound_id} -> {position}")
            return True
            
        except Exception as e:
            print(f"✗ 设置音源位置失败: {e}")
            return False
            
    def set_sound_volume(self, sound_id: str, volume: float) -> bool:
        """
        设置音源音量
        
        Args:
            sound_id: 音源ID
            volume: 音量 (0.0-1.0)
            
        Returns:
            是否设置成功
        """
        if sound_id not in self.audio_sources:
            print(f"✗ 音源不存在: {sound_id}")
            return False
            
        try:
            sound_info = self.audio_sources[sound_id]
            sound = sound_info['sound']
            
            # 限制音量范围
            volume = max(0.0, min(1.0, volume))
            
            sound.setVolume(volume)
            sound_info['volume'] = volume
            
            print(f"✓ 音源音量已设置: {sound_id} -> {volume}")
            return True
            
        except Exception as e:
            print(f"✗ 设置音源音量失败: {e}")
            return False
            
    def set_sound_loop(self, sound_id: str, loop: bool) -> bool:
        """
        设置音源循环模式
        
        Args:
            sound_id: 音源ID
            loop: 是否循环
            
        Returns:
            是否设置成功
        """
        if sound_id not in self.audio_sources:
            print(f"✗ 音源不存在: {sound_id}")
            return False
            
        try:
            sound_info = self.audio_sources[sound_id]
            sound = sound_info['sound']
            
            sound.setLoop(loop)
            sound_info['loop'] = loop
            
            print(f"✓ 音源循环模式已设置: {sound_id} -> {'循环' if loop else '单次'}")
            return True
            
        except Exception as e:
            print(f"✗ 设置音源循环模式失败: {e}")
            return False
            
    def is_sound_playing(self, sound_id: str) -> bool:
        """
        检查音效是否正在播放
        
        Args:
            sound_id: 音源ID
            
        Returns:
            是否正在播放
        """
        if sound_id not in self.audio_sources:
            return False
            
        try:
            sound_info = self.audio_sources[sound_id]
            sound = sound_info['sound']
            return sound.status() == AudioSound.PLAYING
        except Exception:
            return False
            
    def get_sound_duration(self, sound_id: str) -> float:
        """
        获取音效时长
        
        Args:
            sound_id: 音源ID
            
        Returns:
            音效时长（秒）
        """
        if sound_id not in self.audio_sources:
            return 0.0
            
        try:
            sound_info = self.audio_sources[sound_id]
            sound = sound_info['sound']
            return sound.length()
        except Exception:
            return 0.0
            
    def get_sound_position(self, sound_id: str) -> Tuple[float, float, float]:
        """
        获取音源位置
        
        Args:
            sound_id: 音源ID
            
        Returns:
            音源位置 (x, y, z)
        """
        if sound_id not in self.audio_sources:
            return (0, 0, 0)
            
        try:
            sound_info = self.audio_sources[sound_id]
            return sound_info['position']
        except Exception:
            return (0, 0, 0)
            
    def delete_sound(self, sound_id: str) -> bool:
        """
        删除音效
        
        Args:
            sound_id: 音源ID
            
        Returns:
            是否删除成功
        """
        if sound_id not in self.audio_sources:
            print(f"✗ 音源不存在: {sound_id}")
            return False
            
        try:
            sound_info = self.audio_sources[sound_id]
            
            # 停止播放
            if self.is_sound_playing(sound_id):
                self.stop_sound(sound_id)
                
            # 清理资源
            sound = sound_info['sound']
            node = sound_info['node']
            
            if node:
                node.removeNode()
                
            # 从管理器中移除
            del self.audio_sources[sound_id]
            
            print(f"✓ 音效已删除: {sound_id}")
            return True
            
        except Exception as e:
            print(f"✗ 删除音效失败: {e}")
            return False
            
    def stop_all_sounds(self):
        """停止所有音频"""
        sound_ids = list(self.audio_sources.keys())
        for sound_id in sound_ids:
            self.stop_sound(sound_id)
        print("✓ 所有音频已停止")
        
    def cleanup(self):
        """清理所有资源"""
        self.stop_all_sounds()
        self.audio_sources.clear()
        self.stats = {
            'total_created': 0,
            'currently_playing': 0,
            'total_played': 0
        }
        print("✓ 音频源管理器资源已清理")
        
    def get_stats(self) -> Dict[str, int]:
        """
        获取统计信息
        
        Returns:
            统计信息字典
        """
        return self.stats.copy()
        
    def update(self, dt: float):
        """
        更新音频源状态
        
        Args:
            dt: 时间增量
        """
        # 检查已完成播放的音效
        finished_sounds = []
        for sound_id, sound_info in self.audio_sources.items():
            sound = sound_info['sound']
            if sound.status() != AudioSound.PLAYING and sound_info['loop'] == False:
                # 检查是否是从播放状态变为停止状态
                if hasattr(sound_info, '_was_playing') and sound_info['_was_playing']:
                    self.stats['currently_playing'] -= 1
                    finished_sounds.append(sound_id)
            # 更新播放状态
            sound_info['_was_playing'] = (sound.status() == AudioSound.PLAYING)
            
        # 清理已完成的非循环音效
        for sound_id in finished_sounds:
            if sound_id in self.audio_sources:
                sound_info = self.audio_sources[sound_id]
                if not sound_info['loop']:
                    self.stats['currently_playing'] -= 1

