"""
VR对象池和优化系统

负责VR系统中的对象池管理、垃圾回收控制、分辨率缩放和性能模式控制。
"""

import gc
from panda3d.core import Mat4


class VROptimization:
    """VR优化系统 - 管理对象池、GC控制、分辨率缩放和性能模式"""

    def __init__(self, vr_manager):
        """初始化VR优化系统

        Args:
            vr_manager: VR管理器实例引用
        """
        self.vr_manager = vr_manager
        
        # 对象池属性
        self._matrix_pool = []  # Mat4对象池
        self._matrix_pool_size = 8  # 池大小，足够处理多个控制器
        self._cached_matrices = {}  # 设备ID到矩阵的缓存
        self._controller_poses_cache = {}  # 控制器姿态缓存，避免每帧clear()

        # OpenVR Texture对象缓存 - 避免每帧创建openvr.Texture_t()
        self._left_ovr_texture = None    # 左眼纹理对象缓存
        self._right_ovr_texture = None   # 右眼纹理对象缓存

        # Python垃圾回收控制
        self._gc_control_enabled = True  # 是否启用GC控制
        self._gc_disabled = False  # GC是否被禁用
        self._manual_gc_interval = 900  # 每900帧手动触发一次GC (15秒@60fps) - 减少GC频率
        self._last_manual_gc_frame = 0

        # VR分辨率缩放优化
        self.resolution_scale = 0.75  # 默认0.75倍分辨率，性能和质量平衡
        self.base_eye_width = 1080    # 原始推荐分辨率
        self.base_eye_height = 1200
        self.scaled_eye_width = 1080  # 实际使用的缩放后分辨率
        self.scaled_eye_height = 1200

        # VR质量预设
        self.quality_presets = {
            'performance': 0.6,   # 性能模式 - 约60%分辨率
            'balanced': 0.75,     # 平衡模式 - 约75%分辨率
            'quality': 1.0        # 质量模式 - 100%分辨率
        }
        self.current_quality_preset = 'balanced'  # 默认平衡模式

        # 性能模式控制
        self.performance_mode_enabled = False  # 是否启用性能模式
        self.performance_mode_trigger_frame = 600  # 600帧后自动启用性能模式

    def _initialize_object_pools(self):
        """初始化对象池 - 修复16-19帧周期性GPU峰值"""
        try:
            # 预填充Mat4对象池
            for _ in range(self._matrix_pool_size):
                self._matrix_pool.append(Mat4())

            print(f"✅ Mat4对象池初始化完成 - 池大小: {self._matrix_pool_size}")

            # 🚀 预创建OpenVR Texture对象 - 消除每帧创建openvr.Texture_t()的开销
            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 texture_error:
                print(f"⚠️ OpenVR Texture对象创建失败: {texture_error}")
                # 不影响整体初始化，但性能可能不是最优

            # 启用GC控制
            if self._gc_control_enabled:
                # 禁用自动垃圾回收，改为手动控制
                gc.disable()
                self._gc_disabled = True
                print("✅ Python垃圾回收已禁用，改为手动控制")

        except Exception as e:
            print(f"⚠️ 对象池初始化失败: {e}")

    def _get_pooled_matrix(self):
        """从对象池获取Mat4对象"""
        if self._matrix_pool:
            return self._matrix_pool.pop()
        else:
            # 池为空时创建新对象（不应该发生，但作为备用）
            return Mat4()

    def _return_pooled_matrix(self, matrix):
        """将Mat4对象返回对象池"""
        if len(self._matrix_pool) < self._matrix_pool_size:
            # 重置矩阵到单位矩阵
            matrix.identMat()
            self._matrix_pool.append(matrix)

    def _manual_gc_control(self):
        """手动垃圾回收控制 - 避免VR渲染期间的GC峰值"""
        if not self._gc_control_enabled or not self._gc_disabled:
            return

        # 🚀 智能GC间隔：性能模式下减少GC频率
        current_interval = self._manual_gc_interval
        if self.performance_mode_enabled:
            current_interval = self._manual_gc_interval * 2  # 性能模式下间隔翻倍

        # 每N帧手动触发一次垃圾回收
        if self.vr_manager.frame_count - self._last_manual_gc_frame >= current_interval:
            # 在非渲染关键时刻触发GC
            collected = gc.collect()
            self._last_manual_gc_frame = self.vr_manager.frame_count

            # 仅在收集到对象时输出信息
            if collected > 0:
                print(f"🗑️ 手动GC: 清理了 {collected} 个对象 (帧#{self.vr_manager.frame_count})")

    def enable_gc_control(self):
        """启用垃圾回收控制 - 减少VR渲染期间的GC峰值"""
        if not self._gc_control_enabled:
            self._gc_control_enabled = True
            if not self._gc_disabled:
                gc.disable()
                self._gc_disabled = True
            print("✅ VR垃圾回收控制已启用")
        else:
            print("ℹ️ VR垃圾回收控制已经启用")

    def disable_gc_control(self):
        """禁用垃圾回收控制 - 恢复自动垃圾回收"""
        if self._gc_control_enabled:
            self._gc_control_enabled = False
            if self._gc_disabled:
                gc.enable()
                self._gc_disabled = False
            print("✅ VR垃圾回收控制已禁用，恢复自动垃圾回收")
        else:
            print("ℹ️ VR垃圾回收控制已经禁用")

    def set_manual_gc_interval(self, frames):
        """设置手动垃圾回收间隔

        Args:
            frames: 帧数间隔 (建议100-600)
        """
        if 50 <= frames <= 1800:
            old_interval = self._manual_gc_interval
            self._manual_gc_interval = frames
            print(f"✅ 手动GC间隔: {old_interval} → {frames} 帧")
        else:
            print("⚠️ GC间隔应在50-1800帧之间")

    def force_manual_gc(self):
        """强制执行一次垃圾回收"""
        collected = gc.collect()
        print(f"🗑️ 强制GC: 清理了 {collected} 个对象")
        return collected

    def get_object_pool_status(self):
        """获取对象池状态"""
        return {
            'matrix_pool_size': len(self._matrix_pool),
            'matrix_pool_capacity': self._matrix_pool_size,
            'cached_controllers': len(self.vr_manager.controller_poses),
            'cached_matrices': len(self._cached_matrices),
        }

    # ====== VR分辨率缩放和质量预设系统 ======

    def set_resolution_scale(self, scale):
        """设置VR分辨率缩放系数

        Args:
            scale: 缩放系数 (0.3-1.0)，0.75表示75%分辨率
        """
        if not (0.3 <= scale <= 1.0):
            print(f"⚠️ 分辨率缩放系数应在0.3-1.0之间，当前: {scale}")
            return False

        old_scale = self.resolution_scale
        self.resolution_scale = scale

        # 如果VR已初始化，重新创建缓冲区
        if self.vr_manager.vr_initialized:
            self._apply_resolution_scale()

        print(f"✓ VR分辨率缩放: {old_scale} → {scale}")
        pixel_reduction = (1 - scale**2) * 100
        print(f"📊 像素减少: {pixel_reduction:.1f}%")

        return True

    def set_quality_preset(self, preset_name):
        """设置VR质量预设

        Args:
            preset_name: 'performance', 'balanced', 'quality'
        """
        if preset_name not in self.quality_presets:
            print(f"⚠️ 未知的质量预设: {preset_name}")
            print(f"   可用预设: {list(self.quality_presets.keys())}")
            return False

        old_preset = self.current_quality_preset
        self.current_quality_preset = preset_name
        scale = self.quality_presets[preset_name]

        print(f"🎯 切换VR质量预设: {old_preset} → {preset_name}")

        return self.set_resolution_scale(scale)

    def cycle_quality_preset(self):
        """循环切换质量预设"""
        presets = list(self.quality_presets.keys())
        current_index = presets.index(self.current_quality_preset)
        next_index = (current_index + 1) % len(presets)
        next_preset = presets[next_index]

        return self.set_quality_preset(next_preset)

    def _apply_resolution_scale(self):
        """应用分辨率缩放，重新创建VR缓冲区"""
        try:
            # 计算新的分辨率
            self.scaled_eye_width = int(self.base_eye_width * self.resolution_scale)
            self.scaled_eye_height = int(self.base_eye_height * self.resolution_scale)

            # 更新当前分辨率
            self.vr_manager.eye_width = self.scaled_eye_width
            self.vr_manager.eye_height = self.scaled_eye_height
            if hasattr(self.vr_manager, 'current_eye_resolution'):
                self.vr_manager.current_eye_resolution = (self.vr_manager.eye_width, self.vr_manager.eye_height)

            print(f"🔄 重新创建VR缓冲区...")
            print(f"   新分辨率: {self.vr_manager.eye_width}x{self.vr_manager.eye_height}")

            # 清理旧的缓冲区
            self.vr_manager._cleanup_vr_buffers()

            # 🔧 关键修复：根据渲染模式选择创建方法
            success = False
            if self.vr_manager.vr_render_mode.name == "RENDER_PIPELINE":
                print(f"   使用RenderPipeline模式重建...")
                success = self.vr_manager._create_vr_buffers_with_pipeline()
                if not success:
                    print("⚠️ RenderPipeline模式创建失败，回退到普通渲染模式")
                    self.vr_manager.vr_render_mode = self.vr_manager.VRRenderMode.NORMAL
                    success = self.vr_manager._create_vr_buffers()
            else:
                print(f"   使用普通模式重建...")
                success = self.vr_manager._create_vr_buffers()

            if success:
                # 重新设置相机
                self.vr_manager._setup_vr_cameras()
                print("✅ VR缓冲区重新创建成功")
                return True
            else:
                print("❌ VR缓冲区重新创建失败")
                return False

        except Exception as e:
            print(f"❌ 应用分辨率缩放失败: {e}")
            import traceback
            traceback.print_exc()
            return False

    def get_resolution_info(self):
        """获取分辨率相关信息"""
        return {
            'base_resolution': (self.base_eye_width, self.base_eye_height),
            'current_resolution': (self.vr_manager.eye_width, self.vr_manager.eye_height),
            'resolution_scale': self.resolution_scale,
            'current_preset': self.current_quality_preset,
            'available_presets': self.quality_presets,
            'pixel_reduction_percent': (1 - self.resolution_scale**2) * 100
        }

    def print_resolution_info(self):
        """输出分辨率信息"""
        info = self.get_resolution_info()
        print("🔧 ===== VR分辨率信息 =====")
        print(f"   推荐分辨率: {info['base_resolution'][0]}x{info['base_resolution'][1]}")
        print(f"   当前分辨率: {info['current_resolution'][0]}x{info['current_resolution'][1]}")
        print(f"   缩放系数: {info['resolution_scale']}")
        print(f"   当前预设: {info['current_preset']}")
        print(f"   像素减少: {info['pixel_reduction_percent']:.1f}%")
        print("   可用预设:")
        for name, scale in info['available_presets'].items():
            marker = "✓" if name == info['current_preset'] else " "
            print(f"   {marker} {name}: {scale} ({scale*100:.0f}%)")
        print("==========================")

    # ====== 性能模式控制方法 ======

    def enable_performance_mode(self):
        """手动启用性能模式 - 立即禁用详细监控以提升性能"""
        if not self.performance_mode_enabled:
            self.performance_mode_enabled = True
            print("🎯 性能模式已手动启用 - 禁用详细监控以提升性能")
            print("   现在将减少每帧对象创建，显著提升VR性能稳定性")
        else:
            print("ℹ️ 性能模式已经启用")

    def disable_performance_mode(self):
        """禁用性能模式 - 重新启用详细监控（用于调试）"""
        if self.performance_mode_enabled:
            self.performance_mode_enabled = False
            print("🔍 性能模式已禁用 - 重新启用详细监控")
            print("   注意：这将增加每帧对象创建，可能影响VR性能")
        else:
            print("ℹ️ 性能模式已经禁用")

    def set_performance_mode_trigger_frame(self, frame_count):
        """设置性能模式自动触发的帧数

        Args:
            frame_count: 触发帧数 (建议300-1200)
        """
        if 100 <= frame_count <= 3600:
            old_trigger = self.performance_mode_trigger_frame
            self.performance_mode_trigger_frame = frame_count
            print(f"✅ 性能模式触发帧数: {old_trigger} → {frame_count}")
        else:
            print("⚠️ 触发帧数应在100-3600之间")

    def get_performance_mode_status(self):
        """获取性能模式状态"""
        return {
            'performance_mode_enabled': self.performance_mode_enabled,
            'trigger_frame': self.performance_mode_trigger_frame,
            'current_frame': self.vr_manager.frame_count,
            'will_trigger_at_frame': self.performance_mode_trigger_frame if not self.performance_mode_enabled else None,
            'gc_interval_normal': self._manual_gc_interval,
            'gc_interval_performance': self._manual_gc_interval * 2,
        }