"""
VR动作系统模块

基于OpenVR Action系统，提供高级的输入处理和动作映射：
- VR动作清单管理
- 按钮和轴输入处理
- 触觉反馈
- 动作集管理
"""

import json
import os
from pathlib import Path
from direct.showbase.DirectObject import DirectObject

try:
    import openvr
    OPENVR_AVAILABLE = True
except ImportError:
    OPENVR_AVAILABLE = False


class VRActionManager(DirectObject):
    """VR动作管理器 - 处理OpenVR动作系统"""

    def __init__(self, vr_manager):
        """初始化VR动作管理器

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

        self.vr_manager = vr_manager
        self.vr_input = None
        self.action_set_handles = []
        self.action_handles = {}

        # 预定义的标准动作
        self.standard_actions = {
            # 姿态动作
            'pose': '/actions/default/in/Pose',

            # 按钮动作
            'trigger': '/actions/default/in/Trigger',
            'grip': '/actions/default/in/Grip',
            'menu': '/actions/default/in/Menu',
            'system': '/actions/default/in/System',
            'trackpad_click': '/actions/default/in/TrackpadClick',
            'trackpad_touch': '/actions/default/in/TrackpadTouch',
            'a_button': '/actions/default/in/AButton',
            'b_button': '/actions/default/in/BButton',

            # 轴动作
            'trackpad': '/actions/default/in/Trackpad',
            'joystick': '/actions/default/in/Joystick',
            'squeeze': '/actions/default/in/Squeeze',

            # 震动输出
            'haptic': '/actions/default/out/Haptic'
        }

        # 动作集
        self.default_action_set = '/actions/default'

        print("✓ VR动作管理器初始化完成")

    def initialize(self):
        """初始化VR动作系统"""
        if not OPENVR_AVAILABLE or not self.vr_manager.vr_system:
            print("⚠️ VR系统不可用，无法初始化动作系统")
            return False

        try:
            print("🎮 正在初始化VR动作系统...")

            # 获取VR输入接口
            self.vr_input = openvr.VRInput()
            if not self.vr_input:
                print("❌ 无法获取VR输入接口")
                return False

            # 创建动作清单文件
            manifest_path = self._create_action_manifest()
            if not manifest_path:
                print("❌ 无法创建动作清单")
                return False

            # 加载动作清单
            error = self.vr_input.setActionManifestPath(manifest_path)
            if error != openvr.VRInputError_None:
                print(f"❌ 加载动作清单失败: {error}")
                return False

            # 获取动作句柄
            self._load_action_handles()

            # 创建动作集
            self._setup_action_sets()

            print("✅ VR动作系统初始化成功")
            return True

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

    def _create_action_manifest(self):
        """创建VR动作清单文件"""
        try:
            # 动作清单配置
            manifest_data = {
                "actions": [
                    # 姿态动作
                    {
                        "name": "/actions/default/in/Pose",
                        "type": "pose"
                    },

                    # 数字动作（按钮）
                    {
                        "name": "/actions/default/in/Trigger",
                        "type": "boolean"
                    },
                    {
                        "name": "/actions/default/in/Grip",
                        "type": "boolean"
                    },
                    {
                        "name": "/actions/default/in/Menu",
                        "type": "boolean"
                    },
                    {
                        "name": "/actions/default/in/System",
                        "type": "boolean"
                    },
                    {
                        "name": "/actions/default/in/TrackpadClick",
                        "type": "boolean"
                    },
                    {
                        "name": "/actions/default/in/TrackpadTouch",
                        "type": "boolean"
                    },
                    {
                        "name": "/actions/default/in/AButton",
                        "type": "boolean"
                    },
                    {
                        "name": "/actions/default/in/BButton",
                        "type": "boolean"
                    },

                    # 模拟动作（轴）
                    {
                        "name": "/actions/default/in/Trackpad",
                        "type": "vector2"
                    },
                    {
                        "name": "/actions/default/in/Joystick",
                        "type": "vector2"
                    },
                    {
                        "name": "/actions/default/in/Squeeze",
                        "type": "vector1"
                    },

                    # 震动输出
                    {
                        "name": "/actions/default/out/Haptic",
                        "type": "vibration"
                    }
                ],

                "action_sets": [
                    {
                        "name": "/actions/default",
                        "usage": "single"
                    }
                ],

                "default_bindings": [
                    {
                        "controller_type": "vive_controller",
                        "binding_url": "bindings_vive.json"
                    },
                    {
                        "controller_type": "oculus_touch",
                        "binding_url": "bindings_oculus.json"
                    },
                    {
                        "controller_type": "knuckles",
                        "binding_url": "bindings_index.json"
                    }
                ],

                "localization": [
                    {
                        "language_tag": "zh_CN",
                        "/actions/default/in/Trigger": "扳机",
                        "/actions/default/in/Grip": "握把",
                        "/actions/default/in/Menu": "菜单",
                        "/actions/default/in/System": "系统",
                        "/actions/default/in/TrackpadClick": "触摸板点击",
                        "/actions/default/in/TrackpadTouch": "触摸板触摸",
                        "/actions/default/in/Pose": "手部姿态",
                        "/actions/default/out/Haptic": "震动反馈"
                    }
                ]
            }

            # 保存到临时目录
            manifest_dir = Path.cwd() / "vr_actions"
            manifest_dir.mkdir(exist_ok=True)

            manifest_path = manifest_dir / "actions.json"
            with open(manifest_path, 'w', encoding='utf-8') as f:
                json.dump(manifest_data, f, indent=2, ensure_ascii=False)

            # 创建基本的绑定文件
            self._create_default_bindings(manifest_dir)

            print(f"✓ 动作清单已创建: {manifest_path}")
            return str(manifest_path)

        except Exception as e:
            print(f"❌ 创建动作清单失败: {e}")
            return None

    def _create_default_bindings(self, manifest_dir):
        """创建默认的控制器绑定文件"""
        # Vive控制器绑定
        vive_bindings = {
            "controller_type": "vive_controller",
            "description": "Vive控制器绑定",
            "name": "EG VR Editor - Vive",
            "bindings": {
                "/actions/default": {
                    "sources": [
                        {
                            "inputs": {
                                "click": {
                                    "output": "/actions/default/in/Trigger"
                                }
                            },
                            "mode": "button",
                            "path": "/user/hand/left/input/trigger"
                        },
                        {
                            "inputs": {
                                "click": {
                                    "output": "/actions/default/in/Trigger"
                                }
                            },
                            "mode": "button",
                            "path": "/user/hand/right/input/trigger"
                        },
                        {
                            "inputs": {
                                "click": {
                                    "output": "/actions/default/in/Grip"
                                }
                            },
                            "mode": "button",
                            "path": "/user/hand/left/input/grip"
                        },
                        {
                            "inputs": {
                                "click": {
                                    "output": "/actions/default/in/Grip"
                                }
                            },
                            "mode": "button",
                            "path": "/user/hand/right/input/grip"
                        },
                        {
                            "inputs": {
                                "click": {
                                    "output": "/actions/default/in/Menu"
                                }
                            },
                            "mode": "button",
                            "path": "/user/hand/left/input/menu"
                        },
                        {
                            "inputs": {
                                "position": {
                                    "output": "/actions/default/in/Trackpad"
                                },
                                "click": {
                                    "output": "/actions/default/in/TrackpadClick"
                                },
                                "touch": {
                                    "output": "/actions/default/in/TrackpadTouch"
                                }
                            },
                            "mode": "trackpad",
                            "path": "/user/hand/left/input/trackpad"
                        },
                        {
                            "inputs": {
                                "position": {
                                    "output": "/actions/default/in/Trackpad"
                                },
                                "click": {
                                    "output": "/actions/default/in/TrackpadClick"
                                },
                                "touch": {
                                    "output": "/actions/default/in/TrackpadTouch"
                                }
                            },
                            "mode": "trackpad",
                            "path": "/user/hand/right/input/trackpad"
                        }
                    ],
                    "poses": [
                        {
                            "output": "/actions/default/in/Pose",
                            "path": "/user/hand/left/pose/raw"
                        },
                        {
                            "output": "/actions/default/in/Pose",
                            "path": "/user/hand/right/pose/raw"
                        }
                    ],
                    "haptics": [
                        {
                            "output": "/actions/default/out/Haptic",
                            "path": "/user/hand/left/output/haptic"
                        },
                        {
                            "output": "/actions/default/out/Haptic",
                            "path": "/user/hand/right/output/haptic"
                        }
                    ]
                }
            }
        }

        bindings_path = manifest_dir / "bindings_vive.json"
        with open(bindings_path, 'w', encoding='utf-8') as f:
            json.dump(vive_bindings, f, indent=2)

        print(f"✓ Vive控制器绑定已创建: {bindings_path}")

    def _load_action_handles(self):
        """加载动作句柄"""
        if not self.vr_input:
            return

        try:
            for action_name, action_path in self.standard_actions.items():
                handle = self.vr_input.getActionHandle(action_path)
                self.action_handles[action_name] = handle
                print(f"✓ 加载动作: {action_name} -> {handle}")

        except Exception as e:
            print(f"⚠️ 加载动作句柄失败: {e}")

    def _setup_action_sets(self):
        """设置动作集"""
        if not self.vr_input:
            return

        try:
            # 获取默认动作集句柄
            action_set_handle = self.vr_input.getActionSetHandle(self.default_action_set)
            self.action_set_handles = [action_set_handle]

            print(f"✓ 动作集已设置: {self.default_action_set}")

        except Exception as e:
            print(f"⚠️ 设置动作集失败: {e}")

    def update_actions(self):
        """更新动作状态 - 每帧调用"""
        if not self.vr_input or not self.action_set_handles:
            return

        try:
            # 更新动作状态
            action_sets = (openvr.VRActiveActionSet_t * len(self.action_set_handles))()
            for i, action_set_handle in enumerate(self.action_set_handles):
                action_sets[i].ulActionSet = action_set_handle

            self.vr_input.updateActionState(action_sets)

        except Exception as e:
            # 限制错误输出频率
            if not hasattr(self, '_last_action_error_frame'):
                self._last_action_error_frame = 0

            if hasattr(self.vr_manager, 'frame_count'):
                if self.vr_manager.frame_count - self._last_action_error_frame > 300:  # 每5秒输出一次
                    print(f"⚠️ 更新动作状态失败: {e}")
                    self._last_action_error_frame = self.vr_manager.frame_count

    def is_digital_action_pressed(self, action_name, device_path=None):
        """检查数字动作是否被按下

        Args:
            action_name: 动作名称
            device_path: 设备路径（可选）

        Returns:
            tuple: (是否按下, 设备路径)
        """
        if not self.vr_input or action_name not in self.action_handles:
            return False, None

        try:
            action_handle = self.action_handles[action_name]
            device_handle = openvr.k_ulInvalidInputValueHandle

            if device_path:
                device_handle = self.vr_input.getInputSourceHandle(device_path)

            action_data = self.vr_input.getDigitalActionData(action_handle, device_handle)

            if device_path and action_data.bActive:
                origin_info = self.vr_input.getOriginTrackedDeviceInfo(action_data.activeOrigin)
                device_path = origin_info.devicePath

            return action_data.bActive and action_data.bState, device_path

        except Exception as e:
            return False, None

    def is_digital_action_just_pressed(self, action_name, device_path=None):
        """检查数字动作是否刚刚被按下（上升沿）"""
        if not self.vr_input or action_name not in self.action_handles:
            return False, None

        try:
            action_handle = self.action_handles[action_name]
            device_handle = openvr.k_ulInvalidInputValueHandle

            if device_path:
                device_handle = self.vr_input.getInputSourceHandle(device_path)

            action_data = self.vr_input.getDigitalActionData(action_handle, device_handle)

            if device_path and action_data.bActive:
                origin_info = self.vr_input.getOriginTrackedDeviceInfo(action_data.activeOrigin)
                device_path = origin_info.devicePath

            return action_data.bActive and action_data.bChanged and action_data.bState, device_path

        except Exception as e:
            return False, None

    def is_digital_action_just_released(self, action_name, device_path=None):
        """检查数字动作是否刚刚被释放（下降沿）"""
        if not self.vr_input or action_name not in self.action_handles:
            return False, None

        try:
            action_handle = self.action_handles[action_name]
            device_handle = openvr.k_ulInvalidInputValueHandle

            if device_path:
                device_handle = self.vr_input.getInputSourceHandle(device_path)

            action_data = self.vr_input.getDigitalActionData(action_handle, device_handle)

            if device_path and action_data.bActive:
                origin_info = self.vr_input.getOriginTrackedDeviceInfo(action_data.activeOrigin)
                device_path = origin_info.devicePath

            return action_data.bActive and action_data.bChanged and not action_data.bState, device_path

        except Exception as e:
            return False, None

    def get_analog_action_value(self, action_name, device_path=None):
        """获取模拟动作值

        Args:
            action_name: 动作名称
            device_path: 设备路径（可选）

        Returns:
            tuple: (值, 设备路径) - 值为Vec2(x,y)对于vector2，float对于vector1
        """
        if not self.vr_input or action_name not in self.action_handles:
            return None, None

        try:
            action_handle = self.action_handles[action_name]
            device_handle = openvr.k_ulInvalidInputValueHandle

            if device_path:
                device_handle = self.vr_input.getInputSourceHandle(device_path)

            analog_data = self.vr_input.getAnalogActionData(action_handle, device_handle)

            if device_path and analog_data.bActive:
                origin_info = self.vr_input.getOriginTrackedDeviceInfo(analog_data.activeOrigin)
                device_path = origin_info.devicePath

            if analog_data.bActive:
                # 根据动作类型返回适当的值
                from panda3d.core import Vec2
                if action_name in ['trackpad', 'joystick']:
                    return Vec2(analog_data.x, analog_data.y), device_path
                else:
                    return analog_data.x, device_path

            return None, device_path

        except Exception as e:
            return None, None

    def get_pose_action_data(self, action_name, device_path=None):
        """获取姿态动作数据"""
        if not self.vr_input or action_name not in self.action_handles:
            return None

        try:
            action_handle = self.action_handles[action_name]
            device_handle = openvr.k_ulInvalidInputValueHandle

            if device_path:
                device_handle = self.vr_input.getInputSourceHandle(device_path)

            pose_data = self.vr_input.getPoseActionDataForNextFrame(
                action_handle,
                openvr.TrackingUniverseStanding,
                device_handle
            )

            return pose_data

        except Exception as e:
            return None

    def trigger_haptic_pulse(self, action_name, duration=0.001, frequency=1.0, amplitude=1.0, device_path=None):
        """触发震动反馈

        Args:
            action_name: 震动动作名称
            duration: 持续时间（秒）
            frequency: 频率
            amplitude: 振幅 (0.0-1.0)
            device_path: 设备路径（可选）
        """
        if not self.vr_input or action_name not in self.action_handles:
            return False

        try:
            action_handle = self.action_handles[action_name]
            device_handle = openvr.k_ulInvalidInputValueHandle

            if device_path:
                device_handle = self.vr_input.getInputSourceHandle(device_path)

            # 触发震动
            self.vr_input.triggerHapticVibrationAction(
                action_handle,
                0,  # 开始时间
                duration,
                frequency,
                amplitude,
                device_handle
            )

            return True

        except Exception as e:
            print(f"⚠️ 触发震动反馈失败: {e}")
            return False

    def cleanup(self):
        """清理资源"""
        self.ignoreAll()

        # 清理动作句柄
        self.action_handles.clear()
        self.action_set_handles.clear()

        print("🧹 VR动作管理器已清理")