"""
压缩器效果处理器
实现专业的音频压缩器效果处理
"""

import uuid
import math
import numpy as np
from typing import Dict, List, Any, Optional

class CompressorProcessor:
    """
    压缩器效果处理器
    实现专业的音频压缩器效果处理
    """
    
    def __init__(self, plugin):
        """
        初始化压缩器效果处理器
        
        Args:
            plugin: 音频效果插件实例
        """
        self.plugin = plugin
        self.effects: Dict[str, Dict[str, Any]] = {}
        self.stats = {
            'total_effects': 0,
            'active_effects': 0,
            'effects_processed': 0,
            'processing_time': 0.0,
            'memory_usage': 0
        }
        self.buffer_size = plugin.buffer_size if plugin else 4096
        self.sample_rate = 44100  # 默认采样率
        
    def create_effect(self, parameters: Dict[str, Any]) -> str:
        """
        创建压缩器效果
        
        Args:
            parameters: 压缩器参数
            
        Returns:
            效果ID
        """
        try:
            # 生成唯一ID
            effect_id = str(uuid.uuid4())
            
            # 默认参数
            default_params = {
                'threshold': -20.0,    # 阈值 (dB)
                'ratio': 4.0,         # 压缩比 (例如 4:1)
                'attack': 0.01,       # 启动时间 (秒)
                'release': 0.1,       # 释放时间 (秒)
                'gain': 0.0,          # 输出增益 (dB)
                'knee': 5.0,          # 膝点 (dB)
                'makeup_gain': True,  # 自动补偿增益
                'sidechain': False,   # 侧链
                'rms_window': 0.01,   # RMS窗口时间 (秒)
                'lookahead': 0.005    # 预测时间 (秒)
            }
            
            # 合并参数
            effect_params = default_params.copy()
            effect_params.update(parameters)
            
            # 创建效果对象
            effect = {
                'id': effect_id,
                'type': 'compressor',
                'parameters': effect_params,
                'active': True,
                'buffers': {},  # 缓冲区
                'envelope': 0.0,  # 包络状态
                'gain_reduction': 0.0,  # 增益减少量
                'created_time': self._get_current_time(),
                'process_count': 0
            }
            
            # 初始化缓冲区
            self._initialize_buffers(effect)
            
            # 存储效果
            self.effects[effect_id] = effect
            
            # 更新统计信息
            self.stats['total_effects'] += 1
            self.stats['active_effects'] += 1
            
            # 在插件中注册效果
            if self.plugin:
                self.plugin.effects[effect_id] = effect.copy()
            
            print(f"✓ 压缩器效果创建成功: {effect_id}")
            return effect_id
            
        except Exception as e:
            print(f"✗ 创建压缩器效果失败: {e}")
            import traceback
            traceback.print_exc()
            return ""
            
    def _initialize_buffers(self, effect: Dict[str, Any]):
        """
        初始化缓冲区
        
        Args:
            effect: 效果对象
        """
        effect_id = effect['id']
        buffers = {}
        
        # 输入和输出缓冲区
        buffers['input'] = np.zeros(self.buffer_size)
        buffers['output'] = np.zeros(self.buffer_size)
        
        # 侧链缓冲区
        buffers['sidechain'] = np.zeros(self.buffer_size)
        
        # 预测缓冲区
        lookahead_samples = int(effect['parameters'].get('lookahead', 0.005) * self.sample_rate)
        buffers['lookahead'] = np.zeros(lookahead_samples)
        
        # RMS窗口缓冲区
        rms_window_samples = int(effect['parameters'].get('rms_window', 0.01) * self.sample_rate)
        buffers['rms_window'] = np.zeros(rms_window_samples)
        
        effect['buffers'] = buffers
        
    def delete_effect(self, effect_id: str) -> bool:
        """
        删除压缩器效果
        
        Args:
            effect_id: 效果ID
            
        Returns:
            是否删除成功
        """
        if effect_id not in self.effects:
            print(f"✗ 压缩器效果不存在: {effect_id}")
            return False
            
        try:
            # 删除效果
            del self.effects[effect_id]
            
            # 更新统计信息
            self.stats['active_effects'] -= 1
            
            # 从插件中移除效果
            if self.plugin and effect_id in self.plugin.effects:
                del self.plugin.effects[effect_id]
            
            print(f"✓ 压缩器效果已删除: {effect_id}")
            return True
            
        except Exception as e:
            print(f"✗ 删除压缩器效果失败: {e}")
            return False
            
    def process(self, audio_data: Any, parameters: Dict[str, Any]) -> Any:
        """
        处理压缩器效果
        
        Args:
            audio_data: 输入音频数据
            parameters: 效果参数
            
        Returns:
            处理后的音频数据
        """
        try:
            import time
            process_start = time.time()
            
            # 如果输入是NumPy数组
            if isinstance(audio_data, np.ndarray):
                processed_data = self._process_numpy_array(audio_data, parameters)
            else:
                # 对于其他类型的数据，返回原始数据
                processed_data = audio_data
                
            # 更新统计信息
            self.stats['effects_processed'] += 1
            self.stats['processing_time'] += (time.time() - process_start)
            
            return processed_data
            
        except Exception as e:
            print(f"✗ 压缩器效果处理失败: {e}")
            return audio_data
            
    def _process_numpy_array(self, audio_data: np.ndarray, parameters: Dict[str, Any]) -> np.ndarray:
        """
        处理NumPy数组音频数据
        
        Args:
            audio_data: 输入音频数据
            parameters: 效果参数
            
        Returns:
            处理后的音频数据
        """
        # 获取参数
        threshold = parameters.get('threshold', -20.0)
        ratio = max(1.0, parameters.get('ratio', 4.0))
        attack = max(0.001, parameters.get('attack', 0.01))
        release = max(0.01, parameters.get('release', 0.1))
        gain = parameters.get('gain', 0.0)
        knee = max(0.0, parameters.get('knee', 5.0))
        makeup_gain = parameters.get('makeup_gain', True)
        
        # 计算时间系数
        attack_coeff = np.exp(-1.0 / (attack * self.sample_rate))
        release_coeff = np.exp(-1.0 / (release * self.sample_rate))
        
        # 创建输出数组
        if audio_data.ndim == 1:
            # 单声道处理
            output_data = np.zeros_like(audio_data)
            envelope = 0.0
            
            for i in range(len(audio_data)):
                # 计算输入信号的幅度（RMS）
                sample = audio_data[i]
                amplitude = abs(sample)
                
                # 包络检测（峰值检测）
                if amplitude > envelope:
                    envelope = attack_coeff * envelope + (1 - attack_coeff) * amplitude
                else:
                    envelope = release_coeff * envelope + (1 - release_coeff) * amplitude
                    
                # 转换为dB
                envelope_db = 20 * np.log10(max(1e-10, envelope))
                
                # 计算增益减少量
                gain_reduction = self._calculate_gain_reduction(
                    envelope_db, threshold, ratio, knee)
                    
                # 应用增益减少
                linear_gain_reduction = 10 ** (gain_reduction / 20.0)
                
                # 应用压缩
                compressed_sample = sample * linear_gain_reduction
                
                # 应用输出增益
                if gain != 0.0:
                    output_gain = 10 ** (gain / 20.0)
                    compressed_sample *= output_gain
                    
                # 自动补偿增益
                if makeup_gain and gain_reduction < 0:
                    makeup = -gain_reduction  # 补偿减少的增益
                    makeup_linear = 10 ** (makeup / 20.0)
                    compressed_sample *= makeup_linear
                    
                output_data[i] = compressed_sample
                
        else:
            # 多声道处理
            output_data = np.zeros_like(audio_data)
            envelope = 0.0
            
            for channel in range(audio_data.shape[0]):
                for i in range(audio_data.shape[1]):
                    # 计算输入信号的幅度（RMS）
                    sample = audio_data[channel, i]
                    amplitude = abs(sample)
                    
                    # 包络检测（峰值检测）
                    if amplitude > envelope:
                        envelope = attack_coeff * envelope + (1 - attack_coeff) * amplitude
                    else:
                        envelope = release_coeff * envelope + (1 - release_coeff) * amplitude
                        
                    # 转换为dB
                    envelope_db = 20 * np.log10(max(1e-10, envelope))
                    
                    # 计算增益减少量
                    gain_reduction = self._calculate_gain_reduction(
                        envelope_db, threshold, ratio, knee)
                        
                    # 应用增益减少
                    linear_gain_reduction = 10 ** (gain_reduction / 20.0)
                    
                    # 应用压缩
                    compressed_sample = sample * linear_gain_reduction
                    
                    # 应用输出增益
                    if gain != 0.0:
                        output_gain = 10 ** (gain / 20.0)
                        compressed_sample *= output_gain
                        
                    # 自动补偿增益
                    if makeup_gain and gain_reduction < 0:
                        makeup = -gain_reduction  # 补偿减少的增益
                        makeup_linear = 10 ** (makeup / 20.0)
                        compressed_sample *= makeup_linear
                        
                    output_data[channel, i] = compressed_sample
                    
        # 确保输出在有效范围内
        processed_data = np.clip(output_data, -1.0, 1.0)
        return processed_data
        
    def _calculate_gain_reduction(self, input_level: float, threshold: float, 
                                ratio: float, knee: float) -> float:
        """
        计算增益减少量
        
        Args:
            input_level: 输入电平 (dB)
            threshold: 阈值 (dB)
            ratio: 压缩比
            knee: 膝点 (dB)
            
        Returns:
            增益减少量 (dB)
        """
        # 如果输入低于阈值，不进行压缩
        if input_level <= threshold - knee/2:
            return 0.0
            
        # 软膝压缩
        if input_level <= threshold + knee/2:
            # 在膝点范围内，使用二次曲线
            x = input_level - threshold + knee/2
            gain_reduction = -((x**2) / (2 * knee)) / ratio
        else:
            # 超过膝点，使用线性压缩
            gain_reduction = (threshold - input_level) * (1 - 1/ratio)
            
        return gain_reduction
        
    def set_parameter(self, effect_id: str, parameter: str, value: Any) -> bool:
        """
        设置效果参数
        
        Args:
            effect_id: 效果ID
            parameter: 参数名
            value: 参数值
            
        Returns:
            是否设置成功
        """
        if effect_id not in self.effects:
            print(f"✗ 压缩器效果不存在: {effect_id}")
            return False
            
        try:
            self.effects[effect_id]['parameters'][parameter] = value
            
            # 如果是插件中的效果，也更新插件中的副本
            if self.plugin and effect_id in self.plugin.effects:
                self.plugin.effects[effect_id]['parameters'][parameter] = value
                
            print(f"✓ 压缩器效果参数已设置: {effect_id}.{parameter} = {value}")
            return True
            
        except Exception as e:
            print(f"✗ 设置压缩器效果参数失败: {e}")
            return False
            
    def get_parameters(self, effect_id: str) -> Dict[str, Any]:
        """
        获取效果参数
        
        Args:
            effect_id: 效果ID
            
        Returns:
            参数字典
        """
        if effect_id not in self.effects:
            return {}
            
        return self.effects[effect_id]['parameters'].copy()
        
    def enable_effect(self, effect_id: str) -> bool:
        """
        启用压缩器效果
        
        Args:
            effect_id: 效果ID
            
        Returns:
            是否启用成功
        """
        if effect_id not in self.effects:
            print(f"✗ 压缩器效果不存在: {effect_id}")
            return False
            
        try:
            self.effects[effect_id]['active'] = True
            self.stats['active_effects'] += 1
            
            # 如果是插件中的效果，也更新插件中的副本
            if self.plugin and effect_id in self.plugin.effects:
                self.plugin.effects[effect_id]['active'] = True
                
            print(f"✓ 压缩器效果已启用: {effect_id}")
            return True
            
        except Exception as e:
            print(f"✗ 启用压缩器效果失败: {e}")
            return False
            
    def disable_effect(self, effect_id: str) -> bool:
        """
        禁用压缩器效果
        
        Args:
            effect_id: 效果ID
            
        Returns:
            是否禁用成功
        """
        if effect_id not in self.effects:
            print(f"✗ 压缩器效果不存在: {effect_id}")
            return False
            
        try:
            self.effects[effect_id]['active'] = False
            self.stats['active_effects'] -= 1
            
            # 如果是插件中的效果，也更新插件中的副本
            if self.plugin and effect_id in self.plugin.effects:
                self.plugin.effects[effect_id]['active'] = False
                
            print(f"✓ 压缩器效果已禁用: {effect_id}")
            return True
            
        except Exception as e:
            print(f"✗ 禁用压缩器效果失败: {e}")
            return False
            
    def cleanup(self):
        """清理所有资源"""
        self.effects.clear()
        self.stats = {
            'total_effects': 0,
            'active_effects': 0,
            'effects_processed': 0,
            'processing_time': 0.0,
            'memory_usage': 0
        }
        print("✓ 压缩器效果处理器资源已清理")
        
    def get_stats(self) -> Dict[str, int]:
        """
        获取统计信息
        
        Returns:
            统计信息字典
        """
        return self.stats.copy()
        
    def _get_current_time(self) -> float:
        """
        获取当前时间（秒）
        
        Returns:
            当前时间
        """
        if self.plugin and self.plugin.plugin_manager and self.plugin.plugin_manager.world:
            return self.plugin.plugin_manager.world.globalClock.getFrameTime()
        import time
        return time.time()
        
    def update(self, dt: float):
        """
        更新处理器状态
        
        Args:
            dt: 时间增量
        """
        # 这里可以更新任何需要定期更新的状态
        pass
        
    def set_sample_rate(self, sample_rate: int):
        """
        设置采样率
        
        Args:
            sample_rate: 采样率 (Hz)
        """
        self.sample_rate = sample_rate
        print(f"✓ 压缩器处理器采样率已设置: {sample_rate} Hz")
        
    def set_threshold(self, effect_id: str, threshold: float) -> bool:
        """
        设置阈值
        
        Args:
            effect_id: 效果ID
            threshold: 阈值 (dB)
            
        Returns:
            是否设置成功
        """
        return self.set_parameter(effect_id, 'threshold', max(-60, min(0, threshold)))
        
    def set_ratio(self, effect_id: str, ratio: float) -> bool:
        """
        设置压缩比
        
        Args:
            effect_id: 效果ID
            ratio: 压缩比
            
        Returns:
            是否设置成功
        """
        return self.set_parameter(effect_id, 'ratio', max(1.0, min(20.0, ratio)))
        
    def set_attack(self, effect_id: str, attack: float) -> bool:
        """
        设置启动时间
        
        Args:
            effect_id: 效果ID
            attack: 启动时间 (秒)
            
        Returns:
            是否设置成功
        """
        return self.set_parameter(effect_id, 'attack', max(0.001, min(1.0, attack)))
        
    def set_release(self, effect_id: str, release: float) -> bool:
        """
        设置释放时间
        
        Args:
            effect_id: 效果ID
            release: 释放时间 (秒)
            
        Returns:
            是否设置成功
        """
        return self.set_parameter(effect_id, 'release', max(0.01, min(5.0, release)))
        
    def set_gain(self, effect_id: str, gain: float) -> bool:
        """
        设置输出增益
        
        Args:
            effect_id: 效果ID
            gain: 输出增益 (dB)
            
        Returns:
            是否设置成功
        """
        return self.set_parameter(effect_id, 'gain', max(-20, min(20, gain)))
        
    def set_knee(self, effect_id: str, knee: float) -> bool:
        """
        设置膝点
        
        Args:
            effect_id: 效果ID
            knee: 膝点 (dB)
            
        Returns:
            是否设置成功
        """
        return self.set_parameter(effect_id, 'knee', max(0, min(20, knee)))
        
    def enable_makeup_gain(self, effect_id: str, enable: bool) -> bool:
        """
        启用/禁用自动补偿增益
        
        Args:
            effect_id: 效果ID
            enable: 是否启用
            
        Returns:
            是否设置成功
        """
        return self.set_parameter(effect_id, 'makeup_gain', enable)
        
    def enable_sidechain(self, effect_id: str, enable: bool) -> bool:
        """
        启用/禁用侧链
        
        Args:
            effect_id: 效果ID
            enable: 是否启用
            
        Returns:
            是否设置成功
        """
        return self.set_parameter(effect_id, 'sidechain', enable)
        
    def get_gain_reduction_meter(self, effect_id: str) -> float:
        """
        获取增益减少量表
        
        Args:
            effect_id: 效果ID
            
        Returns:
            当前增益减少量 (dB)
        """
        if effect_id not in self.effects:
            return 0.0
            
        return self.effects[effect_id].get('gain_reduction', 0.0)
        
    def create_preset(self, preset_name: str) -> Dict[str, Any]:
        """
        创建压缩器预设
        
        Args:
            preset_name: 预设名称
            
        Returns:
            预设参数字典
        """
        presets = {
            'vocal_compressor': {
                'threshold': -24.0,
                'ratio': 4.0,
                'attack': 0.005,
                'release': 0.05,
                'gain': 3.0,
                'knee': 6.0,
                'makeup_gain': True
            },
            'bass_compressor': {
                'threshold': -18.0,
                'ratio': 6.0,
                'attack': 0.015,
                'release': 0.2,
                'gain': 2.0,
                'knee': 8.0,
                'makeup_gain': True
            },
            'drum_compressor': {
                'threshold': -15.0,
                'ratio': 8.0,
                'attack': 0.003,
                'release': 0.08,
                'gain': 1.0,
                'knee': 3.0,
                'makeup_gain': True
            },
            'master_bus': {
                'threshold': -12.0,
                'ratio': 3.0,
                'attack': 0.02,
                'release': 0.3,
                'gain': 1.5,
                'knee': 10.0,
                'makeup_gain': True
            },
            'aggressive': {
                'threshold': -10.0,
                'ratio': 10.0,
                'attack': 0.001,
                'release': 0.05,
                'gain': 4.0,
                'knee': 2.0,
                'makeup_gain': True
            },
            'gentle': {
                'threshold': -28.0,
                'ratio': 2.0,
                'attack': 0.05,
                'release': 0.5,
                'gain': 0.0,
                'knee': 12.0,
                'makeup_gain': True
            }
        }
        
        return presets.get(preset_name, {}).copy()
        
    def get_compression_ratio_meter(self, effect_id: str) -> float:
        """
        获取压缩比率表
        
        Args:
            effect_id: 效果ID
            
        Returns:
            当前压缩比率
        """
        if effect_id not in self.effects:
            return 1.0
            
        return self.effects[effect_id]['parameters'].get('ratio', 1.0)
        
    def get_envelope_follower(self, effect_id: str) -> float:
        """
        获取包络跟随器值
        
        Args:
            effect_id: 效果ID
            
        Returns:
            当前包络值
        """
        if effect_id not in self.effects:
            return 0.0
            
        return self.effects[effect_id].get('envelope', 0.0)

