"""
VR专用阴影Stage

为VR渲染管线提供阴影支持。采用智能复用策略:
- 默认复用主Pipeline的ShadowAtlas(从桌面相机视角)
- 可选:为VR创建独立ShadowAtlas(性能开销较大)

设计考虑:
1. VR左右眼视差小,共享阴影合理
2. 性能优先,避免重复渲染阴影
3. 保留扩展性,支持未来独立阴影渲染
"""

from panda3d.core import SamplerState
from RenderPipelineFile.rpcore.render_target import RenderTarget


class VRShadowStage:
    """VR阴影Stage - 为VR提供阴影数据"""

    def __init__(self, name, pipeline, use_shared_atlas=True):
        """
        初始化VR阴影Stage

        Args:
            name: stage名称
            pipeline: RenderPipeline实例引用
            use_shared_atlas: 是否使用主Pipeline的ShadowAtlas(默认True)
        """
        self.name = name
        self.pipeline = pipeline
        self.use_shared_atlas = use_shared_atlas
        self.target = None
        self.shadow_atlas_tex = None
        self.shadow_atlas_pcf_state = None

    def create(self, width, height):
        """
        创建阴影Stage

        Args:
            width: VR眼睛渲染宽度(参考,阴影atlas不一定使用此分辨率)
            height: VR眼睛渲染高度
        """
        print(f"🌑 创建{self.name} 阴影Stage")

        if self.use_shared_atlas:
            # 方案A: 复用主Pipeline的ShadowAtlas
            return self._create_shared_shadow_atlas()
        else:
            # 方案B: 创建VR独立的ShadowAtlas
            return self._create_independent_shadow_atlas(width, height)

    def _create_shared_shadow_atlas(self):
        """复用主Pipeline的ShadowAtlas(推荐方案)"""
        try:
            # 从主Pipeline获取ShadowStage
            shadow_stage = None
            if hasattr(self.pipeline, 'stage_mgr'):
                # 查找主Pipeline的ShadowStage
                for stage in self.pipeline.stage_mgr.stages:
                    if stage.__class__.__name__ == 'ShadowStage':
                        shadow_stage = stage
                        break

            if not shadow_stage:
                print("   ⚠️ 主Pipeline的ShadowStage不存在")
                # 尝试从pipes获取
                pipes = self.pipeline.stage_mgr.pipes
                if "ShadowAtlas" in pipes and "ShadowAtlasPCF" in pipes:
                    self.shadow_atlas_tex = pipes["ShadowAtlas"]
                    shadow_atlas_pcf_tuple = pipes["ShadowAtlasPCF"]
                    if isinstance(shadow_atlas_pcf_tuple, tuple) and len(shadow_atlas_pcf_tuple) >= 2:
                        self.shadow_atlas_pcf_state = shadow_atlas_pcf_tuple[1]
                    print("   ✅ 从pipes获取到ShadowAtlas")
                    return True
                else:
                    print("   ❌ pipes中也没有ShadowAtlas")
                    return False

            # 从ShadowStage获取atlas
            if hasattr(shadow_stage, 'target') and shadow_stage.target:
                self.shadow_atlas_tex = shadow_stage.target.depth_tex
                self.shadow_atlas_pcf_state = self._make_pcf_state()
                print("   ✅ 复用主Pipeline的ShadowAtlas")
                print(f"      Atlas分辨率: {shadow_stage.size}x{shadow_stage.size}")
                print(f"      优点: 零额外开销,与桌面视图共享阴影")
                print(f"      注意: 阴影从桌面相机视角渲染")
                return True
            else:
                print("   ❌ ShadowStage.target不存在")
                return False

        except Exception as e:
            print(f"   ❌ 复用ShadowAtlas失败: {e}")
            import traceback
            traceback.print_exc()
            return False

    def _create_independent_shadow_atlas(self, width, height):
        """为VR创建独立的ShadowAtlas(高级方案)"""
        try:
            print("   创建VR独立ShadowAtlas...")
            print("   ⚠️ 此方案需要额外实现阴影渲染逻辑")
            print("   ⚠️ 当前版本暂不支持,请使用共享模式")

            # TODO: 未来实现
            # 1. 创建VR专用的shadow atlas buffer
            # 2. 为VR相机视角设置shadow manager
            # 3. 渲染VR视角的阴影到独立atlas
            # 4. 性能开销: 需要为VR单独渲染一次所有阴影

            return False

        except Exception as e:
            print(f"   ❌ 创建独立ShadowAtlas失败: {e}")
            return False

    def _make_pcf_state(self):
        """创建PCF(Percentage Closer Filtering)采样器状态"""
        state = SamplerState()
        state.set_minfilter(SamplerState.FT_shadow)
        state.set_magfilter(SamplerState.FT_shadow)
        return state

    def get_shadow_atlas_tex(self):
        """获取阴影Atlas纹理"""
        return self.shadow_atlas_tex

    def get_shadow_atlas_pcf(self):
        """获取带PCF的阴影Atlas(纹理+采样状态的元组)"""
        if self.shadow_atlas_tex and self.shadow_atlas_pcf_state:
            return (self.shadow_atlas_tex, self.shadow_atlas_pcf_state)
        return None

    def bind_to_stage(self, target_stage):
        """
        将阴影数据绑定到目标stage(通常是lighting stage)

        Args:
            target_stage: 需要阴影数据的目标stage(VRLightingStage等)
        """
        if not target_stage or not hasattr(target_stage, 'target'):
            print(f"   ⚠️ 无法绑定阴影到无效的stage")
            return False

        try:
            # 绑定阴影atlas纹理
            if self.shadow_atlas_tex:
                target_stage.target.set_shader_input("ShadowAtlas", self.shadow_atlas_tex)

            # 绑定PCF阴影atlas
            pcf_tuple = self.get_shadow_atlas_pcf()
            if pcf_tuple:
                target_stage.target.set_shader_input("ShadowAtlasPCF", *pcf_tuple)

            print(f"   ✅ 阴影数据已绑定到 {target_stage.name}")
            return True

        except Exception as e:
            print(f"   ⚠️ 绑定阴影数据失败: {e}")
            return False

    def cleanup(self):
        """清理资源"""
        # 如果使用共享atlas,不需要清理
        # 如果创建了独立atlas,需要在这里释放
        if self.target:
            self.target.remove()
            self.target = None
        self.shadow_atlas_tex = None
        self.shadow_atlas_pcf_state = None
        print(f"✓ {self.name} 阴影Stage已清理")
