"""
性能监控器
监控粒子系统的性能指标
"""

import time
from typing import Dict, List, Optional
from collections import deque
from direct.task import Task

class PerformanceMonitor:
    """
    粒子系统性能监控器
    实时监控和显示性能指标
    """
    
    def __init__(self, particle_manager):
        """
        初始化性能监控器
        
        Args:
            particle_manager: 粒子管理器
        """
        self.particle_manager = particle_manager
        self.enabled = False
        self.display_visible = False
        
        # 性能数据收集
        self.frame_times = deque(maxlen=60)  # 保存60帧的数据
        self.particle_counts = deque(maxlen=60)
        self.render_times = deque(maxlen=60)
        self.physics_times = deque(maxlen=60)
        self.update_times = deque(maxlen=60)
        
        # 统计数据
        self.stats = {
            'fps': 0.0,
            'avg_fps': 0.0,
            'min_fps': 0.0,
            'max_fps': 0.0,
            'particle_count': 0,
            'avg_particle_count': 0.0,
            'max_particle_count': 0,
            'render_time': 0.0,
            'physics_time': 0.0,
            'update_time': 0.0,
            'memory_usage': 0.0,
            'draw_calls': 0,
            'vertices_rendered': 0,
            'active_emitters': 0
        }
        
        # 性能阈值
        self.performance_thresholds = {
            'low_fps_warning': 30.0,
            'high_particle_warning': 5000,
            'high_render_time_warning': 16.0,  # ms
            'high_update_time_warning': 5.0     # ms
        }
        
        # 警告状态
        self.warnings = {
            'low_fps': False,
            'high_particles': False,
            'high_render_time': False,
            'high_update_time': False
        }
        
        # GUI元素
        self.gui_elements = []
        self.info_labels = {}
        
        # 监控任务
        self.monitor_task = None
        
        # 时间记录
        self.last_update_time = time.time()
        self.update_interval = 0.1  # 100ms更新一次
        
        # 历史数据（用于图表显示）
        self.history_data = {
            'fps_history': deque(maxlen=100),
            'particle_count_history': deque(maxlen=100),
            'render_time_history': deque(maxlen=100)
        }
        
        print("✓ 性能监控器初始化完成")
        
    def start(self):
        """启动性能监控"""
        if self.enabled:
            return
            
        self.enabled = True
        
        # 启动监控任务
        if hasattr(self.particle_manager, 'world') and self.particle_manager.world:
            self.monitor_task = self.particle_manager.world.taskMgr.add(
                self._monitor_task, 
                "particle_performance_monitor"
            )
            
        print("✓ 性能监控器已启动")
        
    def stop(self):
        """停止性能监控"""
        if not self.enabled:
            return
            
        self.enabled = False
        
        # 停止监控任务
        if self.monitor_task and hasattr(self.particle_manager, 'world'):
            self.particle_manager.world.taskMgr.remove(self.monitor_task)
            self.monitor_task = None
            
        # 隐藏显示
        self.hide_display()
        
        print("✓ 性能监控器已停止")
        
    def toggle_display(self):
        """切换显示状态"""
        if self.display_visible:
            self.hide_display()
        else:
            self.show_display()
            
    def show_display(self):
        """显示性能信息"""
        if self.display_visible:
            return
            
        self.display_visible = True
        self._create_display_gui()
        
        print("✓ 性能监控显示已开启")
        
    def hide_display(self):
        """隐藏性能信息"""
        if not self.display_visible:
            return
            
        self.display_visible = False
        self._cleanup_display_gui()
        
        print("✓ 性能监控显示已关闭")
        
    def _monitor_task(self, task):
        """监控任务"""
        if not self.enabled:
            return task.done
            
        current_time = time.time()
        
        # 检查更新间隔
        if current_time - self.last_update_time < self.update_interval:
            return task.cont
            
        dt = current_time - self.last_update_time
        self.last_update_time = current_time
        
        # 收集性能数据
        self._collect_performance_data(dt)
        
        # 更新统计信息
        self._update_statistics()
        
        # 检查性能警告
        self._check_performance_warnings()
        
        # 更新显示
        if self.display_visible:
            self._update_display()
            
        return task.cont
        
    def _collect_performance_data(self, dt: float):
        """收集性能数据"""
        try:
            # FPS计算
            fps = 1.0 / dt if dt > 0 else 0.0
            self.frame_times.append(dt)
            self.history_data['fps_history'].append(fps)
            
            # 获取粒子管理器统计信息
            if hasattr(self.particle_manager, 'get_stats'):
                manager_stats = self.particle_manager.get_stats()
                
                # 粒子数量
                particle_count = self.particle_manager.get_particle_count()
                self.particle_counts.append(particle_count)
                self.history_data['particle_count_history'].append(particle_count)
                
                # 渲染时间
                render_time = manager_stats.get('render_time', 0.0)
                self.render_times.append(render_time)
                self.history_data['render_time_history'].append(render_time * 1000)  # 转换为毫秒
                
                # 物理时间
                physics_time = manager_stats.get('physics_time', 0.0)
                self.physics_times.append(physics_time)
                
                # 更新时间
                update_time = manager_stats.get('update_time', 0.0)
                self.update_times.append(update_time)
                
                # 渲染统计
                if hasattr(self.particle_manager, 'renderer'):
                    render_stats = self.particle_manager.renderer.get_render_stats()
                    self.stats['draw_calls'] = render_stats.get('draw_calls', 0)
                    self.stats['vertices_rendered'] = render_stats.get('vertices_rendered', 0)
                    
                # 活跃发射器
                self.stats['active_emitters'] = self.particle_manager.get_emitter_count()
                
            # 更新当前值
            self.stats['fps'] = fps
            self.stats['particle_count'] = self.particle_manager.get_particle_count() if self.particle_manager else 0
            
        except Exception as e:
            print(f"⚠ 性能数据收集失败: {e}")
            
    def _update_statistics(self):
        """更新统计信息"""
        try:
            # FPS统计
            if self.frame_times:
                fps_values = [1.0/dt if dt > 0 else 0.0 for dt in self.frame_times]
                self.stats['avg_fps'] = sum(fps_values) / len(fps_values) if fps_values else 0.0
                self.stats['min_fps'] = min(fps_values) if fps_values else 0.0
                self.stats['max_fps'] = max(fps_values) if fps_values else 0.0
                
            # 粒子数量统计
            if self.particle_counts:
                self.stats['avg_particle_count'] = sum(self.particle_counts) / len(self.particle_counts)
                self.stats['max_particle_count'] = max(self.particle_counts)
                
            # 渲染时间统计
            if self.render_times:
                self.stats['render_time'] = sum(self.render_times[-10:]) / min(10, len(self.render_times))
                
            # 物理时间统计
            if self.physics_times:
                self.stats['physics_time'] = sum(self.physics_times[-10:]) / min(10, len(self.physics_times))
                
            # 更新时间统计
            if self.update_times:
                self.stats['update_time'] = sum(self.update_times[-10:]) / min(10, len(self.update_times))
                
            # 内存使用（简化估算）
            self.stats['memory_usage'] = self.stats['particle_count'] * 0.1  # KB per particle
            
        except Exception as e:
            print(f"⚠ 统计信息更新失败: {e}")
            
    def _check_performance_warnings(self):
        """检查性能警告"""
        try:
            # 低FPS警告
            if self.stats['fps'] < self.performance_thresholds['low_fps_warning']:
                if not self.warnings['low_fps']:
                    self.warnings['low_fps'] = True
                    print(f"⚠ 性能警告: FPS过低 ({self.stats['fps']:.1f})")
            else:
                self.warnings['low_fps'] = False
                
            # 高粒子数警告
            if self.stats['particle_count'] > self.performance_thresholds['high_particle_warning']:
                if not self.warnings['high_particles']:
                    self.warnings['high_particles'] = True
                    print(f"⚠ 性能警告: 粒子数过多 ({self.stats['particle_count']})")
            else:
                self.warnings['high_particles'] = False
                
            # 高渲染时间警告
            render_time_ms = self.stats['render_time'] * 1000
            if render_time_ms > self.performance_thresholds['high_render_time_warning']:
                if not self.warnings['high_render_time']:
                    self.warnings['high_render_time'] = True
                    print(f"⚠ 性能警告: 渲染时间过长 ({render_time_ms:.1f}ms)")
            else:
                self.warnings['high_render_time'] = False
                
            # 高更新时间警告
            update_time_ms = self.stats['update_time'] * 1000
            if update_time_ms > self.performance_thresholds['high_update_time_warning']:
                if not self.warnings['high_update_time']:
                    self.warnings['high_update_time'] = True
                    print(f"⚠ 性能警告: 更新时间过长 ({update_time_ms:.1f}ms)")
            else:
                self.warnings['high_update_time'] = False
                
        except Exception as e:
            print(f"⚠ 性能警告检查失败: {e}")
            
    def _create_display_gui(self):
        """创建显示GUI"""
        try:
            world = self.particle_manager.world
            if not hasattr(world, 'gui_manager') or not world.gui_manager:
                print("⚠ GUI管理器不可用，无法显示性能信息")
                return
                
            gui_manager = world.gui_manager
            
            # 创建性能信息面板
            panel = gui_manager.createGUIButton(
                pos=(0.02, 0, 0.5), 
                text="性能监控", 
                size=0.04
            )
            self.gui_elements.append(panel)
            
            # 创建信息标签
            info_items = [
                ("FPS", "fps"),
                ("平均FPS", "avg_fps"),
                ("粒子数", "particle_count"),
                ("活跃发射器", "active_emitters"),
                ("渲染时间", "render_time"),
                ("物理时间", "physics_time"),
                ("更新时间", "update_time"),
                ("内存使用", "memory_usage"),
                ("绘制调用", "draw_calls"),
                ("顶点数", "vertices_rendered")
            ]
            
            for i, (label, key) in enumerate(info_items):
                # 标签
                label_gui = gui_manager.createGUIButton(
                    pos=(0.02, 0, 0.45 - i * 0.04), 
                    text=f"{label}:", 
                    size=0.03
                )
                self.gui_elements.append(label_gui)
                
                # 值
                value_gui = gui_manager.createGUIButton(
                    pos=(0.12, 0, 0.45 - i * 0.04), 
                    text="0", 
                    size=0.03
                )
                self.gui_elements.append(value_gui)
                self.info_labels[key] = value_gui
                
        except Exception as e:
            print(f"⚠ 性能显示GUI创建失败: {e}")
            
    def _cleanup_display_gui(self):
        """清理显示GUI"""
        try:
            world = self.particle_manager.world
            if hasattr(world, 'gui_manager') and world.gui_manager:
                gui_manager = world.gui_manager
                
                for element in self.gui_elements:
                    gui_manager.deleteGUIElement(element)
                    
            self.gui_elements.clear()
            self.info_labels.clear()
            
        except Exception as e:
            print(f"⚠ 性能显示GUI清理失败: {e}")
            
    def _update_display(self):
        """更新显示内容"""
        try:
            # 更新各项数值显示
            for key, label_gui in self.info_labels.items():
                value = self.stats.get(key, 0)
                
                if key in ['fps', 'avg_fps', 'min_fps', 'max_fps']:
                    text = f"{value:.1f}"
                elif key in ['particle_count', 'max_particle_count', 'draw_calls', 'vertices_rendered', 'active_emitters']:
                    text = f"{int(value)}"
                elif key in ['render_time', 'physics_time', 'update_time']:
                    text = f"{value*1000:.1f}ms"
                elif key == 'memory_usage':
                    if value > 1024:
                        text = f"{value/1024:.1f}MB"
                    else:
                        text = f"{value:.1f}KB"
                else:
                    text = f"{value:.2f}"
                    
                label_gui.setText(text)
                
                # 根据警告状态设置颜色
                color_set = False
                if key == 'fps' and self.warnings['low_fps']:
                    label_gui.setColor(1, 0.3, 0.3, 1)  # 红色
                    color_set = True
                elif key == 'particle_count' and self.warnings['high_particles']:
                    label_gui.setColor(1, 0.8, 0.3, 1)  # 橙色
                    color_set = True
                elif key == 'render_time' and self.warnings['high_render_time']:
                    label_gui.setColor(1, 0.5, 0.3, 1)  # 橙红色
                    color_set = True
                elif key == 'update_time' and self.warnings['high_update_time']:
                    label_gui.setColor(1, 0.4, 0.4, 1)  # 红色
                    color_set = True
                    
                if not color_set:
                    label_gui.setColor(1, 1, 1, 1)  # 白色
                    
        except Exception as e:
            print(f"⚠ 性能显示更新失败: {e}")
            
    def get_performance_report(self) -> Dict:
        """获取性能报告"""
        return {
            'current_stats': self.stats.copy(),
            'warnings': self.warnings.copy(),
            'thresholds': self.performance_thresholds.copy(),
            'data_points': {
                'frame_times': len(self.frame_times),
                'particle_counts': len(self.particle_counts),
                'render_times': len(self.render_times),
                'physics_times': len(self.physics_times),
                'update_times': len(self.update_times)
            },
            'history': {
                'fps_history': list(self.history_data['fps_history']),
                'particle_count_history': list(self.history_data['particle_count_history']),
                'render_time_history': list(self.history_data['render_time_history'])
            }
        }
        
    def reset_statistics(self):
        """重置统计数据"""
        self.frame_times.clear()
        self.particle_counts.clear()
        self.render_times.clear()
        self.physics_times.clear()
        self.update_times.clear()
        
        # 清空历史数据
        for history_list in self.history_data.values():
            history_list.clear()
        
        # 重置统计值
        for key in self.stats:
            self.stats[key] = 0.0
            
        # 重置警告状态
        for key in self.warnings:
            self.warnings[key] = False
            
        print("✓ 性能统计数据已重置")
        
    def set_performance_thresholds(self, **thresholds):
        """设置性能阈值"""
        for key, value in thresholds.items():
            if key in self.performance_thresholds:
                self.performance_thresholds[key] = value
                print(f"✓ 性能阈值已更新 {key}: {value}")
                
    def cleanup(self):
        """清理监控器资源"""
        self.stop()
        self.reset_statistics()
        
    def get_history_data(self, data_type: str) -> List:
        """获取历史数据"""
        if data_type in self.history_data:
            return list(self.history_data[data_type])
        return []
        
    def export_performance_data(self, filepath: str) -> bool:
        """导出性能数据"""
        try:
            import json
            report = self.get_performance_report()
            
            with open(filepath, 'w', encoding='utf-8') as f:
                json.dump(report, f, indent=2, ensure_ascii=False)
                
            print(f"✓ 性能数据已导出到: {filepath}")
            return True
            
        except Exception as e:
            print(f"✗ 性能数据导出失败: {e}")
            return False