import { Deferred as l, interruptAndCheck as u } from "../utils/promise-utils.js";
import { UriUtils as o } from "../utils/uri-utils.js";
import { c } from "../../../../../../../_virtual/cancellation.js";
import { URI as d } from "../../../../../vscode-uri@3.0.8/node_modules/vscode-uri/lib/esm/index.js";
class g {
  constructor(e) {
    this.initialBuildOptions = {}, this._ready = new l(), this.serviceRegistry = e.ServiceRegistry, this.langiumDocuments = e.workspace.LangiumDocuments, this.documentBuilder = e.workspace.DocumentBuilder, this.fileSystemProvider = e.workspace.FileSystemProvider, this.mutex = e.workspace.WorkspaceLock;
  }
  get ready() {
    return this._ready.promise;
  }
  get workspaceFolders() {
    return this.folders;
  }
  initialize(e) {
    var i;
    this.folders = (i = e.workspaceFolders) !== null && i !== void 0 ? i : void 0;
  }
  initialized(e) {
    return this.mutex.write((i) => {
      var r;
      return this.initializeWorkspace((r = this.folders) !== null && r !== void 0 ? r : [], i);
    });
  }
  async initializeWorkspace(e, i = c.CancellationToken.None) {
    const r = await this.performStartup(e);
    await u(i), await this.documentBuilder.build(r, this.initialBuildOptions, i);
  }
  /**
   * Performs the uninterruptable startup sequence of the workspace manager.
   * This methods loads all documents in the workspace and other documents and returns them.
   */
  async performStartup(e) {
    const i = this.serviceRegistry.all.flatMap((t) => t.LanguageMetaData.fileExtensions), r = [], s = (t) => {
      r.push(t), this.langiumDocuments.hasDocument(t.uri) || this.langiumDocuments.addDocument(t);
    };
    return await this.loadAdditionalDocuments(e, s), await Promise.all(e.map((t) => [t, this.getRootFolder(t)]).map(async (t) => this.traverseFolder(...t, i, s))), this._ready.resolve(), r;
  }
  /**
   * Load all additional documents that shall be visible in the context of the given workspace
   * folders and add them to the collector. This can be used to include built-in libraries of
   * your language, which can be either loaded from provided files or constructed in memory.
   */
  loadAdditionalDocuments(e, i) {
    return Promise.resolve();
  }
  /**
   * Determine the root folder of the source documents in the given workspace folder.
   * The default implementation returns the URI of the workspace folder, but you can override
   * this to return a subfolder like `src` instead.
   */
  getRootFolder(e) {
    return d.parse(e.uri);
  }
  /**
   * Traverse the file system folder identified by the given URI and its subfolders. All
   * contained files that match the file extensions are added to the collector.
   */
  async traverseFolder(e, i, r, s) {
    const t = await this.fileSystemProvider.readDirectory(i);
    await Promise.all(t.map(async (a) => {
      if (this.includeEntry(e, a, r)) {
        if (a.isDirectory)
          await this.traverseFolder(e, a.uri, r, s);
        else if (a.isFile) {
          const n = await this.langiumDocuments.getOrCreateDocument(a.uri);
          s(n);
        }
      }
    }));
  }
  /**
   * Determine whether the given folder entry shall be included while indexing the workspace.
   */
  includeEntry(e, i, r) {
    const s = o.basename(i.uri);
    if (s.startsWith("."))
      return !1;
    if (i.isDirectory)
      return s !== "node_modules" && s !== "out";
    if (i.isFile) {
      const t = o.extname(i.uri);
      return r.includes(t);
    }
    return !1;
  }
}
export {
  g as DefaultWorkspaceManager
};
