public static boolean changeTo(@NotNull Project project,
                                 @NotNull Document document,
                                 Editor editor,
                                 @NotNull VirtualFile virtualFile,
                                 @NotNull Charset charset,
                                 @NotNull EncodingUtil.Magic8 isSafeToConvert, @NotNull EncodingUtil.Magic8 isSafeToReload) {
    Charset oldCharset = virtualFile.getCharset();
    Runnable undo;
    Runnable redo;
    if (isSafeToConvert == EncodingUtil.Magic8.ABSOLUTELY && isSafeToReload == EncodingUtil.Magic8.ABSOLUTELY) {
      final EncodingManager encodingManager = EncodingProjectManager.getInstance(project);
      //change and forget
      undo = () -> encodingManager.setEncoding(virtualFile, oldCharset);
      redo = () -> encodingManager.setEncoding(virtualFile, charset);
    }
    else {
      IncompatibleEncodingDialog dialog = new IncompatibleEncodingDialog(virtualFile, charset, isSafeToReload, isSafeToConvert);
      dialog.show();
      if (dialog.getExitCode() == IncompatibleEncodingDialog.RELOAD_EXIT_CODE) {
        undo = () -> EncodingUtil.reloadIn(virtualFile, oldCharset, project);
        redo = () -> EncodingUtil.reloadIn(virtualFile, charset, project);
      }
      else if (dialog.getExitCode() == IncompatibleEncodingDialog.CONVERT_EXIT_CODE) {
        undo = () -> EncodingUtil.saveIn(project, document, editor, virtualFile, oldCharset);
        redo = () -> EncodingUtil.saveIn(project, document, editor, virtualFile, charset);
      }
      else {
        return false;
      }
    }

    final UndoableAction action = new GlobalUndoableAction(virtualFile) {
      @Override
      public void undo() {
        // invoke later because changing document inside undo/redo is not allowed
        Application application = ApplicationManager.getApplication();
        application.invokeLater(undo, ModalityState.nonModal(), project.getDisposed());
      }

      @Override
      public void redo() {
        // invoke later because changing document inside undo/redo is not allowed
        Application application = ApplicationManager.getApplication();
        application.invokeLater(redo, ModalityState.nonModal(), project.getDisposed());
      }
    };

    redo.run();
    CommandProcessor.getInstance().executeCommand(project, () -> {
      UndoManager undoManager = UndoManager.getInstance(project);
      undoManager.undoableActionPerformed(action);
    }, IdeBundle.message("change.encoding.command.name", virtualFile.getName()), null, UndoConfirmationPolicy.REQUEST_CONFIRMATION);

    return true;
  }
public static boolean changeTo(@NotNull Project project,
                                 @NotNull Document document,
                                 Editor editor,
                                 @NotNull VirtualFile virtualFile,
                                 @NotNull Charset charset,
                                 @NotNull EncodingUtil.Magic8 isSafeToConvert, @NotNull EncodingUtil.Magic8 isSafeToReload)