import { once } from "../../../../base/common/functional.mjs";
import { DisposableStore, MutableDisposable, toDisposable } from "../../../../base/common/lifecycle.mjs";
import { withNullAsUndefined } from "../../../../base/common/types.mjs";
import { getCodeEditor, isDiffEditor } from "../../../browser/editorBrowser.mjs";
import { OverviewRulerLane } from "../../../common/model.mjs";
import { overviewRulerRangeHighlight } from "../../../common/core/editorColorRegistry.mjs";
import { themeColorFromId } from "../../../../platform/theme/common/themeService.mjs";
class AbstractEditorNavigationQuickAccessProvider {
  constructor(options) {
    this.options = options;
    this.rangeHighlightDecorationId = void 0;
  }
  //#region Provider methods
  provide(picker, token) {
    var _a;
    const disposables = new DisposableStore();
    picker.canAcceptInBackground = !!((_a = this.options) === null || _a === void 0 ? void 0 : _a.canAcceptInBackground);
    picker.matchOnLabel = picker.matchOnDescription = picker.matchOnDetail = picker.sortByLabel = false;
    const pickerDisposable = disposables.add(new MutableDisposable());
    pickerDisposable.value = this.doProvide(picker, token);
    disposables.add(this.onDidActiveTextEditorControlChange(() => {
      pickerDisposable.value = void 0;
      pickerDisposable.value = this.doProvide(picker, token);
    }));
    return disposables;
  }
  doProvide(picker, token) {
    const disposables = new DisposableStore();
    const editor = this.activeTextEditorControl;
    if (editor && this.canProvideWithTextEditor(editor)) {
      const context = { editor };
      const codeEditor = getCodeEditor(editor);
      if (codeEditor) {
        let lastKnownEditorViewState = withNullAsUndefined(editor.saveViewState());
        disposables.add(codeEditor.onDidChangeCursorPosition(() => {
          lastKnownEditorViewState = withNullAsUndefined(editor.saveViewState());
        }));
        context.restoreViewState = () => {
          if (lastKnownEditorViewState && editor === this.activeTextEditorControl) {
            editor.restoreViewState(lastKnownEditorViewState);
          }
        };
        disposables.add(once(token.onCancellationRequested)(() => {
          var _a;
          return (_a = context.restoreViewState) === null || _a === void 0 ? void 0 : _a.call(context);
        }));
      }
      disposables.add(toDisposable(() => this.clearDecorations(editor)));
      disposables.add(this.provideWithTextEditor(context, picker, token));
    } else {
      disposables.add(this.provideWithoutTextEditor(picker, token));
    }
    return disposables;
  }
  /**
   * Subclasses to implement if they can operate on the text editor.
   */
  canProvideWithTextEditor(editor) {
    return true;
  }
  gotoLocation({ editor }, options) {
    editor.setSelection(options.range);
    editor.revealRangeInCenter(
      options.range,
      0
      /* Smooth */
    );
    if (!options.preserveFocus) {
      editor.focus();
    }
  }
  getModel(editor) {
    var _a;
    return isDiffEditor(editor) ? (_a = editor.getModel()) === null || _a === void 0 ? void 0 : _a.modified : editor.getModel();
  }
  addDecorations(editor, range) {
    editor.changeDecorations((changeAccessor) => {
      const deleteDecorations = [];
      if (this.rangeHighlightDecorationId) {
        deleteDecorations.push(this.rangeHighlightDecorationId.overviewRulerDecorationId);
        deleteDecorations.push(this.rangeHighlightDecorationId.rangeHighlightId);
        this.rangeHighlightDecorationId = void 0;
      }
      const newDecorations = [
        // highlight the entire line on the range
        {
          range,
          options: {
            description: "quick-access-range-highlight",
            className: "rangeHighlight",
            isWholeLine: true
          }
        },
        // also add overview ruler highlight
        {
          range,
          options: {
            description: "quick-access-range-highlight-overview",
            overviewRuler: {
              color: themeColorFromId(overviewRulerRangeHighlight),
              position: OverviewRulerLane.Full
            }
          }
        }
      ];
      const [rangeHighlightId, overviewRulerDecorationId] = changeAccessor.deltaDecorations(deleteDecorations, newDecorations);
      this.rangeHighlightDecorationId = { rangeHighlightId, overviewRulerDecorationId };
    });
  }
  clearDecorations(editor) {
    const rangeHighlightDecorationId = this.rangeHighlightDecorationId;
    if (rangeHighlightDecorationId) {
      editor.changeDecorations((changeAccessor) => {
        changeAccessor.deltaDecorations([
          rangeHighlightDecorationId.overviewRulerDecorationId,
          rangeHighlightDecorationId.rangeHighlightId
        ], []);
      });
      this.rangeHighlightDecorationId = void 0;
    }
  }
}
export {
  AbstractEditorNavigationQuickAccessProvider
};
