content: package com.alphabugx;
  
  import com.alphabugx.config.AppConfig;
  import com.alphabugx.dialog.SettingsDialog;
  import com.alphabugx.jar.JarProcessor;
  import com.alphabugx.editor.JavaCodeEditor;
  import com.alphabugx.search.GlobalSearchDialog;
  import com.alphabugx.util.ProgressReporter;
  import com.alphabugx.util.LogCapture;
  
  import javafx.application.Platform;
  import javafx.concurrent.Task;
  import javafx.fxml.FXML;
  import javafx.scene.control.*;
  import javafx.scene.layout.AnchorPane;
  import javafx.scene.layout.VBox;
  import javafx.scene.input.MouseEvent;
  import javafx.stage.FileChooser;
  import javafx.stage.Stage;
  import java.io.File;
  import java.io.IOException;
  import java.nio.file.Files;
  import java.nio.file.Paths;
  import java.util.*;
  import java.util.List;
  import java.util.Optional;
  
  public class FileEditorApp {
  
      // FXML组件 - 菜单栏
      @FXML
      private MenuBar menuBar;
      @FXML
      private MenuItem newMenuItem;
      @FXML
      private MenuItem openMenuItem;
      @FXML
      private MenuItem saveMenuItem;
      @FXML
      private MenuItem saveAsMenuItem;
      @FXML
      private MenuItem exitMenuItem;
      @FXML
      private MenuItem packageMenuItem;
      @FXML
      private MenuItem openJarMenuItem;
      @FXML
      private MenuItem jdkConfigMenuItem;
      @FXML
      private MenuItem cfrConfigMenuItem;
      @FXML
      private MenuItem findMenuItem;
      @FXML
      private MenuItem globalSearchMenuItem;
      @FXML
      private CheckMenuItem detailProgressMenuItem;
  
      // FXML组件 - 日志区域
      @FXML
      private Button toggleLogButton;
      @FXML
      private Button clearLogButton;
      @FXML
      private VBox logContainer;
      @FXML
      private TextArea logTextArea;
      @FXML
      private Label logStatusLabel;
  
  
      // FXML组件 - 主界面
      @FXML
      private SplitPane splitPane;  // 分割面板
      @FXML
      private TreeView<String> treeView;  // 目录树视图
      @FXML
      private TabPane tabPane;  // 标签页
  
      // FXML组件 - 状态栏
      @FXML
      private Label lineColumnLabel;  // 行列信息
      @FXML
      private Label saveStatusLabel;  // 保存状态
      @FXML
      private Label filePathLabel;    // 文件路径
  
      // 数据管理
      // 用于追踪TreeItem对应的实际文件路径
      private Map<TreeItem<String>, File> itemToFileMap = new HashMap<>();
      // 用于追踪Tab对应的文件
      private Map<Tab, File> tabToFileMap = new HashMap<>();
      // 用于追踪Tab对应的代码编辑器
      private Map<Tab, JavaCodeEditor> tabToEditorMap = new HashMap<>();
      // 用于追踪文件的修改状态
      private Map<Tab, Boolean> tabModifiedMap = new HashMap<>();
      
      // Jar冷补丁相关
      private JarProcessor jarProcessor;
      private File currentJarFile;
      private Set<File> modifiedJavaFiles = new HashSet<>();
      
      // 进度报告器
      private ProgressReporter progressReporter;
      
      // 日志捕获器
      private LogCapture logCapture;
  
      // 初始化：加载根目录
      public void initialize() {
          // 初始化进度报告器
          progressReporter = ProgressReporter.getInstance();
          
          // 初始化日志捕获器
          logCapture = LogCapture.getInstance();
          logCapture.setLogTextArea(logTextArea);
          logCapture.startCapture();
          
          // 初始化空的根目录
          TreeItem<String> rootItem = new TreeItem<>("请选择Jar文件开始编辑");
          rootItem.setExpanded(true);
          treeView.setRoot(rootItem);
  
          // 为TreeView添加双击事件监听器
          treeView.setOnMouseClicked(this::onTreeItemClick);
  
          // 为TabPane添加选择监听器，更新状态栏
          tabPane.getSelectionModel().selectedItemProperty().addListener((obs, oldTab, newTab) -> {
              updateStatusBar();
          });
  
          // 初始化状态栏
          updateStatusBar();
          
          // 添加应用程序关闭时的清理操作
          setupShutdownHook();
          
          // 添加启动日志
          Platform.runLater(() -> {
              String separator = repeatString("=", 50);
              logCapture.info(separator);
              logCapture.info("🚀 JAWD (Jar文件冷补丁编辑器) 启动成功");
              logCapture.info("版本: v1.0 | 作者: Alphabug");
              logCapture.info("支持功能: Jar解压、反编译、编辑、重打包");
              logCapture.info(separator);
              logCapture.info("💡 提示: 点击状态栏的「显示日志」按钮来查看详细操作日志");
          });
          
          // 延迟显示选择Jar文件的提示
          Platform.runLater(this::showInitialJarSelectionDialog);
      }
      
      /**
       * 显示初始Jar文件选择对话框
       */
      private void showInitialJarSelectionDialog() {
          Alert alert = new Alert(Alert.AlertType.INFORMATION);
          alert.setTitle("欢迎使用Jar冷补丁编辑器");
          alert.setHeaderText("开始您的Jar编辑之旅");
          alert.setContentText("请选择一个Jar文件开始编辑。\n\n点击菜单栏：工具 → 打开Jar文件");
          
          ButtonType openJarButton = new ButtonType("立即选择Jar文件");
          ButtonType laterButton = new ButtonType("稍后选择", ButtonBar.ButtonData.CANCEL_CLOSE);
          alert.getButtonTypes().setAll(openJarButton, laterButton);
          
          Optional<ButtonType> result = alert.showAndWait();
          if (result.isPresent() && result.get() == openJarButton) {
              onOpenJar();
          }
      }
      
      /**
       * 设置应用程序关闭时的清理钩子
       */
      private void setupShutdownHook() {
          Runtime.getRuntime().addShutdownHook(new Thread(() -> {
              if (jarProcessor != null) {
                  System.out.println("应用程序关闭，清理临时文件...");
                  jarProcessor.cleanup();
              }
          }));
      }
  
      // 加载目录内容
      private void loadDirectory(File directory, TreeItem<String> parentItem) {
          File[] files = directory.listFiles();
          if (files != null) {
              for (File file : files) {
                  // 跳过隐藏文件和目录
                  if (file.getName().startsWith(".")) {
                      continue;
                  }
                  
                  TreeItem<String> item = new TreeItem<>(file.getName());
                  parentItem.getChildren().add(item);
                  itemToFileMap.put(item, file);
                  
                  if (file.isDirectory()) {
                      // 为目录添加一个占位子项，实现延迟加载
                      TreeItem<String> placeholder = new TreeItem<>("Loading...");
                      item.getChildren().add(placeholder);
                      
                      // 当展开目录时加载子内容
                      item.expandedProperty().addListener((obs, wasExpanded, isExpanded) -> {
                          if (isExpanded && item.getChildren().size() == 1 && 
                              "Loading...".equals(item.getChildren().get(0).getValue())) {
                              item.getChildren().clear();
                              loadDirectory(file, item);
                          }
                      });
                  }
              }
          }
      }
  
      // 当点击文件时打开文件编辑标签
      @FXML
      private void onTreeItemClick(MouseEvent event) {
          if (event.getClickCount() == 2) { // 双击
              TreeItem<String> selectedItem = treeView.getSelectionModel().getSelectedItem();
              if (selectedItem != null) {
                  File file = itemToFileMap.get(selectedItem);
                  if (file != null && file.isFile()) {
                      openFile(file);
                  }
              }
          }
      }
  
      // 打开文件并将其内容加载到新标签页
      private void openFile(File file) {
          // 检查是否是Jar文件
          if (file.getName().toLowerCase().endsWith(".jar")) {
              Alert alert = new Alert(Alert.AlertType.INFORMATION);
              alert.setTitle("提示");
              alert.setHeaderText("检测到Jar文件");
              alert.setContentText("这是一个Jar文件，请使用菜单栏的\"打开Jar文件 → 选择Jar文件...\"功能来处理Jar文件。");
              alert.showAndWait();
              return;
          }
          
          // 检查文件是否已打开
          for (Tab tab : tabPane.getTabs()) {
              if (tabToFileMap.get(tab) != null && tabToFileMap.get(tab).equals(file)) {
                  tabPane.getSelectionModel().select(tab);
                  return;
              }
          }
  
          // 如果文件未打开，则创建新的标签页
          Tab newTab = new Tab(file.getName());
          
          // 创建AnchorPane容器
          AnchorPane anchorPane = new AnchorPane();
          
          // 创建JavaCodeEditor
          JavaCodeEditor codeEditor = new JavaCodeEditor();
          codeEditor.setCurrentFile(file);
          codeEditor.replaceText(readFile(file));  // 读取文件内容
          
          // 设置全局搜索回调
          codeEditor.setGlobalSearchCallback(this::onGlobalSearch);
          
          // 设置CodeEditor的锚点，使其填充整个AnchorPane
          AnchorPane.setTopAnchor(codeEditor, 0.0);
          AnchorPane.setBottomAnchor(codeEditor, 0.0);
          AnchorPane.setLeftAnchor(codeEditor, 0.0);
          AnchorPane.setRightAnchor(codeEditor, 0.0);
          
          // 添加文本变化监听器
          codeEditor.textProperty().addListener((obs, oldText, newText) -> {
              tabModifiedMap.put(newTab, true);
              updateTabTitle(newTab);
              updateStatusBar();
              
              // 如果是Java文件且在Jar编辑模式下，记录为已修改
              if (file.getName().endsWith(".java") && jarProcessor != null) {
                  modifiedJavaFiles.add(file);
              }
          });
          
          // 添加光标位置监听器
          codeEditor.caretPositionProperty().addListener((obs, oldPos, newPos) -> {
              updateStatusBar();
          });
          
          anchorPane.getChildren().add(codeEditor);
          newTab.setContent(anchorPane);
          
          // 记录Tab与文件、编辑器的对应关系
          tabToFileMap.put(newTab, file);
          tabToEditorMap.put(newTab, codeEditor);
          tabModifiedMap.put(newTab, false);
          
          // 当标签页关闭时清理映射
          newTab.setOnCloseRequest(event -> {
              if (tabModifiedMap.get(newTab)) {
                  // 如果文件已修改，询问是否保存
                  Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
                  alert.setTitle("确认");
                  alert.setHeaderText("文件已修改");
                  alert.setContentText("是否保存文件 " + file.getName() + "？");
                  
                  ButtonType saveButton = new ButtonType("保存");
                  ButtonType dontSaveButton = new ButtonType("不保存");
                  ButtonType cancelButton = new ButtonType("取消", ButtonBar.ButtonData.CANCEL_CLOSE);
                  alert.getButtonTypes().setAll(saveButton, dontSaveButton, cancelButton);
                  
                  Optional<ButtonType> result = alert.showAndWait();
                  if (result.get() == saveButton) {
                      saveTabFile(newTab);
                  } else if (result.get() == cancelButton) {
                      event.consume(); // 取消关闭
                      return;
                  }
              }
              
              // 清理映射和资源
              tabToFileMap.remove(newTab);
              JavaCodeEditor editor = tabToEditorMap.remove(newTab);
              if (editor != null) {
                  editor.cleanup(); // 清理编辑器资源
              }
              tabModifiedMap.remove(newTab);
              tabPane.getTabs().remove(newTab);
              updateStatusBar();
          });
  
          tabPane.getTabs().add(newTab);
          tabPane.getSelectionModel().select(newTab);  // 选中当前新打开的标签页
          updateStatusBar();
      }
  
      // 更新标签页标题（显示修改状态）
      private void updateTabTitle(Tab tab) {
          File file = tabToFileMap.get(tab);
          if (file != null) {
              String title = file.getName();
              if (tabModifiedMap.get(tab)) {
                  title += " *";
              }
              tab.setText(title);
          }
      }
  
      // 更新状态栏信息
      private void updateStatusBar() {
          Tab currentTab = tabPane.getSelectionModel().getSelectedItem();
          if (currentTab != null && tabToFileMap.containsKey(currentTab)) {
              File file = tabToFileMap.get(currentTab);
              
              // 更新文件路径
              filePathLabel.setText(file.getAbsolutePath());
              
              // 更新保存状态
              boolean isModified = tabModifiedMap.getOrDefault(currentTab, false);
              saveStatusLabel.setText(isModified ? "未保存" : "已保存");
              
              // 更新行列信息
              JavaCodeEditor codeEditor = tabToEditorMap.get(currentTab);
              if (codeEditor != null) {
                  String text = codeEditor.getText();
                  int caretPosition = codeEditor.getCaretPosition();
                  
                  int line = 1;
                  int column = 1;
                  for (int i = 0; i < caretPosition && i < text.length(); i++) {
                      if (text.charAt(i) == '\n') {
                          line++;
                          column = 1;
                      } else {
                          column++;
                      }
                  }
                  
                  lineColumnLabel.setText("行: " + line + ", 列: " + column);
              }
          } else {
              filePathLabel.setText("无文件");
              saveStatusLabel.setText("已保存");
              lineColumnLabel.setText("行: 1, 列: 1");
          }
      }
  
      // 读取文件内容
      private String readFile(File file) {
          try {
              return new String(Files.readAllBytes(Paths.get(file.toURI())));
          } catch (IOException e) {
              e.printStackTrace();
              return "Error reading file: " + e.getMessage();
          }
      }
  
      // 保存指定标签页的文件
      private void saveTabFile(Tab tab) {
          File file = tabToFileMap.get(tab);
          JavaCodeEditor codeEditor = tabToEditorMap.get(tab);
          if (file != null && codeEditor != null) {
              String content = codeEditor.getText();
              
              try {
                  Files.write(Paths.get(file.toURI()), content.getBytes());
                  tabModifiedMap.put(tab, false);
                  updateTabTitle(tab);
                  updateStatusBar();
                  System.out.println("文件已保存: " + file.getName());
              } catch (IOException e) {
                  e.printStackTrace();
                  Alert alert = new Alert(Alert.AlertType.ERROR);
                  alert.setTitle("保存失败");
                  alert.setHeaderText("无法保存文件");
                  alert.setContentText("错误信息: " + e.getMessage());
                  alert.showAndWait();
              }
          }
      }
  
      // === 菜单事件处理方法 ===
  
      // 新建文件
      @FXML
      private void onNewFile() {
          Tab newTab = new Tab("未命名");
          
          AnchorPane anchorPane = new AnchorPane();
          TextArea fileTextArea = new TextArea();
          fileTextArea.setWrapText(true);
          
          AnchorPane.setTopAnchor(fileTextArea, 0.0);
          AnchorPane.setBottomAnchor(fileTextArea, 0.0);
          AnchorPane.setLeftAnchor(fileTextArea, 0.0);
          AnchorPane.setRightAnchor(fileTextArea, 0.0);
          
          // 添加文本变化监听器
          fileTextArea.textProperty().addListener((obs, oldText, newText) -> {
              tabModifiedMap.put(newTab, true);
              updateTabTitle(newTab);
              updateStatusBar();
          });
          
          // 添加光标位置监听器
          fileTextArea.caretPositionProperty().addListener((obs, oldPos, newPos) -> {
              updateStatusBar();
          });
          
          anchorPane.getChildren().add(fileTextArea);
          newTab.setContent(anchorPane);
          
          tabModifiedMap.put(newTab, false);
          
          tabPane.getTabs().add(newTab);
          tabPane.getSelectionModel().select(newTab);
          updateStatusBar();
      }
  
      // 打开文件
      @FXML
      private void onOpenFile() {
          FileChooser fileChooser = new FileChooser();
          fileChooser.setTitle("打开文件");
          
          // 设置默认目录为当前工作目录
          fileChooser.setInitialDirectory(new File(System.getProperty("user.dir")));
          
          // 添加文件过滤器
          fileChooser.getExtensionFilters().addAll(
              new FileChooser.ExtensionFilter("所有文件", "*.*"),
              new FileChooser.ExtensionFilter("Java文件", "*.java"),
              new FileChooser.ExtensionFilter("文本文件", "*.txt"),
              new FileChooser.ExtensionFilter("XML文件", "*.xml"),
              new FileChooser.ExtensionFilter("配置文件", "*.properties", "*.yml", "*.yaml")
          );
          
          Stage stage = (Stage) menuBar.getScene().getWindow();
          File selectedFile = fileChooser.showOpenDialog(stage);
          
          if (selectedFile != null) {
              // 检查是否是Jar文件，如果是则提示用户使用正确的功能
              if (selectedFile.getName().toLowerCase().endsWith(".jar")) {
                  Alert alert = new Alert(Alert.AlertType.INFORMATION);
                  alert.setTitle("提示");
                  alert.setHeaderText("检测到Jar文件");
                  alert.setContentText("您选择的是Jar文件。如果要进行Jar冷补丁编辑，请使用：\n工具 → 打开Jar文件");
                  alert.showAndWait();
                  return;
              }
              
              openFile(selectedFile);
          }
      }
  
      // 保存文件（菜单栏版本）
      @FXML
      private void onSaveButtonClick() {
          Tab selectedTab = tabPane.getSelectionModel().getSelectedItem();
          if (selectedTab != null) {
              if (tabToFileMap.containsKey(selectedTab)) {
                  // 已有文件，直接保存
                  saveTabFile(selectedTab);
              } else {
                  // 新文件，另存为
                  onSaveAsFile();
              }
          }
      }
  
      // 另存为
      @FXML
      private void onSaveAsFile() {
          Tab selectedTab = tabPane.getSelectionModel().getSelectedItem();
          if (selectedTab != null) {
              FileChooser fileChooser = new FileChooser();
              fileChooser.setTitle("另存为");
              
              // 设置默认目录为当前工作目录
              fileChooser.setInitialDirectory(new File(System.getProperty("user.dir")));
              
              Stage stage = (Stage) menuBar.getScene().getWindow();
              File selectedFile = fileChooser.showSaveDialog(stage);
              
              if (selectedFile != null) {
                  AnchorPane anchorPane = (AnchorPane) selectedTab.getContent();
                  TextArea textArea = (TextArea) anchorPane.getChildren().get(0);
                  String content = textArea.getText();
                  
                  try {
                      Files.write(Paths.get(selectedFile.toURI()), content.getBytes());
                      
                      // 更新标签页关联
                      tabToFileMap.put(selectedTab, selectedFile);
                      tabModifiedMap.put(selectedTab, false);
                      selectedTab.setText(selectedFile.getName());
                      updateStatusBar();
                      
                      System.out.println("文件已保存: " + selectedFile.getName());
                  } catch (IOException e) {
                      e.printStackTrace();
                      Alert alert = new Alert(Alert.AlertType.ERROR);
                      alert.setTitle("保存失败");
                      alert.setHeaderText("无法保存文件");
                      alert.setContentText("错误信息: " + e.getMessage());
                      alert.showAndWait();
                  }
              }
          }
      }
  
      // 退出应用
      @FXML
      private void onExit() {
          // 获取当前Stage并调用强制退出处理
          Stage stage = (Stage) menuBar.getScene().getWindow();
          handleWindowClose(stage);
      }
      
      /**
       * 处理窗口关闭事件 - 与主应用程序的强制退出逻辑一致
       */
      private void handleWindowClose(Stage stage) {
          Alert alert = new Alert(Alert.AlertType.WARNING);
          alert.setTitle("确认退出");
          alert.setHeaderText("强制退出应用程序");
          alert.setContentText("检测到后台可能存在运行的进程。\n" +
                             "点击「强制退出」将终止所有相关的Java进程。\n" +
                             "点击「取消」返回应用程序。\n\n" +
                             "是否确认强制退出？");
          
          // 自定义按钮
          ButtonType forceExitButton = new ButtonType("强制退出", ButtonBar.ButtonData.YES);
          ButtonType cancelButton = new ButtonType("取消", ButtonBar.ButtonData.CANCEL_CLOSE);
          alert.getButtonTypes().setAll(forceExitButton, cancelButton);
          
          // 设置警告图标
          alert.setAlertType(Alert.AlertType.WARNING);
          
          Optional<ButtonType> result = alert.showAndWait();
          if (result.isPresent() && result.get() == forceExitButton) {
              performForceExit();
          }
          // 如果选择取消，什么都不做，窗口继续保持打开
      }
      
      /**
       * 执行强制退出操作
       */
      private void performForceExit() {
          try {
              // 1. 清理临时文件
              if (jarProcessor != null) {
                  System.out.println("清理临时文件...");
                  jarProcessor.cleanup();
              }
              
              // 2. 显示退出进度
              System.out.println("正在强制退出应用程序...");
              
              // 3. 尝试终止所有Java进程（包括javaw）
              killJavaProcesses();
              
              // 4. 强制退出JavaFX平台
              Platform.exit();
              
              // 5. 最后的保险 - 强制退出JVM
              System.exit(0);
              
          } catch (Exception e) {
              System.err.println("强制退出时发生异常: " + e.getMessage());
              // 即使出现异常也要强制退出
              System.exit(1);
          }
      }
      
      /**
       * 终止所有相关的Java进程
       */
      private void killJavaProcesses() {
          try {
              String os = System.getProperty("os.name").toLowerCase();
              
              if (os.contains("win")) {
                  // Windows系统 - 终止javaw.exe进程
                  System.out.println("终止Windows Java进程...");
                  
                  // 方法1：使用taskkill终止当前进程组
                  String currentPid = getCurrentProcessId();
                  ProcessBuilder pb1 = new ProcessBuilder("taskkill", "/F", "/T", "/PID", currentPid);
                  pb1.start();
                  
                  // 给进程一点时间来终止
                  Thread.sleep(1000);
                  
              } else if (os.contains("nix") || os.contains("nux") || os.contains("mac")) {
                  // Unix/Linux/Mac系统
                  System.out.println("终止Unix/Linux Java进程...");
                  
                  // 获取当前进程PID
                  String currentPid = getCurrentProcessId();
                  
                  // 使用kill命令终止进程组
                  ProcessBuilder pb = new ProcessBuilder("kill", "-TERM", currentPid);
                  pb.start();
                  
                  Thread.sleep(500);
                  
                  // 如果温和终止失败，使用强制终止
                  ProcessBuilder pb2 = new ProcessBuilder("kill", "-KILL", currentPid);
                  pb2.start();
              }
              
          } catch (Exception e) {
              System.err.println("终止Java进程时出错: " + e.getMessage());
              // 继续执行其他退出步骤
          }
      }
      
      // 切换日志区域显示/隐藏
      @FXML
      private void onToggleLogArea() {
          boolean isVisible = logContainer.isVisible();
          
          if (isVisible) {
              // 隐藏日志区域
              logContainer.setVisible(false);
              logContainer.setManaged(false);
              toggleLogButton.setText("显示日志");
              logStatusLabel.setText("日志已隐藏");
          } else {
              // 显示日志区域
              logContainer.setVisible(true);
              logContainer.setManaged(true);
              toggleLogButton.setText("隐藏日志");
              logStatusLabel.setText("日志监控中");
              
              // 添加一条欢迎消息
              logCapture.info("日志区域已打开，所有系统输出将显示在这里");
          }
      }
      
      // 清空日志
      @FXML
      private void onClearLog() {
          if (logCapture != null) {
              logCapture.clearLog();
          }
      }
      
      /**
       * 获取当前进程ID (Java 8兼容版本)
       */
      private String getCurrentProcessId() {
          try {
              // 使用JMX获取进程名称，然后提取PID
              String jvmName = java.lang.management.ManagementFactory.getRuntimeMXBean().getName();
              // jvmName格式通常是: "pid@hostname"
              if (jvmName.contains("@")) {
                  return jvmName.split("@")[0];
              }
              
              // 如果上述方法失败，使用同样的方法但更安全的提取
              String processName = java.lang.management.ManagementFactory.getRuntimeMXBean().getName();
              return processName.substring(0, processName.indexOf('@'));
              
          } catch (Exception e) {
              System.err.println("无法获取进程ID: " + e.getMessage());
              // 返回一个默认值，虽然可能不准确但不会导致程序崩溃
              return "0";
          }
      }
      
      /**
       * 重复字符串（Java 8兼容版本）
       */
      private String repeatString(String str, int count) {
          StringBuilder sb = new StringBuilder();
          for (int i = 0; i < count; i++) {
              sb.append(str);
          }
          return sb.toString();
      }
      
      /**
       * 格式化文件大小显示
       */
      private String formatFileSize(long bytes) {
          if (bytes < 1024) return bytes + " B";
          if (bytes < 1024 * 1024) return String.format("%.1f KB", bytes / 1024.0);
          return String.format("%.1f MB", bytes / (1024.0 * 1024.0));
      }
      
      // 关于对话框
      @FXML
      private void onAbout() {
          Alert alert = new Alert(Alert.AlertType.INFORMATION);
          alert.setTitle("关于JAWD - by Alphabug");
          alert.setHeaderText("Jar冷补丁编辑器 (JAWD) - v1.0 - 作者: Alphabug");
          
          // 设置精简的关于信息 - 小红书风格
          String aboutText = "🔧 Jar冷补丁编辑器 - 让修补变得so easy！\n\n" +
                            "✨ 核心功能:\n" +
                            "• 一键反编译Jar文件\n" +
                            "• 可视化代码编辑器\n" +
                            "• 智能编译+多线程打包\n" +
                            "• 完美支持Spring Boot\n\n" +
                            "🏆 实战场景:\n" +
                            "• 🐛 紧急漏洞修复 - 线上救火必备\n" +
                            "• 🚩 AWD攻防比赛 - 快速打补丁神器\n" +
                            "• 🔍 代码逆向分析 - 看透第三方库\n" +
                            "• 🎓 Java学习研究 - 探索底层奥秘\n\n" +
                            "⚡ 性能亮点:\n" +
                            "• 多线程处理，速度提升3-4倍\n" +
                            "• 实时进度显示，告别卡顿\n" +
                            "• 智能依赖解析，编译无忧\n\n" +
                            "👨‍💻 开发者信息:\n" +
                            "• 作者: Alphabug\n" +
                            "• 版本: v1.0\n" +
                            "• 发布: 2024年1月\n" +
                            "• 专注: 安全工具开发\n\n" +
                            "💡 小贴士: 首次使用记得配置JDK和CFR路径哦~\n\n" +
                            "🎉 让每一次Jar编辑都成为愉快的体验！";
          
          alert.setContentText(aboutText);
          
          // 设置对话框大小
          alert.getDialogPane().setPrefWidth(480);
          alert.getDialogPane().setPrefHeight(400);
          
          // 设置对话框为可调整大小
          alert.setResizable(true);
          
                  alert.showAndWait();
      }
      
  
      
      // 查找功能
      @FXML
      private void onFind() {
          Tab currentTab = tabPane.getSelectionModel().getSelectedItem();
          if (currentTab != null) {
              JavaCodeEditor codeEditor = tabToEditorMap.get(currentTab);
              if (codeEditor != null) {
                  // 触发编辑器的搜索功能 (Ctrl+F)
                  System.out.println("打开当前文件搜索");
                  // 这里可以实现一个简单的搜索对话框
                  showSimpleSearchDialog(codeEditor);
              }
          }
      }
      
      // 全局搜索功能
      @FXML
      private void onGlobalSearch() {
          if (jarProcessor != null && jarProcessor.getWorkDir() != null) {
              Stage stage = (Stage) menuBar.getScene().getWindow();
              GlobalSearchDialog searchDialog = new GlobalSearchDialog(stage, jarProcessor.getWorkDir());
              
              // 设置搜索结果处理器
              searchDialog.setResultHandler(result -> {
                  // 打开文件并跳转到指定行
                  openFileAndGoToLine(new File(result.getFilePath()), result.getLineNumber());
              });
              
              searchDialog.showDialog();
          } else {
              Alert alert = new Alert(Alert.AlertType.WARNING);
              alert.setTitle("全局搜索");
              alert.setHeaderText("无法执行全局搜索");
              alert.setContentText("请先打开一个Jar文件，然后才能在反编译的Java文件中进行全局搜索。");
              alert.showAndWait();
          }
      }
      
      /**
       * 显示简单搜索对话框
       */
      private void showSimpleSearchDialog(JavaCodeEditor codeEditor) {
          TextInputDialog dialog = new TextInputDialog();
          dialog.setTitle("查找");
          dialog.setHeaderText("在当前文件中查找");
          dialog.setContentText("请输入搜索内容:");
          
          Optional<String> result = dialog.showAndWait();
          if (result.isPresent() && !result.get().trim().isEmpty()) {
              String searchText = result.get().trim();
              codeEditor.searchText(searchText, false, false);
          }
      }
      
      /**
       * 打开文件并跳转到指定行
       */
      private void openFileAndGoToLine(File file, int lineNumber) {
          // 先打开文件
          openFile(file);
          
          // 跳转到指定行
          Platform.runLater(() -> {
              Tab currentTab = tabPane.getSelectionModel().getSelectedItem();
              if (currentTab != null) {
                  JavaCodeEditor codeEditor = tabToEditorMap.get(currentTab);
                  if (codeEditor != null) {
                      try {
                          codeEditor.moveTo(lineNumber - 1, 0); // 行号从0开始
                          codeEditor.requestFollowCaret();
                      } catch (Exception e) {
                          System.err.println("跳转到行失败: " + e.getMessage());
                      }
                  }
              }
          });
      }
      
      // 打包功能
      @FXML
      private void onPackageButtonClick() {
          if (jarProcessor == null || currentJarFile == null) {
              Alert alert = new Alert(Alert.AlertType.WARNING);
              alert.setTitle("打包失败");
              alert.setHeaderText("没有可打包的Jar文件");
              alert.setContentText("请先打开一个Jar文件进行编辑");
              alert.showAndWait();
              return;
          }
          
          // 自动保存所有修改的文件
          saveAllModifiedFiles();
          
          // 开始打包
          repackageJar();
      }
      
      // === Jar冷补丁相关方法 ===
      
      // 打开Jar文件
      @FXML
      private void onOpenJar() {
          FileChooser fileChooser = new FileChooser();
          fileChooser.setTitle("选择要编辑的Jar文件");
          
          // 设置默认目录为当前工作目录
          fileChooser.setInitialDirectory(new File(System.getProperty("user.dir")));
          
          fileChooser.getExtensionFilters().add(
              new FileChooser.ExtensionFilter("Jar文件", "*.jar")
          );
          
          Stage stage = (Stage) menuBar.getScene().getWindow();
          File selectedFile = fileChooser.showOpenDialog(stage);
          
          if (selectedFile != null) {
              openJarFile(selectedFile);
          }
      }
      
      // JDK配置
      @FXML
      private void onJdkConfig() {
          Stage stage = (Stage) menuBar.getScene().getWindow();
          SettingsDialog.showJdkConfigDialog(stage);
      }
      
      // CFR工具配置
      @FXML
      private void onCfrConfig() {
          Stage stage = (Stage) menuBar.getScene().getWindow();
          SettingsDialog.showCfrConfigDialog(stage);
      }
      
      // 切换进度显示模式
      @FXML
      private void onToggleProgressMode() {
          if (progressReporter != null) {
              progressReporter.toggleMode();
              
              // 更新菜单项状态
              boolean isDetailed = (progressReporter.getCurrentMode() == ProgressReporter.DisplayMode.DETAILED);
              detailProgressMenuItem.setSelected(isDetailed);
              
              // 显示提示信息
              Alert alert = new Alert(Alert.AlertType.INFORMATION);
              alert.setTitle("进度显示模式");
              alert.setHeaderText("进度显示模式已切换");
              alert.setContentText("当前模式: " + (isDetailed ? "详细模式" : "简洁模式") + 
                                  "\n\n" + (isDetailed ? 
                                  "详细模式：显示每个操作的详细信息、时间戳和错误详情" :
                                  "简洁模式：只显示主要进度条和当前操作"));
              alert.showAndWait();
          }
      }
      
      /**
       * 打开并处理Jar文件
       */
      private void openJarFile(File jarFile) {
          // 记录开始处理日志
          logCapture.info("📂 开始处理Jar文件: " + jarFile.getName());
          logCapture.info("文件路径: " + jarFile.getAbsolutePath());
          logCapture.info("文件大小: " + formatFileSize(jarFile.length()));
          // 在后台线程中检查配置和处理Jar文件
          Task<Void> configCheckTask = new Task<Void>() {
              @Override
              protected Void call() throws Exception {
                  // 检查配置
                  AppConfig config = AppConfig.getInstance();
                  
                  if (config.getJdkPath().isEmpty()) {
                      Platform.runLater(() -> {
                          Alert alert = new Alert(Alert.AlertType.WARNING);
                          alert.setTitle("配置不完整");
                          alert.setHeaderText("JDK路径未配置");
                          alert.setContentText("请先配置JDK路径才能处理Jar文件");
                          alert.showAndWait();
                      });
                      return null;
                  }
                  
                  if (!new File(config.getCfrPath()).exists()) {
                      Platform.runLater(() -> {
                          Alert alert = new Alert(Alert.AlertType.WARNING);
                          alert.setTitle("配置不完整");
                          alert.setHeaderText("CFR工具未找到");
                          alert.setContentText("CFR工具路径: " + config.getCfrPath() + "\n请确保CFR工具存在或重新配置路径");
                          alert.showAndWait();
                      });
                      return null;
                  }
                  
                  // 配置检查通过，开始处理Jar文件
                  Platform.runLater(() -> {
                      processJarFileInBackground(jarFile);
                  });
                  
                  return null;
              }
          };
          
          Thread configThread = new Thread(configCheckTask);
          configThread.setDaemon(true);
          configThread.start();
      }
      
      /**
       * 在后台线程中处理Jar文件
       */
      private void processJarFileInBackground(File jarFile) {
          // 显示进度对话框
          ProgressDialog progressDialog = new ProgressDialog();
          progressDialog.show();
          
          // 在后台线程中处理Jar文件
          Task<Void> task = new Task<Void>() {
              @Override
              protected Void call() throws Exception {
                  try {
                      updateMessage("初始化工作环境...");
                      updateProgress(0, 100);
                      
                      // 清理之前的工作
                      if (jarProcessor != null) {
                          jarProcessor.cleanup();
                      }
                      
                      jarProcessor = new JarProcessor();
                      currentJarFile = jarFile;
                      modifiedJavaFiles.clear();
                      
                      updateMessage("解压Jar文件...");
                      updateProgress(10, 100);
                      jarProcessor.initWorkspace(jarFile);
                      
                      updateMessage("正在解压Jar内容...");
                      updateProgress(20, 100);
                      jarProcessor.extractJar();
                      
                      updateMessage("复制Class文件...");
                      updateProgress(35, 100);
                      jarProcessor.copyClassFiles();
                      
                      updateMessage("开始多线程反编译Class文件...");
                      updateProgress(30, 100);
                      jarProcessor.decompileClasses();
                      
                      updateMessage("反编译完成，正在整理文件...");
                      updateProgress(75, 100);
                      
                      updateMessage("加载到编辑器...");
                      updateProgress(90, 100);
                      
                      // 在JavaFX线程中更新界面
                      Platform.runLater(() -> {
                          try {
                              loadJarToEditor();
                              updateProgress(100, 100);
                              updateMessage("Jar文件加载完成");
                          } catch (Exception e) {
                              System.err.println("加载编辑器失败: " + e.getMessage());
                              e.printStackTrace();
                          }
                      });
                      
                      // 小延迟确保界面更新完成
                      Thread.sleep(500);
                      
                  } catch (Exception e) {
                      e.printStackTrace();
                      throw new RuntimeException("处理Jar文件失败: " + e.getMessage(), e);
                  }
                  return null;
              }
          };
          
          progressDialog.bindToTask(task);
          
          task.setOnSucceeded(e -> {
              Platform.runLater(() -> {
                  progressDialog.close();
                  showInfo("成功", "Jar文件已加载到编辑器中\n\n工作目录: " + jarProcessor.getWorkDir().getAbsolutePath() + "\n\n现在可以开始编辑Java源码了！");
              });
          });
          
          task.setOnFailed(e -> {
              Platform.runLater(() -> {
                  progressDialog.close();
                  Throwable exception = task.getException();
                  exception.printStackTrace();
                  showError("处理失败", "处理Jar文件时发生错误", 
                      exception.getMessage() + "\n\n请检查：\n1. Jar文件是否完整\n2. CFR工具是否可用\n3. 是否有足够的磁盘空间");
                  
                  // 清理
                  if (jarProcessor != null) {
                      jarProcessor.cleanup();
                      jarProcessor = null;
                  }
                  currentJarFile = null;
              });
          });
          
          Thread thread = new Thread(task);
          thread.setDaemon(true);
          thread.start();
      }
      
      /**
       * 将反编译后的Java文件加载到编辑器
       */
      private void loadJarToEditor() {
          // 清空当前标签页
          tabPane.getTabs().clear();
          
          // 更新树视图根节点
          TreeItem<String> rootItem = new TreeItem<>(currentJarFile.getName() + " (反编译)");
          rootItem.setExpanded(true);
          treeView.setRoot(rootItem);
          
          // 清空映射
          itemToFileMap.clear();
          tabToFileMap.clear();
          tabModifiedMap.clear();
          
          // 加载源码目录
          File sourceDir = jarProcessor.getSourceDir();
          itemToFileMap.put(rootItem, sourceDir);
          loadDirectory(sourceDir, rootItem);
          
          updateStatusBar();
      }
      
      /**
       * 保存所有修改的文件
       */
      private void saveAllModifiedFiles() {
          for (Tab tab : tabPane.getTabs()) {
              if (tabModifiedMap.getOrDefault(tab, false)) {
                  saveTabFile(tab);
                  
                  // 记录修改的Java文件
                  File file = tabToFileMap.get(tab);
                  if (file != null && file.getName().endsWith(".java")) {
                      modifiedJavaFiles.add(file);
                  }
              }
          }
      }
      
      /**
       * 重新打包Jar文件
       */
      private void repackageJar() {
          if (modifiedJavaFiles.isEmpty()) {
              Alert alert = new Alert(Alert.AlertType.INFORMATION);
              alert.setTitle("打包");
              alert.setHeaderText("没有修改的文件");
              alert.setContentText("没有检测到修改的Java文件，无需重新编译");
              alert.showAndWait();
              return;
          }
          
          // 选择输出文件
          FileChooser fileChooser = new FileChooser();
          fileChooser.setTitle("保存打包后的Jar文件");
          
          // 设置默认目录为当前工作目录
          fileChooser.setInitialDirectory(new File(System.getProperty("user.dir")));
          
          fileChooser.setInitialFileName(currentJarFile.getName().replace(".jar", "_patched.jar"));
          fileChooser.getExtensionFilters().add(
              new FileChooser.ExtensionFilter("Jar文件", "*.jar")
          );
          
          Stage stage = (Stage) menuBar.getScene().getWindow();
          File outputFile = fileChooser.showSaveDialog(stage);
          
          if (outputFile == null) {
              return;
          }
          
          // 显示进度对话框
          ProgressDialog progressDialog = new ProgressDialog();
          progressDialog.show();
          
          // 在后台线程中进行编译和打包
          Task<File> task = new Task<File>() {
              @Override
              protected File call() throws Exception {
                  try {
                      updateMessage("编译修改的Java文件...");
                      updateProgress(5, 100);
                      
                      // 编译修改的Java文件
                      List<File> javaFilesList = new ArrayList<>(modifiedJavaFiles);
                      updateMessage("编译 " + javaFilesList.size() + " 个修改的Java文件...");
                      jarProcessor.compileJavaFiles(javaFilesList);
                      
                      updateMessage("编译完成，开始打包...");
                      updateProgress(20, 100);
                      
                      updateMessage("替换编译后的class文件...");
                      updateProgress(25, 100);
                      
                      updateMessage("开始重新打包Jar文件...");
                      updateProgress(30, 100);
                      
                      // 设置进度回调来更新UI
                      jarProcessor.setProgressCallback((step, progress, message) -> {
                          Platform.runLater(() -> {
                              // 将30-100的进度范围分配给打包过程
                              double totalProgress = 30 + (progress * 70 / 100.0);
                              updateProgress(totalProgress, 100);
                              updateMessage(message);
                          });
                      });
                      
                      // 重新打包（现在包含InterruptedException处理）
                      File result = jarProcessor.repackageJar(outputFile.getAbsolutePath());
                      
                      updateProgress(100, 100);
                      updateMessage("打包完成");
                      
                      return result;
                      
                  } catch (Exception e) {
                      e.printStackTrace();
                      throw new RuntimeException("打包失败: " + e.getMessage(), e);
                  }
              }
          };
          
          progressDialog.bindToTask(task);
          
          task.setOnSucceeded(e -> {
              progressDialog.close();
              File result = task.getValue();
              showInfo("打包成功", "Jar文件已保存到: " + result.getAbsolutePath());
              modifiedJavaFiles.clear(); // 清空修改记录
          });
          
          task.setOnFailed(e -> {
              progressDialog.close();
              Throwable exception = task.getException();
              showError("打包失败", "重新打包Jar文件时发生错误", exception.getMessage());
          });
          
          Thread thread = new Thread(task);
          thread.setDaemon(true);
          thread.start();
      }
      
      /**
       * 进度对话框类
       */
      private static class ProgressDialog {
          private Dialog<Void> dialog;
          private ProgressBar progressBar;
          private Label messageLabel;
          private Label detailLabel;
          private Task<?> currentTask;
          
          public ProgressDialog() {
              dialog = new Dialog<>();
              dialog.setTitle("Jar冷补丁处理中");
              dialog.setHeaderText("正在处理Jar文件，请耐心等待...");
              
              // 创建进度条而不是进度指示器
              progressBar = new ProgressBar(0);
              progressBar.setPrefWidth(280);
              
              messageLabel = new Label("初始化工作环境...");
              messageLabel.setStyle("-fx-font-weight: bold;");
              
              detailLabel = new Label("准备开始处理");
              detailLabel.setStyle("-fx-text-fill: #666666; -fx-font-size: 11px;");
              
              AnchorPane content = new AnchorPane();
              content.setPrefSize(320, 120);
              content.getChildren().addAll(progressBar, messageLabel, detailLabel);
              
              AnchorPane.setTopAnchor(progressBar, 20.0);
              AnchorPane.setLeftAnchor(progressBar, 20.0);
              AnchorPane.setRightAnchor(progressBar, 20.0);
              
              AnchorPane.setTopAnchor(messageLabel, 50.0);
              AnchorPane.setLeftAnchor(messageLabel, 20.0);
              AnchorPane.setRightAnchor(messageLabel, 20.0);
              
              AnchorPane.setTopAnchor(detailLabel, 75.0);
              AnchorPane.setLeftAnchor(detailLabel, 20.0);
              AnchorPane.setRightAnchor(detailLabel, 20.0);
              
              dialog.getDialogPane().setContent(content);
              
              // 添加取消按钮
              ButtonType cancelButtonType = new ButtonType("取消", ButtonBar.ButtonData.CANCEL_CLOSE);
              dialog.getDialogPane().getButtonTypes().add(cancelButtonType);
              
              // 处理取消操作
              dialog.setResultConverter(dialogButton -> {
                  if (dialogButton == cancelButtonType && currentTask != null) {
                      currentTask.cancel();
                      return null;
                  }
                  return null;
              });
          }
          
          public void show() {
              dialog.show();
          }
          
          public void close() {
              dialog.close();
          }
          
          public void bindToTask(Task<?> task) {
              this.currentTask = task;
              progressBar.progressProperty().bind(task.progressProperty());
              messageLabel.textProperty().bind(task.messageProperty());
              
              // 更新详细信息
              task.progressProperty().addListener((obs, oldProgress, newProgress) -> {
                  if (newProgress != null) {
                      int percentage = (int) (newProgress.doubleValue() * 100);
                      Platform.runLater(() -> {
                          detailLabel.setText("已完成 " + percentage + "%");
                      });
                  }
              });
          }
      }
      
      /**
       * 显示信息对话框
       */
      private void showInfo(String title, String message) {
          Alert alert = new Alert(Alert.AlertType.INFORMATION);
          alert.setTitle(title);
          alert.setHeaderText(null);
          alert.setContentText(message);
          alert.showAndWait();
      }
      
      /**
       * 显示错误对话框
       */
      private void showError(String title, String header, String message) {
          Alert alert = new Alert(Alert.AlertType.ERROR);
          alert.setTitle(title);
          alert.setHeaderText(header);
          alert.setContentText(message);
          alert.showAndWait();
      }
  }
  