"""
路径规划编辑器
提供可视化编辑路径规划场景的功能
"""

from typing import List, Tuple, Optional, Dict, Any
from panda3d.core import Point3, KeyboardButton, MouseWatcher

class PathfindingEditor:
    """
    路径规划编辑器
    提供可视化编辑路径规划场景的功能
    """
    
    def __init__(self, world, algorithm_manager, visualization_manager):
        """
        初始化路径规划编辑器
        
        Args:
            world: 3D世界对象
            algorithm_manager: 算法管理器
            visualization_manager: 可视化管理器
        """
        self.world = world
        self.algorithm_manager = algorithm_manager
        self.visualization_manager = visualization_manager
        self.visible = False
        
        # 编辑器状态
        self.edit_mode = False
        self.selected_tool = "select"  # select, add_obstacle, remove_obstacle, set_start, set_goal
        self.grid_size = (20, 20)
        self.current_grid = None
        
        # 当前场景元素
        self.start_point = (0, 0)
        self.goal_point = (19, 19)
        
        # 编辑器GUI元素
        self.gui_elements = []
        self.tool_buttons = {}
        
        # 鼠标交互
        self.last_mouse_pos = None
        
        # 初始化网格
        self._initialize_grid()
        
    def _initialize_grid(self):
        """初始化网格"""
        rows, cols = self.grid_size
        self.current_grid = [[0 for _ in range(cols)] for _ in range(rows)]
        
    def toggle_visibility(self):
        """切换编辑器可见性"""
        if self.visible:
            self.hide()
        else:
            self.show()
            
    def show(self):
        """显示编辑器"""
        if self.visible:
            return
            
        self.visible = True
        self._create_editor_gui()
        print("✓ 路径规划编辑器已显示")
        
    def hide(self):
        """隐藏编辑器"""
        if not self.visible:
            return
            
        self.visible = False
        self._cleanup_editor_gui()
        print("✓ 路径规划编辑器已隐藏")
        
    def _create_editor_gui(self):
        """创建编辑器GUI"""
        try:
            if not hasattr(self.world, 'gui_manager') or not self.world.gui_manager:
                print("⚠ GUI管理器不可用，无法创建编辑器界面")
                return
                
            gui_manager = self.world.gui_manager
            
            # 创建编辑器面板标题
            panel = gui_manager.createGUIButton(
                pos=(0.7, 0, 0.95), 
                text="路径规划编辑器", 
                size=0.06
            )
            self.gui_elements.append(panel)
            
            # 创建工具按钮
            tools = [
                ("选择", "select"),
                ("添加障碍", "add_obstacle"),
                ("移除障碍", "remove_obstacle"),
                ("设置起点", "set_start"),
                ("设置终点", "set_goal")
            ]
            
            for i, (name, tool) in enumerate(tools):
                button = gui_manager.createGUIButton(
                    pos=(0.7, 0, 0.88 - i * 0.06), 
                    text=name, 
                    size=0.04
                )
                self.gui_elements.append(button)
                self.tool_buttons[tool] = button
                self.world.accept(f"pathfinding_tool_{tool}", 
                                lambda t=tool: self.set_edit_tool(t))
                
            # 创建编辑功能按钮
            functions = [
                ("生成随机障碍", self.generate_random_obstacles),
                ("清除障碍", self.clear_obstacles),
                ("运行A*", lambda: self.run_algorithm("astar")),
                ("运行Dijkstra", lambda: self.run_algorithm("dijkstra")),
                ("运行BFS", lambda: self.run_algorithm("bfs")),
                ("运行DFS", lambda: self.run_algorithm("dfs")),
                ("比较算法", self.compare_algorithms)
            ]
            
            for i, (name, callback) in enumerate(functions):
                button = gui_manager.createGUIButton(
                    pos=(0.82, 0, 0.88 - i * 0.06), 
                    text=name, 
                    size=0.04
                )
                self.gui_elements.append(button)
                self.world.accept(f"pathfinding_func_{name}", callback)
                
            # 显示网格
            self.visualization_manager.visualize_grid(self.current_grid)
            
        except Exception as e:
            print(f"⚠ 编辑器GUI创建失败: {e}")
            
    def _cleanup_editor_gui(self):
        """清理编辑器GUI"""
        try:
            if hasattr(self.world, 'gui_manager') and self.world.gui_manager:
                gui_manager = self.world.gui_manager
                
                for element in self.gui_elements:
                    gui_manager.deleteGUIElement(element)
                    
            # 清理事件监听
            tools = ["select", "add_obstacle", "remove_obstacle", "set_start", "set_goal"]
            for tool in tools:
                self.world.ignore(f"pathfinding_tool_{tool}")
                
            functions = [
                "生成随机障碍", "清除障碍", "运行A*", "运行Dijkstra", 
                "运行BFS", "运行DFS", "比较算法"
            ]
            for func in functions:
                self.world.ignore(f"pathfinding_func_{func}")
                
            self.gui_elements.clear()
            self.tool_buttons.clear()
            
        except Exception as e:
            print(f"⚠ 编辑器GUI清理失败: {e}")
            
    def set_edit_tool(self, tool: str):
        """设置编辑工具"""
        self.selected_tool = tool
        print(f"✓ 切换到 {tool} 工具")
        
        # 更新按钮状态
        for tool_name, button in self.tool_buttons.items():
            if tool_name == tool:
                # 高亮选中工具
                button.setColor(0.5, 1.0, 0.5, 1.0)  # 绿色
            else:
                # 恢复默认颜色
                button.setColor(1.0, 1.0, 1.0, 1.0)  # 白色
                
    def generate_random_obstacles(self):
        """生成随机障碍物"""
        import random
        
        if not self.current_grid:
            return
            
        rows, cols = len(self.current_grid), len(self.current_grid[0])
        obstacle_count = rows * cols // 4  # 25%的格子设为障碍物
        
        # 清除现有障碍物
        self.clear_obstacles()
        
        # 生成随机障碍物
        for _ in range(obstacle_count):
            row = random.randint(0, rows - 1)
            col = random.randint(0, cols - 1)
            
            # 不要在起点和终点生成障碍物
            if (row, col) != self.start_point and (row, col) != self.goal_point:
                self.current_grid[row][col] = 1
                
        # 更新可视化
        self.visualization_manager.visualize_grid(self.current_grid)
        print(f"✓ 生成了 {obstacle_count} 个随机障碍物")
        
    def clear_obstacles(self):
        """清除障碍物"""
        if not self.current_grid:
            return
            
        rows, cols = len(self.current_grid), len(self.current_grid[0])
        for row in range(rows):
            for col in range(cols):
                # 不清除起点和终点
                if (row, col) != self.start_point and (row, col) != self.goal_point:
                    self.current_grid[row][col] = 0
                    
        # 更新可视化
        self.visualization_manager.visualize_grid(self.current_grid)
        print("✓ 障碍物已清除")
        
    def run_algorithm(self, algorithm: str):
        """运行指定算法"""
        if not self.algorithm_manager or not self.visualization_manager:
            return
            
        print(f"✓ 运行 {algorithm} 算法...")
        
        # 查找路径
        path, stats = self.algorithm_manager.find_path(
            algorithm, self.current_grid, self.start_point, self.goal_point)
            
        if path:
            print(f"✓ 找到路径，长度: {len(path)}")
            print(f"  访问节点数: {stats.get('nodes_visited', 0)}")
            print(f"  耗时: {stats.get('time_taken', 0):.6f}秒")
            
            # 可视化路径
            self.visualization_manager.visualize_path(path, self.current_grid)
        else:
            print("✗ 未找到路径")
            print(f"  耗时: {stats.get('time_taken', 0):.6f}秒")
            
    def compare_algorithms(self):
        """比较算法性能"""
        if not self.algorithm_manager:
            return
            
        print("✓ 比较路径规划算法...")
        
        algorithms = ["astar", "dijkstra", "bfs", "dfs"]
        results = {}
        
        for algorithm in algorithms:
            path, stats = self.algorithm_manager.find_path(
                algorithm, self.current_grid, self.start_point, self.goal_point)
            results[algorithm] = {
                "path_length": len(path) if path else 0,
                "nodes_visited": stats.get("nodes_visited", 0),
                "time_taken": stats.get("time_taken", 0)
            }
            
        print("=== 算法性能比较 ===")
        for algorithm, result in results.items():
            print(f"{algorithm}:")
            print(f"  路径长度: {result['path_length']}")
            print(f"  访问节点数: {result['nodes_visited']}")
            print(f"  耗时: {result['time_taken']:.6f}秒")
            
    def handle_mouse_click(self, mouse_x: float, mouse_y: float):
        """处理鼠标点击事件"""
        if not self.edit_mode:
            return
            
        # 将屏幕坐标转换为网格坐标
        grid_pos = self._screen_to_grid(mouse_x, mouse_y)
        if not grid_pos:
            return
            
        row, col = grid_pos
        
        # 检查坐标是否在网格范围内
        rows, cols = len(self.current_grid), len(self.current_grid[0]) if self.current_grid else (0, 0)
        if not (0 <= row < rows and 0 <= col < cols):
            return
            
        # 根据当前工具执行操作
        if self.selected_tool == "add_obstacle":
            # 不要在起点和终点添加障碍物
            if (row, col) != self.start_point and (row, col) != self.goal_point:
                self.current_grid[row][col] = 1
                self.visualization_manager.visualize_grid(self.current_grid)
                
        elif self.selected_tool == "remove_obstacle":
            # 不要移除起点和终点
            if (row, col) != self.start_point and (row, col) != self.goal_point:
                self.current_grid[row][col] = 0
                self.visualization_manager.visualize_grid(self.current_grid)
                
        elif self.selected_tool == "set_start":
            # 移除旧起点的障碍物
            old_row, old_col = self.start_point
            if self.current_grid[old_row][old_col] == 1:
                self.current_grid[old_row][old_col] = 0
                
            self.start_point = (row, col)
            print(f"✓ 起点设置为: {row}, {col}")
            # 更新可视化
            self.visualization_manager.visualize_grid(self.current_grid)
            
        elif self.selected_tool == "set_goal":
            # 移除旧终点的障碍物
            old_row, old_col = self.goal_point
            if self.current_grid[old_row][old_col] == 1:
                self.current_grid[old_row][old_col] = 0
                
            self.goal_point = (row, col)
            print(f"✓ 终点设置为: {row}, {col}")
            # 更新可视化
            self.visualization_manager.visualize_grid(self.current_grid)
            
    def _screen_to_grid(self, screen_x: float, screen_y: float) -> Optional[Tuple[int, int]]:
        """
        将屏幕坐标转换为网格坐标
        
        Args:
            screen_x: 屏幕X坐标 (-1 到 1)
            screen_y: 屏幕Y坐标 (-1 到 1)
            
        Returns:
            网格坐标 (row, col)，如果转换失败则返回None
        """
        # 这是一个简化的实现
        # 实际应用中需要根据摄像机位置和方向进行更精确的转换
        
        if not self.current_grid:
            return None
            
        rows, cols = len(self.current_grid), len(self.current_grid[0])
        
        # 将屏幕坐标映射到网格坐标
        col = int((screen_x + 1) * cols / 2)
        row = int((1 - screen_y) * rows / 2)
        
        return (row, col)
        
    def toggle_edit_mode(self):
        """切换编辑模式"""
        self.edit_mode = not self.edit_mode
        if self.edit_mode:
            print("✓ 进入编辑模式")
        else:
            print("✓ 退出编辑模式")
            
    def update(self, dt: float):
        """更新编辑器状态"""
        # 处理键盘输入
        if self.world.mouseWatcherNode.hasMouse():
            mouse_pos = self.world.mouseWatcherNode.getMouse()
            
            # 检查鼠标按键
            if self.world.mouseWatcherNode.isButtonDown(MouseWatcher.getGlobalPointer()):
                if self.last_mouse_pos is None or \
                   (mouse_pos - self.last_mouse_pos).length() > 0.01:
                    self.handle_mouse_click(mouse_pos.x, mouse_pos.y)
                    self.last_mouse_pos = mouse_pos
                    
            # 检查键盘快捷键
            if self.world.mouseWatcherNode.isButtonDown(KeyboardButton.asciiKey('e')):
                self.toggle_edit_mode()
                
    def cleanup(self):
        """清理编辑器资源"""
        self.hide()
        self.current_grid = None
        self.start_point = None
        self.goal_point = None