"use strict";
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const linkedList = require("../../../../base/common/linkedList.js");
const position = require("../../../common/core/position.js");
const range = require("../../../common/core/range.js");
var __awaiter = globalThis && globalThis.__awaiter || function(thisArg, _arguments, P, generator) {
  function adopt(value) {
    return value instanceof P ? value : new P(function(resolve) {
      resolve(value);
    });
  }
  return new (P || (P = Promise))(function(resolve, reject) {
    function fulfilled(value) {
      try {
        step(generator.next(value));
      } catch (e) {
        reject(e);
      }
    }
    function rejected(value) {
      try {
        step(generator["throw"](value));
      } catch (e) {
        reject(e);
      }
    }
    function step(result) {
      result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected);
    }
    step((generator = generator.apply(thisArg, _arguments || [])).next());
  });
};
class BracketSelectionRangeProvider {
  provideSelectionRanges(model, positions) {
    return __awaiter(this, void 0, void 0, function* () {
      const result = [];
      for (const position2 of positions) {
        const bucket = [];
        result.push(bucket);
        const ranges = /* @__PURE__ */ new Map();
        yield new Promise((resolve) => BracketSelectionRangeProvider._bracketsRightYield(resolve, 0, model, position2, ranges));
        yield new Promise((resolve) => BracketSelectionRangeProvider._bracketsLeftYield(resolve, 0, model, position2, ranges, bucket));
      }
      return result;
    });
  }
  static _bracketsRightYield(resolve, round, model, pos, ranges) {
    const counts = /* @__PURE__ */ new Map();
    const t1 = Date.now();
    while (true) {
      if (round >= BracketSelectionRangeProvider._maxRounds) {
        resolve();
        break;
      }
      if (!pos) {
        resolve();
        break;
      }
      let bracket = model.bracketPairs.findNextBracket(pos);
      if (!bracket) {
        resolve();
        break;
      }
      let d = Date.now() - t1;
      if (d > BracketSelectionRangeProvider._maxDuration) {
        setTimeout(() => BracketSelectionRangeProvider._bracketsRightYield(resolve, round + 1, model, pos, ranges));
        break;
      }
      const key = bracket.close[0];
      if (bracket.isOpen) {
        let val = counts.has(key) ? counts.get(key) : 0;
        counts.set(key, val + 1);
      } else {
        let val = counts.has(key) ? counts.get(key) : 0;
        val -= 1;
        counts.set(key, Math.max(0, val));
        if (val < 0) {
          let list = ranges.get(key);
          if (!list) {
            list = new linkedList.LinkedList();
            ranges.set(key, list);
          }
          list.push(bracket.range);
        }
      }
      pos = bracket.range.getEndPosition();
    }
  }
  static _bracketsLeftYield(resolve, round, model, pos, ranges, bucket) {
    const counts = /* @__PURE__ */ new Map();
    const t1 = Date.now();
    while (true) {
      if (round >= BracketSelectionRangeProvider._maxRounds && ranges.size === 0) {
        resolve();
        break;
      }
      if (!pos) {
        resolve();
        break;
      }
      let bracket = model.bracketPairs.findPrevBracket(pos);
      if (!bracket) {
        resolve();
        break;
      }
      let d = Date.now() - t1;
      if (d > BracketSelectionRangeProvider._maxDuration) {
        setTimeout(() => BracketSelectionRangeProvider._bracketsLeftYield(resolve, round + 1, model, pos, ranges, bucket));
        break;
      }
      const key = bracket.close[0];
      if (!bracket.isOpen) {
        let val = counts.has(key) ? counts.get(key) : 0;
        counts.set(key, val + 1);
      } else {
        let val = counts.has(key) ? counts.get(key) : 0;
        val -= 1;
        counts.set(key, Math.max(0, val));
        if (val < 0) {
          let list = ranges.get(key);
          if (list) {
            let closing = list.shift();
            if (list.size === 0) {
              ranges.delete(key);
            }
            const innerBracket = range.Range.fromPositions(bracket.range.getEndPosition(), closing.getStartPosition());
            const outerBracket = range.Range.fromPositions(bracket.range.getStartPosition(), closing.getEndPosition());
            bucket.push({ range: innerBracket });
            bucket.push({ range: outerBracket });
            BracketSelectionRangeProvider._addBracketLeading(model, outerBracket, bucket);
          }
        }
      }
      pos = bracket.range.getStartPosition();
    }
  }
  static _addBracketLeading(model, bracket, bucket) {
    if (bracket.startLineNumber === bracket.endLineNumber) {
      return;
    }
    const startLine = bracket.startLineNumber;
    const column = model.getLineFirstNonWhitespaceColumn(startLine);
    if (column !== 0 && column !== bracket.startColumn) {
      bucket.push({ range: range.Range.fromPositions(new position.Position(startLine, column), bracket.getEndPosition()) });
      bucket.push({ range: range.Range.fromPositions(new position.Position(startLine, 1), bracket.getEndPosition()) });
    }
    const aboveLine = startLine - 1;
    if (aboveLine > 0) {
      const column2 = model.getLineFirstNonWhitespaceColumn(aboveLine);
      if (column2 === bracket.startColumn && column2 !== model.getLineLastNonWhitespaceColumn(aboveLine)) {
        bucket.push({ range: range.Range.fromPositions(new position.Position(aboveLine, column2), bracket.getEndPosition()) });
        bucket.push({ range: range.Range.fromPositions(new position.Position(aboveLine, 1), bracket.getEndPosition()) });
      }
    }
  }
}
BracketSelectionRangeProvider._maxDuration = 30;
BracketSelectionRangeProvider._maxRounds = 2;
exports.BracketSelectionRangeProvider = BracketSelectionRangeProvider;
