/**
   * Dump Java Class Histogram to CSV.
   *
   * @param isSelected If this value is true, this method dumps data which is selected in class
   *     filter, otherwise this method dumps all snapshot data.
   */
  public void dumpClassHistogramToCSV(boolean isSelected) {
    FileChooser dialog = new FileChooser();
    ResourceBundle resource =
        ResourceBundle.getBundle("snapshotResources", new Locale(HeapStatsUtils.getLanguage()));

    dialog.setTitle(resource.getString("dialog.csvchooser.title"));
    dialog.setInitialDirectory(new File(HeapStatsUtils.getDefaultDirectory()));
    dialog
        .getExtensionFilters()
        .addAll(
            new ExtensionFilter("CSV file (*.csv)", "*.csv"),
            new ExtensionFilter("All files", "*.*"));
    File csvFile = dialog.showSaveDialog(WindowController.getInstance().getOwner());

    if (csvFile != null) {
      Predicate<? super ObjectData> filter = histogramController.getFilter();
      TaskAdapter<CSVDumpHeap> task =
          new TaskAdapter<>(
              new CSVDumpHeap(
                  csvFile,
                  isSelected ? currentTarget.get() : startCombo.getItems(),
                  isSelected ? filter : null,
                  HeapStatsUtils.getReplaceClassName()));
      super.bindTask(task);

      Thread parseThread = new Thread(task);
      parseThread.start();
    }
  }
  /**
   * Event handler of OK button.
   *
   * @param event ActionEvent of this event.
   */
  @FXML
  private void onOkClick(ActionEvent event) {
    int startIdx = startCombo.getSelectionModel().getSelectedIndex();
    int endIdx = endCombo.getSelectionModel().getSelectedIndex();
    currentTarget.set(
        FXCollections.observableArrayList(startCombo.getItems().subList(startIdx, endIdx + 1)));
    currentClassNameSet.set(FXCollections.observableSet());
    summaryData.set(new SummaryData(currentTarget.get()));

    Task<Void> topNTask = histogramController.getDrawTopNDataTask(currentTarget.get(), true, null);
    super.bindTask(topNTask);
    Thread topNThread = new Thread(topNTask);
    topNThread.start();

    Task<Void> summarizeTask =
        summaryController.getCalculateGCSummaryTask(this::drawRebootSuspectLine);
    super.bindTask(summarizeTask);
    Thread summarizeThread = new Thread(summarizeTask);
    summarizeThread.start();
  }
  /**
   * Event handler of SnapShot file button.
   *
   * @param event ActionEvent of this event.
   */
  @FXML
  public void onSnapshotFileClick(ActionEvent event) {
    FileChooser dialog = new FileChooser();
    ResourceBundle resource =
        ResourceBundle.getBundle("snapshotResources", new Locale(HeapStatsUtils.getLanguage()));

    dialog.setTitle(resource.getString("dialog.filechooser.title"));
    dialog.setInitialDirectory(new File(HeapStatsUtils.getDefaultDirectory()));
    dialog
        .getExtensionFilters()
        .addAll(
            new ExtensionFilter("SnapShot file (*.dat)", "*.dat"),
            new ExtensionFilter("All files", "*.*"));

    List<File> snapshotFileList =
        dialog.showOpenMultipleDialog(WindowController.getInstance().getOwner());

    if (snapshotFileList != null) {
      clearAllItems();

      HeapStatsUtils.setDefaultDirectory(snapshotFileList.get(0).getParent());
      List<String> files =
          snapshotFileList.stream().map(File::getAbsolutePath).collect(Collectors.toList());
      snapshotList.setText(files.stream().collect(Collectors.joining("; ")));

      TaskAdapter<ParseHeader> task =
          new TaskAdapter<>(new ParseHeader(files, HeapStatsUtils.getReplaceClassName(), true));
      task.setOnSucceeded(
          evt -> {
            ObservableList<SnapShotHeader> list =
                FXCollections.observableArrayList(task.getTask().getSnapShotList());
            startCombo.setItems(list);
            endCombo.setItems(list);
            startCombo.getSelectionModel().selectFirst();
            endCombo.getSelectionModel().selectLast();
          });
      super.bindTask(task);

      Thread parseThread = new Thread(task);
      parseThread.start();
    }
  }
  @Override
  public void setData(Object data, boolean select) {
    super.setData(data, select);
    snapshotList.setText((String) data);

    TaskAdapter<ParseHeader> task =
        new TaskAdapter<>(
            new ParseHeader(
                Arrays.asList((String) data), HeapStatsUtils.getReplaceClassName(), true));
    task.setOnSucceeded(
        evt -> {
          startCombo.setItems(FXCollections.observableArrayList(task.getTask().getSnapShotList()));
          endCombo.setItems(FXCollections.observableArrayList(task.getTask().getSnapShotList()));
          startCombo.getSelectionModel().selectFirst();
          endCombo.getSelectionModel().selectLast();
        });
    super.bindTask(task);

    Thread parseThread = new Thread(task);
    parseThread.start();
  }
  /**
   * Dump GC Statistics to CSV.
   *
   * @param isSelected If this value is true, this method dumps data which is selected time range,
   *     otherwise this method dumps all snapshot data.
   */
  public void dumpGCStatisticsToCSV(boolean isSelected) {
    FileChooser dialog = new FileChooser();
    dialog.setTitle("Select CSV files");
    dialog.setInitialDirectory(new File(HeapStatsUtils.getDefaultDirectory()));
    dialog
        .getExtensionFilters()
        .addAll(
            new ExtensionFilter("CSV file (*.csv)", "*.csv"),
            new ExtensionFilter("All files", "*.*"));
    File csvFile = dialog.showSaveDialog(WindowController.getInstance().getOwner());

    if (csvFile != null) {
      TaskAdapter<CSVDumpGC> task =
          new TaskAdapter<>(
              new CSVDumpGC(csvFile, isSelected ? currentTarget.get() : startCombo.getItems()));
      super.bindTask(task);

      Thread parseThread = new Thread(task);
      parseThread.start();
    }
  }