import { firstNonWhitespaceIndex, getLeftDeleteOffset } from "../../../base/common/strings.mjs";
import { ReplaceCommand } from "../commands/replaceCommand.mjs";
import { isQuote, EditOperationResult } from "../cursorCommon.mjs";
import { CursorColumns } from "../core/cursorColumns.mjs";
import { MoveOperations } from "./cursorMoveOperations.mjs";
import { Range } from "../core/range.mjs";
import { Position } from "../core/position.mjs";
class DeleteOperations {
  static deleteRight(prevEditOperationType, config, model, selections) {
    const commands = [];
    let shouldPushStackElementBefore = prevEditOperationType !== 3;
    for (let i = 0, len = selections.length; i < len; i++) {
      const selection = selections[i];
      let deleteSelection = selection;
      if (deleteSelection.isEmpty()) {
        const position = selection.getPosition();
        const rightOfPosition = MoveOperations.right(config, model, position);
        deleteSelection = new Range(rightOfPosition.lineNumber, rightOfPosition.column, position.lineNumber, position.column);
      }
      if (deleteSelection.isEmpty()) {
        commands[i] = null;
        continue;
      }
      if (deleteSelection.startLineNumber !== deleteSelection.endLineNumber) {
        shouldPushStackElementBefore = true;
      }
      commands[i] = new ReplaceCommand(deleteSelection, "");
    }
    return [shouldPushStackElementBefore, commands];
  }
  static isAutoClosingPairDelete(autoClosingDelete, autoClosingBrackets, autoClosingQuotes, autoClosingPairsOpen, model, selections, autoClosedCharacters) {
    if (autoClosingBrackets === "never" && autoClosingQuotes === "never") {
      return false;
    }
    if (autoClosingDelete === "never") {
      return false;
    }
    for (let i = 0, len = selections.length; i < len; i++) {
      const selection = selections[i];
      const position = selection.getPosition();
      if (!selection.isEmpty()) {
        return false;
      }
      const lineText = model.getLineContent(position.lineNumber);
      if (position.column < 2 || position.column >= lineText.length + 1) {
        return false;
      }
      const character = lineText.charAt(position.column - 2);
      const autoClosingPairCandidates = autoClosingPairsOpen.get(character);
      if (!autoClosingPairCandidates) {
        return false;
      }
      if (isQuote(character)) {
        if (autoClosingQuotes === "never") {
          return false;
        }
      } else {
        if (autoClosingBrackets === "never") {
          return false;
        }
      }
      const afterCharacter = lineText.charAt(position.column - 1);
      let foundAutoClosingPair = false;
      for (const autoClosingPairCandidate of autoClosingPairCandidates) {
        if (autoClosingPairCandidate.open === character && autoClosingPairCandidate.close === afterCharacter) {
          foundAutoClosingPair = true;
        }
      }
      if (!foundAutoClosingPair) {
        return false;
      }
      if (autoClosingDelete === "auto") {
        let found = false;
        for (let j = 0, lenJ = autoClosedCharacters.length; j < lenJ; j++) {
          const autoClosedCharacter = autoClosedCharacters[j];
          if (position.lineNumber === autoClosedCharacter.startLineNumber && position.column === autoClosedCharacter.startColumn) {
            found = true;
            break;
          }
        }
        if (!found) {
          return false;
        }
      }
    }
    return true;
  }
  static _runAutoClosingPairDelete(config, model, selections) {
    const commands = [];
    for (let i = 0, len = selections.length; i < len; i++) {
      const position = selections[i].getPosition();
      const deleteSelection = new Range(position.lineNumber, position.column - 1, position.lineNumber, position.column + 1);
      commands[i] = new ReplaceCommand(deleteSelection, "");
    }
    return [true, commands];
  }
  static deleteLeft(prevEditOperationType, config, model, selections, autoClosedCharacters) {
    if (this.isAutoClosingPairDelete(config.autoClosingDelete, config.autoClosingBrackets, config.autoClosingQuotes, config.autoClosingPairs.autoClosingPairsOpenByEnd, model, selections, autoClosedCharacters)) {
      return this._runAutoClosingPairDelete(config, model, selections);
    }
    const commands = [];
    let shouldPushStackElementBefore = prevEditOperationType !== 2;
    for (let i = 0, len = selections.length; i < len; i++) {
      const deleteRange = DeleteOperations.getDeleteRange(selections[i], model, config);
      if (deleteRange.isEmpty()) {
        commands[i] = null;
        continue;
      }
      if (deleteRange.startLineNumber !== deleteRange.endLineNumber) {
        shouldPushStackElementBefore = true;
      }
      commands[i] = new ReplaceCommand(deleteRange, "");
    }
    return [shouldPushStackElementBefore, commands];
  }
  static getDeleteRange(selection, model, config) {
    if (!selection.isEmpty()) {
      return selection;
    }
    const position = selection.getPosition();
    if (config.useTabStops && position.column > 1) {
      const lineContent = model.getLineContent(position.lineNumber);
      const firstNonWhitespaceIndex$1 = firstNonWhitespaceIndex(lineContent);
      const lastIndentationColumn = firstNonWhitespaceIndex$1 === -1 ? (
        /* entire string is whitespace */
        lineContent.length + 1
      ) : firstNonWhitespaceIndex$1 + 1;
      if (position.column <= lastIndentationColumn) {
        const fromVisibleColumn = config.visibleColumnFromColumn(model, position);
        const toVisibleColumn = CursorColumns.prevIndentTabStop(fromVisibleColumn, config.indentSize);
        const toColumn = config.columnFromVisibleColumn(model, position.lineNumber, toVisibleColumn);
        return new Range(position.lineNumber, toColumn, position.lineNumber, position.column);
      }
    }
    return Range.fromPositions(DeleteOperations.getPositionAfterDeleteLeft(position, model), position);
  }
  static getPositionAfterDeleteLeft(position, model) {
    if (position.column > 1) {
      const idx = getLeftDeleteOffset(position.column - 1, model.getLineContent(position.lineNumber));
      return position.with(void 0, idx + 1);
    } else if (position.lineNumber > 1) {
      const newLine = position.lineNumber - 1;
      return new Position(newLine, model.getLineMaxColumn(newLine));
    } else {
      return position;
    }
  }
  static cut(config, model, selections) {
    const commands = [];
    let lastCutRange = null;
    selections.sort((a, b) => Position.compare(a.getStartPosition(), b.getEndPosition()));
    for (let i = 0, len = selections.length; i < len; i++) {
      const selection = selections[i];
      if (selection.isEmpty()) {
        if (config.emptySelectionClipboard) {
          const position = selection.getPosition();
          let startLineNumber, startColumn, endLineNumber, endColumn;
          if (position.lineNumber < model.getLineCount()) {
            startLineNumber = position.lineNumber;
            startColumn = 1;
            endLineNumber = position.lineNumber + 1;
            endColumn = 1;
          } else if (position.lineNumber > 1 && (lastCutRange === null || lastCutRange === void 0 ? void 0 : lastCutRange.endLineNumber) !== position.lineNumber) {
            startLineNumber = position.lineNumber - 1;
            startColumn = model.getLineMaxColumn(position.lineNumber - 1);
            endLineNumber = position.lineNumber;
            endColumn = model.getLineMaxColumn(position.lineNumber);
          } else {
            startLineNumber = position.lineNumber;
            startColumn = 1;
            endLineNumber = position.lineNumber;
            endColumn = model.getLineMaxColumn(position.lineNumber);
          }
          const deleteSelection = new Range(startLineNumber, startColumn, endLineNumber, endColumn);
          lastCutRange = deleteSelection;
          if (!deleteSelection.isEmpty()) {
            commands[i] = new ReplaceCommand(deleteSelection, "");
          } else {
            commands[i] = null;
          }
        } else {
          commands[i] = null;
        }
      } else {
        commands[i] = new ReplaceCommand(selection, "");
      }
    }
    return new EditOperationResult(0, commands, {
      shouldPushStackElementBefore: true,
      shouldPushStackElementAfter: true
    });
  }
}
export {
  DeleteOperations
};
