import { Deferred, interruptAndCheck } from "./lib-utils-promise-utils.js";
import { UriUtils } from "./lib-utils-uri-utils.js";
import { c as cancellationExports } from "../../_virtual/cancellation.js";
import { URI } from "../vscode-uri/lib-esm-index.js";
class DefaultWorkspaceManager {
  constructor(services) {
    this.initialBuildOptions = {};
    this._ready = new Deferred();
    this.serviceRegistry = services.ServiceRegistry;
    this.langiumDocuments = services.workspace.LangiumDocuments;
    this.documentBuilder = services.workspace.DocumentBuilder;
    this.fileSystemProvider = services.workspace.FileSystemProvider;
    this.mutex = services.workspace.WorkspaceLock;
  }
  get ready() {
    return this._ready.promise;
  }
  get workspaceFolders() {
    return this.folders;
  }
  initialize(params) {
    var _a;
    this.folders = (_a = params.workspaceFolders) !== null && _a !== void 0 ? _a : void 0;
  }
  initialized(_params) {
    return this.mutex.write((token) => {
      var _a;
      return this.initializeWorkspace((_a = this.folders) !== null && _a !== void 0 ? _a : [], token);
    });
  }
  async initializeWorkspace(folders, cancelToken = cancellationExports.CancellationToken.None) {
    const documents = await this.performStartup(folders);
    await interruptAndCheck(cancelToken);
    await this.documentBuilder.build(documents, this.initialBuildOptions, cancelToken);
  }
  /**
   * 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(folders) {
    const fileExtensions = this.serviceRegistry.all.flatMap((e) => e.LanguageMetaData.fileExtensions);
    const documents = [];
    const collector = (document) => {
      documents.push(document);
      if (!this.langiumDocuments.hasDocument(document.uri)) {
        this.langiumDocuments.addDocument(document);
      }
    };
    await this.loadAdditionalDocuments(folders, collector);
    await Promise.all(folders.map((wf) => [wf, this.getRootFolder(wf)]).map(async (entry) => this.traverseFolder(...entry, fileExtensions, collector)));
    this._ready.resolve();
    return documents;
  }
  /**
   * 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(_folders, _collector) {
    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(workspaceFolder) {
    return URI.parse(workspaceFolder.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(workspaceFolder, folderPath, fileExtensions, collector) {
    const content = await this.fileSystemProvider.readDirectory(folderPath);
    await Promise.all(content.map(async (entry) => {
      if (this.includeEntry(workspaceFolder, entry, fileExtensions)) {
        if (entry.isDirectory) {
          await this.traverseFolder(workspaceFolder, entry.uri, fileExtensions, collector);
        } else if (entry.isFile) {
          const document = await this.langiumDocuments.getOrCreateDocument(entry.uri);
          collector(document);
        }
      }
    }));
  }
  /**
   * Determine whether the given folder entry shall be included while indexing the workspace.
   */
  includeEntry(_workspaceFolder, entry, fileExtensions) {
    const name = UriUtils.basename(entry.uri);
    if (name.startsWith(".")) {
      return false;
    }
    if (entry.isDirectory) {
      return name !== "node_modules" && name !== "out";
    } else if (entry.isFile) {
      const extname = UriUtils.extname(entry.uri);
      return fileExtensions.includes(extname);
    }
    return false;
  }
}
export {
  DefaultWorkspaceManager
};
//# sourceMappingURL=lib-workspace-workspace-manager.js.map
