from direct.task.TaskManagerGlobal import taskMgr


class CustomMouseController:
    def __init__(self, showbase):
        self.showbase = showbase
        # This is used to store which keys are currently pressed.
        self.keyMap = {
            # "mouse1": 0,  # 移除左键，用于选择功能
            "mouse3": 0,  # 右键
            "cam-forward": 0,
            "cam-backward": 0,
            "cam-left": 0,
            "cam-right": 0,
            "cam-up": 0,
            "cam-down": 0
        }
        
        # 添加鼠标控制 - 只保留右键控制，左键用于选择
        # self.showbase.accept("mouse1", self.setKey, ["mouse1", True])  # 移除左键绑定
        # self.showbase.accept("mouse1-up", self.setKey, ["mouse1", False])  # 移除左键绑定
        self.showbase.accept("mouse3", self.setKey, ["mouse3", True])  # 右键
        self.showbase.accept("mouse3-up", self.setKey, ["mouse3", False])  # 右键释放
        
        self.showbase.accept("w", self.setKey, ["cam-forward", True])
        self.showbase.accept("a", self.setKey, ["cam-left", True])
        self.showbase.accept("s", self.setKey, ["cam-backward", True])
        self.showbase.accept("d", self.setKey, ["cam-right", True])
        self.showbase.accept("e", self.setKey, ["cam-up", True])
        self.showbase.accept("q", self.setKey, ["cam-down", True])
        
        self.showbase.accept("w-up", self.setKey, ["cam-forward", False])
        self.showbase.accept("a-up", self.setKey, ["cam-left", False])
        self.showbase.accept("s-up", self.setKey, ["cam-backward", False])
        self.showbase.accept("d-up", self.setKey, ["cam-right", False])
        self.showbase.accept("e-up", self.setKey, ["cam-up", False])
        self.showbase.accept("q-up", self.setKey, ["cam-down", False])
        
        self.last_mouse_x = 0
        self.last_mouse_y = 0
        
        self.camera_speed = 25
        self.move_speed = 20
    
    def setUp(self, mouse_speed: float = 25, move_speed: float = 20):
        taskMgr.add(self.move, "moveTask")
        self.camera_speed = mouse_speed
        self.move_speed = move_speed
    
    def setKey(self, key, value, arg: str = None):
        self.keyMap[key] = value
        # 只在右键按下时记录鼠标位置
        if key == "mouse3" and value == True:
            mouse_pos = self.showbase.mouseWatcherNode.getMouse()
            if mouse_pos:
                self.last_mouse_x = mouse_pos.get_x()
                self.last_mouse_y = mouse_pos.get_y()
    
    def move(self, task):
        dt = self.showbase.clock.dt
        
        # 检查ImGui是否捕获了键盘输入
        if self._should_handle_keyboard():
            if self.keyMap["cam-left"]:
                self.showbase.camera.setX(self.showbase.camera, -self.move_speed * dt)
            if self.keyMap["cam-right"]:
                self.showbase.camera.setX(self.showbase.camera, +self.move_speed * dt)
            if self.keyMap["cam-backward"]:
                self.showbase.camera.setY(self.showbase.camera, -self.move_speed * dt)
            if self.keyMap["cam-forward"]:
                self.showbase.camera.setY(self.showbase.camera, +self.move_speed * dt)
            if self.keyMap["cam-up"]:
                self.showbase.camera.setZ(self.showbase.camera, +self.move_speed * dt)
            if self.keyMap["cam-down"]:
                self.showbase.camera.setZ(self.showbase.camera, -self.move_speed * dt)
        if self.keyMap["mouse3"]:  # 只使用右键控制视角旋转
            try:
                # 检查是否应该处理鼠标事件（避免与ImGui冲突）
                if self._should_handle_mouse():
                    mouse_pos = self.showbase.mouseWatcherNode.getMouse()
                    if mouse_pos:
                        current_x = mouse_pos.get_x()
                        current_y = mouse_pos.get_y()
                        
                        # 计算鼠标移动差值
                        dx = current_x - self.last_mouse_x
                        dy = current_y - self.last_mouse_y
                        dy *= -1
                        
                        # 根据鼠标移动调整摄像机
                        if abs(dx) > 0.01 or abs(dy) > 0.01:
                            cam_hpr = self.showbase.camera.get_hpr()
                            self.showbase.camera.set_hpr(
                                cam_hpr.x - dx * self.camera_speed,
                                max(-90, min(90, cam_hpr.y - dy * self.camera_speed)),
                                0
                            )
                        
                        # 更新鼠标位置
                        self.last_mouse_x = current_x
                        self.last_mouse_y = current_y
            except Exception as e:
                print(f"旋转相机失败：{e}")
        
        return task.cont
    
    def _should_handle_keyboard(self):
        """检查是否应该处理键盘事件（避免与ImGui冲突）"""
        try:
            # 检查ImGui是否想要捕获键盘
            try:
                from imgui_bundle import imgui
                if hasattr(imgui, 'get_io') and imgui.get_io().want_capture_keyboard:
                    return False
            except ImportError:
                pass
            
            # 如果右键按下，优先处理视角控制（即使ImGui有焦点）
            if self.keyMap["mouse3"]:
                return True
                
            return True
        except:
            return True
    
    def _should_handle_mouse(self):
        """检查是否应该处理鼠标事件（避免与ImGui冲突）"""
        try:
            # 如果是右键，优先处理视角控制
            if self.keyMap["mouse3"]:
                return True
                
            # 检查ImGui是否想要捕获鼠标
            try:
                from imgui_bundle import imgui
                if hasattr(imgui, 'get_io') and imgui.get_io().want_capture_mouse:
                    return False
            except ImportError:
                pass
            
            # 检查鼠标位置是否在ImGui窗口区域内
            mouse_pos = self.showbase.mouseWatcherNode.getMouse()
            if not mouse_pos:
                return True
                
            # 获取显示尺寸
            try:
                from imgui_bundle import imgui
                display_size = imgui.get_io().display_size
                mouse_x = mouse_pos.get_x() * display_size.x / 2 + display_size.x / 2
                mouse_y = display_size.y - (mouse_pos.get_y() * display_size.y / 2 + display_size.y / 2)
                
                # 检查是否在常见的ImGui界面区域内
                # 这里可以根据实际的ImGui窗口位置进行更精确的检测
                if mouse_x < 300 and mouse_y < 200:  # 左上角区域（菜单栏）
                    return False
                if mouse_x < 300 and mouse_y > display_size.y - 200:  # 左下角区域（工具栏）
                    return False
                if mouse_x > display_size.x - 300 and mouse_y < 200:  # 右上角区域
                    return False
            except:
                pass
                
            return True
        except Exception as e:
            print(f"鼠标事件检测失败: {e}")
            return True