"""
VR传送系统模块

提供VR传送功能：
- 抛物线轨迹计算和可视化
- 传送点有效性检测
- 传送执行
- 可视化反馈（抛物线、落点标记）
"""

import math
from panda3d.core import (
    Vec3, Vec4, Mat4, Point3, CollisionRay, CollisionTraverser,
    CollisionNode, CollisionHandlerQueue, BitMask32, NodePath,
    CollisionSphere, CollisionPlane, LineSegs, GeomNode, Material,
    RenderState, TransparencyAttrib, ColorAttrib
)
from direct.showbase.DirectObject import DirectObject


class VRTeleportSystem(DirectObject):
    """VR传送系统 - 处理传送功能和可视化"""

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

        Args:
            vr_manager: VR管理器实例
        """
        super().__init__()

        self.vr_manager = vr_manager
        self.world = vr_manager.world if hasattr(vr_manager, 'world') else None

        # 传送参数
        self.teleport_range = 20.0          # 最大传送距离
        self.arc_resolution = 50            # 抛物线精度
        self.gravity = -9.8                 # 重力系数
        self.initial_velocity = 10.0        # 初始速度
        self.min_teleport_distance = 1.0    # 最小传送距离
        self.player_height_offset = 1.7     # 玩家站立高度偏移（米）

        # 可视化元素
        self.teleport_arc_node = None       # 抛物线节点
        self.teleport_target_node = None    # 落点标记节点
        self.teleport_invalid_node = None   # 无效位置标记

        # 传送状态
        self.is_teleport_active = False     # 是否正在预览传送
        self.teleport_target_pos = None     # 传送目标位置
        self.teleport_valid = False         # 传送位置是否有效
        self.active_controller = None       # 正在使用传送的控制器

        # 碰撞检测
        self.teleport_collision_traverser = CollisionTraverser()
        self.teleport_collision_queue = CollisionHandlerQueue()

        # 可视化颜色
        self.valid_arc_color = Vec4(0.2, 0.9, 0.2, 0.8)      # 绿色抛物线
        self.invalid_arc_color = Vec4(0.9, 0.2, 0.2, 0.8)    # 红色抛物线
        self.target_color = Vec4(0.2, 0.7, 1.0, 0.9)         # 蓝色落点

        print("✓ VR传送系统初始化完成")

    def initialize(self):
        """初始化传送系统"""
        try:
            print("🔧 正在初始化VR传送系统...")

            # 创建可视化元素
            self._create_teleport_visuals()

            # 设置地面检测
            self._setup_ground_detection()

            print("✅ VR传送系统初始化成功")
            return True

        except Exception as e:
            print(f"❌ VR传送系统初始化失败: {e}")
            import traceback
            traceback.print_exc()
            return False

    def _create_teleport_visuals(self):
        """创建传送可视化元素"""
        if not self.world or not hasattr(self.world, 'render'):
            print("⚠️ 无法创建传送可视化 - 缺少世界渲染节点")
            return

        # 创建抛物线节点
        self.teleport_arc_node = self.world.render.attachNewNode("teleport_arc")
        self.teleport_arc_node.hide()  # 初始隐藏

        # 创建落点标记
        self._create_target_marker()

        # 创建无效位置标记
        self._create_invalid_marker()

        print("✓ 传送可视化元素已创建")

    def _create_target_marker(self):
        """创建传送目标标记"""
        try:
            # 创建一个圆形平台作为落点标记
            from panda3d.core import CardMaker

            cm = CardMaker("teleport_target")
            cm.setFrame(-1, 1, -1, 1)  # 2x2的平面

            self.teleport_target_node = self.world.render.attachNewNode(cm.generate())
            self.teleport_target_node.setScale(1.0)  # 2米直径的圆形
            self.teleport_target_node.setP(-90)  # 平放在地面
            self.teleport_target_node.setColor(self.target_color)
            self.teleport_target_node.setTransparency(TransparencyAttrib.MAlpha)
            self.teleport_target_node.hide()

            # 添加PBR材质以兼容RenderPipeline
            material = Material()
            material.setBaseColor(self.target_color)
            material.setRoughness(0.8)
            material.setMetallic(0.0)
            material.setRefractiveIndex(1.5)
            self.teleport_target_node.setMaterial(material, 1)

        except Exception as e:
            print(f"⚠️ 创建传送目标标记失败: {e}")

    def _create_invalid_marker(self):
        """创建无效位置标记"""
        try:
            from panda3d.core import CardMaker

            cm = CardMaker("teleport_invalid")
            cm.setFrame(-0.8, 0.8, -0.8, 0.8)  # 稍小的红色叉号

            self.teleport_invalid_node = self.world.render.attachNewNode(cm.generate())
            self.teleport_invalid_node.setScale(1.0)
            self.teleport_invalid_node.setP(-90)
            self.teleport_invalid_node.setColor(self.invalid_arc_color)
            self.teleport_invalid_node.setTransparency(TransparencyAttrib.MAlpha)
            self.teleport_invalid_node.hide()

            # 添加PBR材质
            material = Material()
            material.setBaseColor(self.invalid_arc_color)
            material.setRoughness(0.8)
            material.setMetallic(0.0)
            material.setRefractiveIndex(1.5)
            self.teleport_invalid_node.setMaterial(material, 1)

        except Exception as e:
            print(f"⚠️ 创建无效位置标记失败: {e}")

    def _setup_ground_detection(self):
        """设置地面检测"""
        try:
            # 假设地面在Z=0平面，使用正确的CollisionPlane API
            from panda3d.core import Plane
            ground_plane = CollisionPlane(Plane(Vec3(0, 0, 1), Point3(0, 0, 0)))

            ground_node = CollisionNode("ground_detection")
            ground_node.addSolid(ground_plane)
            ground_node.setIntoCollideMask(BitMask32.bit(1))  # 地面碰撞掩码

            # 附加到渲染节点
            if self.world and hasattr(self.world, 'render'):
                ground_node_path = self.world.render.attachNewNode(ground_node)
                print("✓ 地面检测设置成功")

        except Exception as e:
            print(f"⚠️ 设置地面检测失败: {e}")
            # 继续运行，不让这个错误阻止传送系统

    def start_teleport_preview(self, controller, direction):
        """开始传送预览

        Args:
            controller: VR控制器实例
            direction: 传送方向向量（摇杆输入转换的世界方向）
        """
        if not controller or not controller.anchor_node:
            return False

        self.is_teleport_active = True
        self.active_controller = controller

        # 计算抛物线轨迹
        start_pos = controller.get_world_position()
        self._calculate_teleport_trajectory(start_pos, direction)

        # 显示可视化
        self._show_teleport_visuals()

        return True

    def _calculate_teleport_trajectory(self, start_pos, direction):
        """计算传送抛物线轨迹

        Args:
            start_pos: 起始位置
            direction: 方向向量
        """
        try:
            # 确保方向向量已标准化
            direction = direction.normalized()

            # 计算抛物线点
            trajectory_points = []
            hit_ground = False
            self.teleport_valid = False

            # 初始速度向量
            velocity = direction * self.initial_velocity
            velocity.z += 2.0  # 给一些向上的初始速度

            dt = 0.05  # 时间步长
            current_pos = Vec3(start_pos)
            current_velocity = Vec3(velocity)

            for i in range(self.arc_resolution):
                trajectory_points.append(Point3(current_pos))

                # 更新位置和速度
                current_pos += current_velocity * dt
                current_velocity.z += self.gravity * dt  # 应用重力

                # 检查是否碰撞地面
                if current_pos.z <= 0.1:  # 假设地面在z=0
                    # 精确计算落地点
                    ground_pos = self._calculate_ground_intersection(
                        trajectory_points[-2] if len(trajectory_points) > 1 else start_pos,
                        current_pos
                    )
                    trajectory_points.append(ground_pos)

                    # 检查传送有效性
                    distance = (ground_pos - start_pos).length()
                    if (distance >= self.min_teleport_distance and
                        distance <= self.teleport_range):
                        self.teleport_target_pos = ground_pos
                        self.teleport_valid = True
                    else:
                        self.teleport_target_pos = ground_pos
                        self.teleport_valid = False

                    hit_ground = True
                    break

                # 超出范围
                if (current_pos - start_pos).length() > self.teleport_range:
                    break

            # 如果没有碰撞地面，传送无效
            if not hit_ground:
                if trajectory_points:
                    self.teleport_target_pos = trajectory_points[-1]
                self.teleport_valid = False

            # 创建抛物线几何体
            self._create_arc_geometry(trajectory_points)

        except Exception as e:
            print(f"⚠️ 计算传送轨迹失败: {e}")
            self.teleport_valid = False

    def _calculate_ground_intersection(self, p1, p2):
        """计算与地面的精确交点"""
        if p1.z == p2.z:
            return Point3(p2)

        # 线性插值找到z=0的点
        t = -p1.z / (p2.z - p1.z)
        t = max(0, min(1, t))  # 限制在0-1范围内

        intersection = p1 + (p2 - p1) * t
        intersection.z = 0.1  # 稍微高于地面

        return Point3(intersection)

    def _create_arc_geometry(self, points):
        """创建抛物线几何体"""
        if not points or len(points) < 2:
            return

        try:
            # 创建线段
            line_segs = LineSegs()
            line_segs.setThickness(3)

            # 根据有效性设置颜色
            color = self.valid_arc_color if self.teleport_valid else self.invalid_arc_color
            line_segs.setColor(color)

            # 添加线段点
            line_segs.moveTo(points[0])
            for point in points[1:]:
                line_segs.drawTo(point)

            # 清除旧的几何体
            self.teleport_arc_node.removeNode()
            self.teleport_arc_node = self.world.render.attachNewNode("teleport_arc")

            # 创建新的几何体
            geom_node = line_segs.create()
            arc_node_path = self.teleport_arc_node.attachNewNode(geom_node)

            # 设置材质
            material = Material()
            material.setBaseColor(color)
            material.setRoughness(0.1)
            material.setMetallic(0.0)
            material.setRefractiveIndex(1.5)
            arc_node_path.setMaterial(material, 1)

            # 设置透明度
            arc_node_path.setTransparency(TransparencyAttrib.MAlpha)

        except Exception as e:
            print(f"⚠️ 创建抛物线几何体失败: {e}")

    def _show_teleport_visuals(self):
        """显示传送可视化"""
        if self.teleport_arc_node:
            self.teleport_arc_node.show()

        if self.teleport_target_pos:
            if self.teleport_valid and self.teleport_target_node:
                # 显示有效的传送目标
                self.teleport_target_node.setPos(self.teleport_target_pos)
                self.teleport_target_node.show()
                self.teleport_invalid_node.hide()
            elif self.teleport_invalid_node:
                # 显示无效的传送位置
                self.teleport_invalid_node.setPos(self.teleport_target_pos)
                self.teleport_invalid_node.show()
                self.teleport_target_node.hide()

    def stop_teleport_preview(self):
        """停止传送预览"""
        self.is_teleport_active = False
        self.active_controller = None

        # 隐藏可视化
        if self.teleport_arc_node:
            self.teleport_arc_node.hide()
        if self.teleport_target_node:
            self.teleport_target_node.hide()
        if self.teleport_invalid_node:
            self.teleport_invalid_node.hide()

    def execute_teleport(self):
        """执行传送"""
        if not self.teleport_valid or not self.teleport_target_pos:
            print("⚠️ 传送位置无效，无法执行传送")
            return False

        try:
            # 计算传送偏移
            if self.vr_manager.tracking_space:
                current_pos = self.vr_manager.tracking_space.getPos()

                # 计算水平偏移（只考虑XY平面）
                controller_pos = self.active_controller.get_world_position()
                horizontal_offset = Vec3(
                    self.teleport_target_pos.x - controller_pos.x,
                    self.teleport_target_pos.y - controller_pos.y,
                    0
                )

                # 计算新位置：保持水平偏移，设置固定站立高度
                new_pos = current_pos + horizontal_offset
                new_pos.z = self.teleport_target_pos.z + self.player_height_offset

                # 执行传送
                self.vr_manager.tracking_space.setPos(new_pos)

                print(f"✅ 传送成功: {current_pos} → {new_pos} (高度偏移: {self.player_height_offset}m)")

                # 停止预览
                self.stop_teleport_preview()

                return True
            else:
                print("⚠️ 无法获取VR跟踪空间，传送失败")
                return False

        except Exception as e:
            print(f"❌ 执行传送失败: {e}")
            return False

    def update_teleport_preview(self, controller, direction):
        """更新传送预览（摇杆移动时调用）"""
        if self.is_teleport_active and controller == self.active_controller:
            start_pos = controller.get_world_position()
            self._calculate_teleport_trajectory(start_pos, direction)
            self._show_teleport_visuals()

    def cleanup(self):
        """清理传送系统资源"""
        try:
            self.stop_teleport_preview()

            if self.teleport_arc_node:
                self.teleport_arc_node.removeNode()
                self.teleport_arc_node = None

            if self.teleport_target_node:
                self.teleport_target_node.removeNode()
                self.teleport_target_node = None

            if self.teleport_invalid_node:
                self.teleport_invalid_node.removeNode()
                self.teleport_invalid_node = None

            self.ignoreAll()

            print("🧹 VR传送系统已清理")

        except Exception as e:
            print(f"⚠️ 清理传送系统失败: {e}")