"use strict";
const async = require("../../../../base/common/async.js");
const errors = require("../../../../base/common/errors.js");
const editorState = require("../../editorState/browser/editorState.js");
const editorExtensions = require("../../../browser/editorExtensions.js");
const range = require("../../../common/core/range.js");
const selection = require("../../../common/core/selection.js");
const editorContextKeys = require("../../../common/editorContextKeys.js");
const textModel = require("../../../common/model/textModel.js");
const editorWorker = require("../../../common/services/editorWorker.js");
const editorColorRegistry = require("../../../common/core/editorColorRegistry.js");
const nls = require("../../../../nls.js");
const themeService = require("../../../../platform/theme/common/themeService.js");
const inPlaceReplaceCommand = require("./inPlaceReplaceCommand.js");
var __decorate = globalThis && globalThis.__decorate || function(decorators, target, key, desc) {
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
    r = Reflect.decorate(decorators, target, key, desc);
  else
    for (var i = decorators.length - 1; i >= 0; i--)
      if (d = decorators[i])
        r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
  return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __param = globalThis && globalThis.__param || function(paramIndex, decorator) {
  return function(target, key) {
    decorator(target, key, paramIndex);
  };
};
let InPlaceReplaceController = class InPlaceReplaceController2 {
  constructor(editor, editorWorkerService) {
    this.decorationIds = [];
    this.editor = editor;
    this.editorWorkerService = editorWorkerService;
  }
  static get(editor) {
    return editor.getContribution(InPlaceReplaceController2.ID);
  }
  dispose() {
  }
  run(source, up) {
    if (this.currentRequest) {
      this.currentRequest.cancel();
    }
    const editorSelection = this.editor.getSelection();
    const model = this.editor.getModel();
    if (!model || !editorSelection) {
      return void 0;
    }
    let selection$1 = editorSelection;
    if (selection$1.startLineNumber !== selection$1.endLineNumber) {
      return void 0;
    }
    const state = new editorState.EditorState(
      this.editor,
      1 | 4
      /* Position */
    );
    const modelURI = model.uri;
    if (!this.editorWorkerService.canNavigateValueSet(modelURI)) {
      return Promise.resolve(void 0);
    }
    this.currentRequest = async.createCancelablePromise((token) => this.editorWorkerService.navigateValueSet(modelURI, selection$1, up));
    return this.currentRequest.then((result) => {
      if (!result || !result.range || !result.value) {
        return;
      }
      if (!state.validate(this.editor)) {
        return;
      }
      let editRange = range.Range.lift(result.range);
      let highlightRange = result.range;
      let diff = result.value.length - (selection$1.endColumn - selection$1.startColumn);
      highlightRange = {
        startLineNumber: highlightRange.startLineNumber,
        startColumn: highlightRange.startColumn,
        endLineNumber: highlightRange.endLineNumber,
        endColumn: highlightRange.startColumn + result.value.length
      };
      if (diff > 1) {
        selection$1 = new selection.Selection(selection$1.startLineNumber, selection$1.startColumn, selection$1.endLineNumber, selection$1.endColumn + diff - 1);
      }
      const command = new inPlaceReplaceCommand.InPlaceReplaceCommand(editRange, selection$1, result.value);
      this.editor.pushUndoStop();
      this.editor.executeCommand(source, command);
      this.editor.pushUndoStop();
      this.decorationIds = this.editor.deltaDecorations(this.decorationIds, [{
        range: highlightRange,
        options: InPlaceReplaceController2.DECORATION
      }]);
      if (this.decorationRemover) {
        this.decorationRemover.cancel();
      }
      this.decorationRemover = async.timeout(350);
      this.decorationRemover.then(() => this.decorationIds = this.editor.deltaDecorations(this.decorationIds, [])).catch(errors.onUnexpectedError);
    }).catch(errors.onUnexpectedError);
  }
};
InPlaceReplaceController.ID = "editor.contrib.inPlaceReplaceController";
InPlaceReplaceController.DECORATION = textModel.ModelDecorationOptions.register({
  description: "in-place-replace",
  className: "valueSetReplacement"
});
InPlaceReplaceController = __decorate([
  __param(1, editorWorker.IEditorWorkerService)
], InPlaceReplaceController);
class InPlaceReplaceUp extends editorExtensions.EditorAction {
  constructor() {
    super({
      id: "editor.action.inPlaceReplace.up",
      label: nls.localize("InPlaceReplaceAction.previous.label", "Replace with Previous Value"),
      alias: "Replace with Previous Value",
      precondition: editorContextKeys.EditorContextKeys.writable,
      kbOpts: {
        kbExpr: editorContextKeys.EditorContextKeys.editorTextFocus,
        primary: 2048 | 1024 | 82,
        weight: 100
        /* EditorContrib */
      }
    });
  }
  run(accessor, editor) {
    const controller = InPlaceReplaceController.get(editor);
    if (!controller) {
      return Promise.resolve(void 0);
    }
    return controller.run(this.id, true);
  }
}
class InPlaceReplaceDown extends editorExtensions.EditorAction {
  constructor() {
    super({
      id: "editor.action.inPlaceReplace.down",
      label: nls.localize("InPlaceReplaceAction.next.label", "Replace with Next Value"),
      alias: "Replace with Next Value",
      precondition: editorContextKeys.EditorContextKeys.writable,
      kbOpts: {
        kbExpr: editorContextKeys.EditorContextKeys.editorTextFocus,
        primary: 2048 | 1024 | 84,
        weight: 100
        /* EditorContrib */
      }
    });
  }
  run(accessor, editor) {
    const controller = InPlaceReplaceController.get(editor);
    if (!controller) {
      return Promise.resolve(void 0);
    }
    return controller.run(this.id, false);
  }
}
editorExtensions.registerEditorContribution(InPlaceReplaceController.ID, InPlaceReplaceController);
editorExtensions.registerEditorAction(InPlaceReplaceUp);
editorExtensions.registerEditorAction(InPlaceReplaceDown);
themeService.registerThemingParticipant((theme, collector) => {
  const border = theme.getColor(editorColorRegistry.editorBracketMatchBorder);
  if (border) {
    collector.addRule(`.monaco-editor.vs .valueSetReplacement { outline: solid 2px ${border}; }`);
  }
});
