"""
VR测试调试子系统
负责VR测试模式、HUD显示和性能测试功能
"""

import time


class VRTestMode:
    """VR测试模式系统
    
    功能:
    - VR内容直接显示在屏幕上(不提交给OpenVR)
    - 实时性能监控HUD
    - 支持左眼/右眼/立体三种显示模式
    - 渐进式测试功能(纹理提交、姿态等待)
    - 性能测试和调试工具
    """
    
    def __init__(self, vr_manager):
        """初始化VR测试模式系统
        
        Args:
            vr_manager: VRManager实例的引用
        """
        self.vr_manager = vr_manager
        
        # ===== 测试模式状态 =====
        self.vr_test_mode = False  # 是否启用VR测试模式
        self.test_display_mode = 'stereo'  # 'left', 'right', 'stereo'
        self.test_mode_initialized = False  # 测试模式是否已初始化
        
        # ===== 显示组件 =====
        self.test_display_quad = None  # 测试显示的四边形
        self.test_right_quad = None  # 右眼显示的四边形(立体模式)
        self.stereo_display_created = False  # 立体显示是否已创建
        
        # ===== HUD组件 =====
        self.test_performance_hud = None  # 性能HUD
        self.test_performance_text = None  # 性能文本节点
        self.hud_update_counter = 0  # HUD更新计数器
        self.hud_update_interval = 30  # HUD更新间隔(帧数), 30帧约0.5秒@60fps
        
        # ===== 测试模式调试选项 =====
        self.test_mode_submit_texture = False  # 是否在测试模式提交纹理到OpenVR
        self.test_mode_wait_poses = False  # 是否在测试模式调用waitGetPoses
        
        # ===== 纹理缓存 =====
        self._left_ovr_texture = None  # 缓存的左眼OpenVR Texture对象
        self._right_ovr_texture = None  # 缓存的右眼OpenVR Texture对象
    
    # ========== 测试模式控制方法 ==========
    
    def enable_vr_test_mode(self, display_mode='stereo'):
        """启用VR测试模式 - 将VR渲染直接显示在屏幕上
        
        Args:
            display_mode: 显示模式
                - 'stereo': 左右眼并排显示
                - 'left': 只显示左眼
                - 'right': 只显示右眼
        """
        if not self.vr_manager.is_vr_available():
            print("❌ VR系统不可用,无法启动测试模式")
            return False
        
        try:
            print(f"🧪 启动VR测试模式 - 显示模式: {display_mode}")
            
            # 初始化VR系统(如果还没初始化)
            if not self.vr_manager.vr_initialized:
                if not self.vr_manager.initialize_vr():
                    print("❌ VR初始化失败")
                    return False
            
            # 🔧 关键修复:确保测试模式的纹理资源已初始化
            # 这解决了测试模式纹理提交失败导致的36FPS问题
            print("🔧 检查VR测试模式纹理资源...")
            if not self._ensure_test_mode_textures():
                print("❌ VR测试模式纹理资源初始化失败")
                return False
            
            # 设置测试模式
            self.vr_test_mode = True
            self.test_display_mode = display_mode
            
            # 启用VR渲染但不提交给OpenVR
            if not self.vr_manager.vr_enabled:
                # 启用VR渲染流程(但会在回调中跳过提交)
                self.vr_manager.vr_enabled = True
                self.vr_manager._disable_main_cam()
                
                # 设置高帧率用于测试
                if hasattr(self.vr_manager.world, 'qtWidget') and self.vr_manager.world.qtWidget:
                    if hasattr(self.vr_manager.world.qtWidget, 'synchronizer'):
                        self.vr_manager.world.qtWidget.synchronizer.setInterval(int(1000/144))
                        print("✓ 测试模式:Qt Timer设置为144Hz")
            
            # 初始化测试显示系统
            if not self._initialize_test_display():
                print("❌ 测试显示系统初始化失败")
                return False
            
            # 创建性能HUD
            if not self._initialize_test_performance_hud():
                print("❌ 性能HUD初始化失败")
                return False
            
            # 恢复主相机以查看测试内容
            self.vr_manager._enable_main_cam()
            
            # 重置HUD更新计数器
            self.hud_update_counter = 0
            
            print("✅ VR测试模式已启用")
            print("   - VR内容将显示在屏幕上")
            print("   - 不会向OpenVR提交纹理")
            print("   - 可以准确测量纯渲染性能")
            print(f"   - 当前显示模式: {display_mode}")
            
            return True
        
        except Exception as e:
            print(f"❌ 启动VR测试模式失败: {e}")
            import traceback
            traceback.print_exc()
            return False
    
    def disable_vr_test_mode(self):
        """禁用VR测试模式"""
        try:
            print("🧪 禁用VR测试模式...")
            
            # 清理测试显示
            self._cleanup_test_display()
            
            # 清理性能HUD
            self._cleanup_test_performance_hud()
            
            # 关闭测试模式
            self.vr_test_mode = False
            self.test_mode_initialized = False
            
            # 重置HUD更新计数器
            self.hud_update_counter = 0
            
            # 恢复正常VR模式或禁用VR
            if self.vr_manager.vr_enabled:
                print("   选择: [1] 恢复正常VR模式  [2] 完全禁用VR")
                # 这里可以让用户选择,现在默认禁用VR
                self.vr_manager.disable_vr()
            
            print("✅ VR测试模式已禁用")
            return True
        
        except Exception as e:
            print(f"❌ 禁用VR测试模式失败: {e}")
            return False
    
    def switch_test_display_mode(self, display_mode):
        """切换测试显示模式
        
        Args:
            display_mode: 'stereo', 'left', 'right'
        """
        if not self.vr_test_mode:
            print("⚠️ 请先启用VR测试模式")
            return False
        
        if display_mode not in ['stereo', 'left', 'right']:
            print(f"⚠️ 无效的显示模式: {display_mode}")
            return False
        
        print(f"🧪 切换显示模式: {self.test_display_mode} → {display_mode}")
        
        # 如果切换模式,需要清理旧的显示并重置标志位
        if self.test_display_mode != display_mode:
            self._cleanup_test_display()
        
        self.test_display_mode = display_mode
        
        # 更新显示
        self._update_test_display()
        return True
    
    # ========== 纹理管理方法 ==========
    
    def _ensure_test_mode_textures(self):
        """确保VR测试模式的纹理资源已正确初始化
        
        这解决了测试模式启用纹理提交时的36FPS问题:
        - VR测试模式可能跳过了VR渲染缓冲区的初始化
        - submit_texture()需要有效的texture ID和OpenVR Texture对象
        - 如果未初始化会导致提交失败,造成帧率减半
        """
        try:
            print("   检查VR渲染缓冲区...")
            
            # 检查VR渲染缓冲区是否存在
            buffers_exist = (
                hasattr(self.vr_manager, 'vr_left_eye_buffer') and self.vr_manager.vr_left_eye_buffer and
                hasattr(self.vr_manager, 'vr_right_eye_buffer') and self.vr_manager.vr_right_eye_buffer
            )
            
            if not buffers_exist:
                print("   ⚠️ VR渲染缓冲区不存在,正在创建...")
                # 🐛 BUG修复: 原代码调用了不存在的 _setup_vr_render_buffers()
                # 应该调用 _create_vr_buffers() 或 _create_vr_buffers_with_pipeline()
                if hasattr(self.vr_manager.world, 'render_pipeline') and self.vr_manager.world.render_pipeline:
                    success = self.vr_manager._create_vr_buffers_with_pipeline()
                else:
                    success = self.vr_manager._create_vr_buffers()
                
                if not success:
                    print("   ❌ VR渲染缓冲区创建失败")
                    return False
                print("   ✅ VR渲染缓冲区创建成功")
            else:
                print("   ✅ VR渲染缓冲区已存在")
            
            # 检查纹理ID是否已缓存
            print("   检查纹理ID缓存...")
            texture_ids_cached = (
                hasattr(self.vr_manager, 'left_texture_id') and self.vr_manager.left_texture_id and self.vr_manager.left_texture_id > 0 and
                hasattr(self.vr_manager, 'right_texture_id') and self.vr_manager.right_texture_id and self.vr_manager.right_texture_id > 0
            )
            
            if not texture_ids_cached:
                print("   ⚠️ 纹理ID未缓存,正在准备纹理...")
                if not self.vr_manager._prepare_and_cache_textures():
                    print("   ❌ 纹理准备和缓存失败")
                    return False
                print(f"   ✅ 纹理ID缓存成功 - 左眼:{self.vr_manager.left_texture_id}, 右眼:{self.vr_manager.right_texture_id}")
            else:
                print(f"   ✅ 纹理ID已缓存 - 左眼:{self.vr_manager.left_texture_id}, 右眼:{self.vr_manager.right_texture_id}")
            
            # 检查OpenVR Texture对象是否已创建
            print("   检查OpenVR Texture对象...")
            ovr_textures_exist = (
                self._left_ovr_texture and self._right_ovr_texture
            )
            
            if not ovr_textures_exist:
                print("   ⚠️ OpenVR Texture对象未创建,正在创建...")
                self._create_cached_ovr_textures()
                print("   ✅ OpenVR Texture对象创建成功")
            else:
                print("   ✅ OpenVR Texture对象已存在")
            
            print("   ✅ VR测试模式纹理资源检查完成,可安全启用纹理提交")
            return True
        
        except Exception as e:
            print(f"   ❌ VR测试模式纹理资源检查失败: {e}")
            import traceback
            traceback.print_exc()
            return False
    
    def _create_cached_ovr_textures(self):
        """创建缓存的OpenVR Texture对象 - 避免每帧创建新对象"""
        try:
            import openvr
            self._left_ovr_texture = openvr.Texture_t()
            self._right_ovr_texture = openvr.Texture_t()

            # 设置固定属性(这些不变)
            self._left_ovr_texture.eType = openvr.TextureType_OpenGL
            self._left_ovr_texture.eColorSpace = openvr.ColorSpace_Gamma
            self._right_ovr_texture.eType = openvr.TextureType_OpenGL
            self._right_ovr_texture.eColorSpace = openvr.ColorSpace_Gamma

            print("✅ OpenVR Texture对象缓存已创建")
        except Exception as e:
            print(f"⚠️ OpenVR Texture对象创建失败: {e}")
            # 不抛出异常,使用备用方案

    # 注意: _batch_submit_textures() 方法已移至VRManager
    # 因为它是VR渲染的核心功能,不仅用于测试模式

    # ========== 显示系统方法 ==========
    
    def _initialize_test_display(self):
        """初始化测试显示系统"""
        try:
            print("🔧 正在初始化测试显示系统...")
            
            # 导入必要的Panda3D组件
            from panda3d.core import CardMaker, PandaNode
            
            # 创建显示四边形
            cm = CardMaker("vr_test_display")
            
            if self.test_display_mode == 'stereo':
                # 并排显示:左眼在左半屏,右眼在右半屏
                cm.setFrame(-1, 1, -0.5, 0.5)  # 全屏
            else:
                # 单眼显示:占据整个屏幕
                cm.setFrame(-1, 1, -1, 1)
            
            # 创建节点
            self.test_display_quad = self.vr_manager.world.render2d.attachNewNode(cm.generate())
            
            # 设置初始纹理
            self._update_test_display()
            
            # 设置渲染状态
            self.test_display_quad.setTransparency(0)  # 不透明
            self.test_display_quad.setBin("background", 0)  # 背景层
            
            self.test_mode_initialized = True
            print("✅ 测试显示系统初始化完成")
            return True
        
        except Exception as e:
            print(f"❌ 测试显示系统初始化失败: {e}")
            import traceback
            traceback.print_exc()
            return False
    
    def _update_test_display(self):
        """更新测试显示内容"""
        try:
            if not self.test_mode_initialized:
                return
            
            # 根据显示模式设置纹理
            if self.test_display_mode == 'left':
                if not self.test_display_quad:
                    return
                if self.vr_manager.vr_left_texture:
                    self.test_display_quad.setTexture(self.vr_manager.vr_left_texture)
            elif self.test_display_mode == 'right':
                if not self.test_display_quad:
                    return
                if self.vr_manager.vr_right_texture:
                    self.test_display_quad.setTexture(self.vr_manager.vr_right_texture)
            elif self.test_display_mode == 'stereo':
                # 立体显示:只在第一次创建,后续只更新纹理
                if not self.stereo_display_created:
                    self._create_stereo_display()
                else:
                    # 只更新纹理,不重新创建
                    if self.test_display_quad and self.vr_manager.vr_left_texture:
                        self.test_display_quad.setTexture(self.vr_manager.vr_left_texture)
                    if self.test_right_quad and self.vr_manager.vr_right_texture:
                        self.test_right_quad.setTexture(self.vr_manager.vr_right_texture)
        
        except Exception as e:
            print(f"⚠️ 更新测试显示失败: {e}")
    
    def _create_stereo_display(self):
        """创建左右眼并排显示"""
        try:
            # 如果已经创建,直接返回
            if self.stereo_display_created and self.test_display_quad and self.test_right_quad:
                return
            
            # 移除旧的显示
            if self.test_display_quad:
                self.test_display_quad.removeNode()
            if self.test_right_quad:
                self.test_right_quad.removeNode()
            
            from panda3d.core import CardMaker
            
            # 创建左眼显示
            left_cm = CardMaker("vr_test_left")
            left_cm.setFrame(-1, 0, -1, 1)  # 左半屏
            left_quad = self.vr_manager.world.render2d.attachNewNode(left_cm.generate())
            if self.vr_manager.vr_left_texture:
                left_quad.setTexture(self.vr_manager.vr_left_texture)
            
            # 创建右眼显示
            right_cm = CardMaker("vr_test_right")
            right_cm.setFrame(0, 1, -1, 1)  # 右半屏
            right_quad = self.vr_manager.world.render2d.attachNewNode(right_cm.generate())
            if self.vr_manager.vr_right_texture:
                right_quad.setTexture(self.vr_manager.vr_right_texture)
            
            # 保存引用
            self.test_display_quad = left_quad  # 保存左眼引用
            self.test_right_quad = right_quad   # 额外保存右眼引用
            self.stereo_display_created = True  # 标记已创建
            
            print("✓ 立体显示已创建")
        
        except Exception as e:
            print(f"⚠️ 创建立体显示失败: {e}")
            self.stereo_display_created = False
    
    def _cleanup_test_display(self):
        """清理测试显示"""
        try:
            if self.test_display_quad:
                self.test_display_quad.removeNode()
                self.test_display_quad = None
            
            if hasattr(self, 'test_right_quad') and self.test_right_quad:
                self.test_right_quad.removeNode()
                self.test_right_quad = None
            
            # 重置立体显示标志位
            self.stereo_display_created = False
            
            print("✓ 测试显示已清理")
        
        except Exception as e:
            print(f"⚠️ 清理测试显示失败: {e}")
    
    # ========== HUD系统方法 ==========
    
    def _initialize_test_performance_hud(self):
        """初始化性能HUD"""
        try:
            print("🔧 正在初始化性能HUD...")
            
            from direct.gui.OnscreenText import OnscreenText
            from panda3d.core import TextNode
            
            # 创建性能文本显示
            self.test_performance_text = OnscreenText(
                text="初始化中...",
                pos=(-0.95, 0.9),  # 左上角,调整到屏幕内
                scale=0.05,
                fg=(1, 1, 0, 1),  # 黄色
                align=TextNode.ALeft,
                shadow=(0, 0, 0, 0.5),  # 黑色阴影
                parent=self.vr_manager.world.render2d
            )
            
            print("✅ 性能HUD初始化完成")
            return True
        
        except Exception as e:
            print(f"❌ 性能HUD初始化失败: {e}")
            return False
    
    def _update_test_performance_hud(self):
        """更新性能HUD显示(限制更新频率避免重影)"""
        try:
            if not self.test_performance_text or not self.vr_test_mode:
                return
            
            # 增加计数器
            self.hud_update_counter += 1
            
            # 只在指定间隔更新文本,避免重影
            if self.hud_update_counter < self.hud_update_interval:
                return
            
            # 重置计数器
            self.hud_update_counter = 0
            
            # 收集性能数据
            perf_mon = self.vr_manager.performance_monitor
            left_render_time = perf_mon.left_render_time if perf_mon else 0
            right_render_time = perf_mon.right_render_time if perf_mon else 0
            total_render_time = left_render_time + right_render_time
            
            # 计算FPS
            current_fps = perf_mon.vr_fps if perf_mon else 0
            
            # 获取系统性能
            cpu_usage = perf_mon.cpu_usage if perf_mon else 0
            memory_usage = perf_mon.memory_usage if perf_mon else 0
            gpu_usage = perf_mon.gpu_usage if perf_mon else 0
            
            # 构建显示文本
            hud_text = f"""VR TEST MODE - {self.test_display_mode.upper()}

Render Performance:
  FPS: {current_fps:.1f}
  Left Eye: {left_render_time:.2f}ms
  Right Eye: {right_render_time:.2f}ms
  Total: {total_render_time:.2f}ms

System Performance:
  CPU: {cpu_usage:.1f}%
  Memory: {memory_usage:.1f}%
  GPU: {gpu_usage:.1f}%

Render Count:
  Left Eye: {perf_mon.left_render_count if perf_mon else 0}
  Right Eye: {perf_mon.right_render_count if perf_mon else 0}

Target: <13.9ms@72Hz
Status: {'GOOD' if total_render_time < 10 else 'HIGH' if total_render_time < 16 else 'SLOW'}

Hotkeys:
F1=Left F2=Right F3=SideBySide
ESC=Exit Test Mode"""
            
            # 更新文本
            self.test_performance_text.setText(hud_text)
        
        except Exception as e:
            print(f"⚠️ 更新性能HUD失败: {e}")
    
    def _cleanup_test_performance_hud(self):
        """清理性能HUD"""
        try:
            if self.test_performance_text:
                self.test_performance_text.destroy()
                self.test_performance_text = None
            
            print("✓ 性能HUD已清理")
        
        except Exception as e:
            print(f"⚠️ 清理性能HUD失败: {e}")
    
    # ========== 状态查询方法 ==========
    
    def get_test_mode_status(self):
        """获取测试模式状态"""
        if not self.vr_test_mode:
            return None
        
        perf_mon = self.vr_manager.performance_monitor
        left_render_time = perf_mon.left_render_time if perf_mon else 0
        right_render_time = perf_mon.right_render_time if perf_mon else 0
        total_render_time = left_render_time + right_render_time
        
        return {
            'test_mode_enabled': self.vr_test_mode,
            'display_mode': self.test_display_mode,
            'vr_fps': perf_mon.vr_fps if perf_mon else 0,
            'left_render_time': left_render_time,
            'right_render_time': right_render_time,
            'total_render_time': total_render_time,
            'left_render_count': perf_mon.left_render_count if perf_mon else 0,
            'right_render_count': perf_mon.right_render_count if perf_mon else 0,
            'performance_rating': ('excellent' if total_render_time < 10 else
                                  'good' if total_render_time < 16 else 'poor')
        }
    
    def get_test_mode_features(self):
        """获取当前测试模式功能设置"""
        return {
            'submit_texture': self.test_mode_submit_texture,
            'wait_poses': self.test_mode_wait_poses,
            'test_mode_active': self.vr_test_mode
        }
    
    def set_test_mode_features(self, submit_texture=None, wait_poses=None):
        """设置测试模式功能开关 - 用于渐进式调试
        
        Args:
            submit_texture: 是否在测试模式启用纹理提交(True/False/None=保持当前)
            wait_poses: 是否在测试模式启用waitGetPoses(True/False/None=保持当前)
        """
        if submit_texture is not None:
            self.test_mode_submit_texture = submit_texture
        if wait_poses is not None:
            self.test_mode_wait_poses = wait_poses
        
        print(f"🔧 VR测试模式功能设置:")
        print(f"   纹理提交: {'启用' if self.test_mode_submit_texture else '禁用'}")
        print(f"   姿态等待: {'启用' if self.test_mode_wait_poses else '禁用'}")
        
        # 如果当前在测试模式,输出预期效果
        if self.vr_test_mode:
            print(f"   当前测试模式已启用,设置将立即生效")
        else:
            print(f"   设置已保存,将在下次启用测试模式时生效")
    
    # ========== 性能测试方法 ==========
    
    def run_vr_performance_test(self, duration_seconds=30, display_mode='stereo'):
        """运行VR性能测试 - 简单的测试入口方法
        
        Args:
            duration_seconds: 测试持续时间(秒)
            display_mode: 显示模式 ('stereo', 'left', 'right')
        
        Returns:
            dict: 测试结果统计
        """
        print("🧪 ======= VR性能测试开始 =======")
        print(f"   测试模式: {display_mode}")
        print(f"   测试时长: {duration_seconds}秒")
        print("   按ESC键提前退出测试")
        print("   F1=左眼 F2=右眼 F3=并排显示")
        print("=================================")
        
        # 启动测试模式
        if not self.enable_vr_test_mode(display_mode):
            print("❌ VR测试模式启动失败")
            return None
        
        # 记录测试开始状态
        test_start_time = time.time()
        perf_mon = self.vr_manager.performance_monitor
        start_frame_count = perf_mon.frame_count if perf_mon else 0
        
        print("✅ VR测试模式已启动")
        print("   - VR内容直接显示在屏幕上")
        print("   - 无OpenVR纹理提交开销")
        print("   - 实时性能监控已启用")
        print(f"   - 当前显示: {display_mode.upper()}模式")
        print("\n开始性能测试...")
        
        # 等待测试完成(用户手动停止或超时)
        print(f"\n📊 测试将运行 {duration_seconds} 秒")
        print("   实时性能数据显示在屏幕左上角")
        print("   观察帧率和渲染时间变化")
        
        # 这里可以添加自动停止逻辑,但现在让用户手动控制
        print(f"\n⏰ 请观察 {duration_seconds} 秒后手动调用 disable_vr_test_mode() 停止测试")
        print("   或者随时调用 get_test_mode_status() 查看当前状态")
        
        return {
            'status': 'running',
            'start_time': test_start_time,
            'start_frame': start_frame_count,
            'display_mode': display_mode,
            'instructions': {
                'stop_test': 'vr_manager.test_mode.disable_vr_test_mode()',
                'check_status': 'vr_manager.test_mode.get_test_mode_status()',
                'switch_mode': 'vr_manager.test_mode.switch_test_display_mode("left/right/stereo")'
            }
        }
