"use strict";
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const strings = require("../../../../../base/common/strings.js");
const ast = require("./ast.js");
const length = require("./length.js");
const smallImmutableSet = require("./smallImmutableSet.js");
const tokenizer = require("./tokenizer.js");
class BracketTokens {
  constructor(map) {
    this.map = map;
    this.hasRegExp = false;
    this._regExpGlobal = null;
  }
  static createFromLanguage(configuration, denseKeyProvider) {
    function getId(languageId, openingText) {
      return denseKeyProvider.getKey(`${languageId}:::${openingText}`);
    }
    const brackets = configuration.characterPair.getColorizedBrackets();
    const closingBrackets = /* @__PURE__ */ new Map();
    const openingBrackets = /* @__PURE__ */ new Set();
    for (const [openingText, closingText] of brackets) {
      openingBrackets.add(openingText);
      let info = closingBrackets.get(closingText);
      const openingTextId = getId(configuration.languageId, openingText);
      if (!info) {
        info = { openingBrackets: smallImmutableSet.SmallImmutableSet.getEmpty(), first: openingTextId };
        closingBrackets.set(closingText, info);
      }
      info.openingBrackets = info.openingBrackets.add(openingTextId, smallImmutableSet.identityKeyProvider);
    }
    const map = /* @__PURE__ */ new Map();
    for (const [closingText, info] of closingBrackets) {
      const length$1 = length.toLength(0, closingText.length);
      map.set(closingText, new tokenizer.Token(length$1, 2, info.first, info.openingBrackets, ast.BracketAstNode.create(length$1, configuration.languageId, info.openingBrackets)));
    }
    for (const openingText of openingBrackets) {
      const length$1 = length.toLength(0, openingText.length);
      const openingTextId = getId(configuration.languageId, openingText);
      const bracketIds = smallImmutableSet.SmallImmutableSet.getEmpty().add(openingTextId, smallImmutableSet.identityKeyProvider);
      map.set(openingText, new tokenizer.Token(length$1, 1, openingTextId, bracketIds, ast.BracketAstNode.create(length$1, configuration.languageId, bracketIds)));
    }
    return new BracketTokens(map);
  }
  getRegExpStr() {
    if (this.isEmpty) {
      return null;
    } else {
      const keys = [...this.map.keys()];
      keys.sort();
      keys.reverse();
      return keys.map((k) => prepareBracketForRegExp(k)).join("|");
    }
  }
  /**
   * Returns null if there is no such regexp (because there are no brackets).
  */
  get regExpGlobal() {
    if (!this.hasRegExp) {
      const regExpStr = this.getRegExpStr();
      this._regExpGlobal = regExpStr ? new RegExp(regExpStr, "g") : null;
      this.hasRegExp = true;
    }
    return this._regExpGlobal;
  }
  getToken(value) {
    return this.map.get(value);
  }
  findClosingTokenText(openingBracketIds) {
    for (const [closingText, info] of this.map) {
      if (info.bracketIds.intersects(openingBracketIds)) {
        return closingText;
      }
    }
    return void 0;
  }
  get isEmpty() {
    return this.map.size === 0;
  }
}
function prepareBracketForRegExp(str) {
  const escaped = strings.escapeRegExpCharacters(str);
  const needsWordBoundaries = /^[\w ]+$/.test(str);
  return needsWordBoundaries ? `\\b${escaped}\\b` : escaped;
}
class LanguageAgnosticBracketTokens {
  constructor(denseKeyProvider, getLanguageConfiguration) {
    this.denseKeyProvider = denseKeyProvider;
    this.getLanguageConfiguration = getLanguageConfiguration;
    this.languageIdToBracketTokens = /* @__PURE__ */ new Map();
  }
  didLanguageChange(languageId) {
    const existing = this.languageIdToBracketTokens.get(languageId);
    if (!existing) {
      return false;
    }
    const newRegExpStr = BracketTokens.createFromLanguage(this.getLanguageConfiguration(languageId), this.denseKeyProvider).getRegExpStr();
    return existing.getRegExpStr() !== newRegExpStr;
  }
  getSingleLanguageBracketTokens(languageId) {
    let singleLanguageBracketTokens = this.languageIdToBracketTokens.get(languageId);
    if (!singleLanguageBracketTokens) {
      singleLanguageBracketTokens = BracketTokens.createFromLanguage(this.getLanguageConfiguration(languageId), this.denseKeyProvider);
      this.languageIdToBracketTokens.set(languageId, singleLanguageBracketTokens);
    }
    return singleLanguageBracketTokens;
  }
}
exports.BracketTokens = BracketTokens;
exports.LanguageAgnosticBracketTokens = LanguageAgnosticBracketTokens;
