"use strict";
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const listView = require("../list/listView.js");
const abstractTree = require("./abstractTree.js");
const indexTreeModel = require("./indexTreeModel.js");
const objectTree = require("./objectTree.js");
const tree = require("./tree.js");
const async = require("../../../common/async.js");
const codicons = require("../../../common/codicons.js");
const errors = require("../../../common/errors.js");
const event = require("../../../common/event.js");
const iterator = require("../../../common/iterator.js");
const lifecycle = require("../../../common/lifecycle.js");
const types = require("../../../common/types.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());
  });
};
function createAsyncDataTreeNode(props) {
  return Object.assign(Object.assign({}, props), { children: [], refreshPromise: void 0, stale: true, slow: false, collapsedByDefault: void 0 });
}
function isAncestor(ancestor, descendant) {
  if (!descendant.parent) {
    return false;
  } else if (descendant.parent === ancestor) {
    return true;
  } else {
    return isAncestor(ancestor, descendant.parent);
  }
}
function intersects(node, other) {
  return node === other || isAncestor(node, other) || isAncestor(other, node);
}
class AsyncDataTreeNodeWrapper {
  constructor(node) {
    this.node = node;
  }
  get element() {
    return this.node.element.element;
  }
  get children() {
    return this.node.children.map((node) => new AsyncDataTreeNodeWrapper(node));
  }
  get depth() {
    return this.node.depth;
  }
  get visibleChildrenCount() {
    return this.node.visibleChildrenCount;
  }
  get visibleChildIndex() {
    return this.node.visibleChildIndex;
  }
  get collapsible() {
    return this.node.collapsible;
  }
  get collapsed() {
    return this.node.collapsed;
  }
  get visible() {
    return this.node.visible;
  }
  get filterData() {
    return this.node.filterData;
  }
}
class AsyncDataTreeRenderer {
  constructor(renderer, nodeMapper, onDidChangeTwistieState) {
    this.renderer = renderer;
    this.nodeMapper = nodeMapper;
    this.onDidChangeTwistieState = onDidChangeTwistieState;
    this.renderedNodes = /* @__PURE__ */ new Map();
    this.templateId = renderer.templateId;
  }
  renderTemplate(container) {
    const templateData = this.renderer.renderTemplate(container);
    return { templateData };
  }
  renderElement(node, index, templateData, height) {
    this.renderer.renderElement(this.nodeMapper.map(node), index, templateData.templateData, height);
  }
  renderTwistie(element, twistieElement) {
    if (element.slow) {
      twistieElement.classList.add(...codicons.Codicon.treeItemLoading.classNamesArray);
      return true;
    } else {
      twistieElement.classList.remove(...codicons.Codicon.treeItemLoading.classNamesArray);
      return false;
    }
  }
  disposeElement(node, index, templateData, height) {
    if (this.renderer.disposeElement) {
      this.renderer.disposeElement(this.nodeMapper.map(node), index, templateData.templateData, height);
    }
  }
  disposeTemplate(templateData) {
    this.renderer.disposeTemplate(templateData.templateData);
  }
  dispose() {
    this.renderedNodes.clear();
  }
}
function asTreeEvent(e) {
  return {
    browserEvent: e.browserEvent,
    elements: e.elements.map((e2) => e2.element)
  };
}
function asTreeMouseEvent(e) {
  return {
    browserEvent: e.browserEvent,
    element: e.element && e.element.element,
    target: e.target
  };
}
class AsyncDataTreeElementsDragAndDropData extends listView.ElementsDragAndDropData {
  constructor(data) {
    super(data.elements.map((node) => node.element));
    this.data = data;
  }
}
function asAsyncDataTreeDragAndDropData(data) {
  if (data instanceof listView.ElementsDragAndDropData) {
    return new AsyncDataTreeElementsDragAndDropData(data);
  }
  return data;
}
class AsyncDataTreeNodeListDragAndDrop {
  constructor(dnd) {
    this.dnd = dnd;
  }
  getDragURI(node) {
    return this.dnd.getDragURI(node.element);
  }
  getDragLabel(nodes, originalEvent) {
    if (this.dnd.getDragLabel) {
      return this.dnd.getDragLabel(nodes.map((node) => node.element), originalEvent);
    }
    return void 0;
  }
  onDragStart(data, originalEvent) {
    if (this.dnd.onDragStart) {
      this.dnd.onDragStart(asAsyncDataTreeDragAndDropData(data), originalEvent);
    }
  }
  onDragOver(data, targetNode, targetIndex, originalEvent, raw = true) {
    return this.dnd.onDragOver(asAsyncDataTreeDragAndDropData(data), targetNode && targetNode.element, targetIndex, originalEvent);
  }
  drop(data, targetNode, targetIndex, originalEvent) {
    this.dnd.drop(asAsyncDataTreeDragAndDropData(data), targetNode && targetNode.element, targetIndex, originalEvent);
  }
  onDragEnd(originalEvent) {
    if (this.dnd.onDragEnd) {
      this.dnd.onDragEnd(originalEvent);
    }
  }
}
function asObjectTreeOptions(options) {
  return options && Object.assign(Object.assign({}, options), { collapseByDefault: true, identityProvider: options.identityProvider && {
    getId(el) {
      return options.identityProvider.getId(el.element);
    }
  }, dnd: options.dnd && new AsyncDataTreeNodeListDragAndDrop(options.dnd), multipleSelectionController: options.multipleSelectionController && {
    isSelectionSingleChangeEvent(e) {
      return options.multipleSelectionController.isSelectionSingleChangeEvent(Object.assign(Object.assign({}, e), { element: e.element }));
    },
    isSelectionRangeChangeEvent(e) {
      return options.multipleSelectionController.isSelectionRangeChangeEvent(Object.assign(Object.assign({}, e), { element: e.element }));
    }
  }, accessibilityProvider: options.accessibilityProvider && Object.assign(Object.assign({}, options.accessibilityProvider), {
    getPosInSet: void 0,
    getSetSize: void 0,
    getRole: options.accessibilityProvider.getRole ? (el) => {
      return options.accessibilityProvider.getRole(el.element);
    } : () => "treeitem",
    isChecked: options.accessibilityProvider.isChecked ? (e) => {
      var _a;
      return !!((_a = options.accessibilityProvider) === null || _a === void 0 ? void 0 : _a.isChecked(e.element));
    } : void 0,
    getAriaLabel(e) {
      return options.accessibilityProvider.getAriaLabel(e.element);
    },
    getWidgetAriaLabel() {
      return options.accessibilityProvider.getWidgetAriaLabel();
    },
    getWidgetRole: options.accessibilityProvider.getWidgetRole ? () => options.accessibilityProvider.getWidgetRole() : () => "tree",
    getAriaLevel: options.accessibilityProvider.getAriaLevel && ((node) => {
      return options.accessibilityProvider.getAriaLevel(node.element);
    }),
    getActiveDescendantId: options.accessibilityProvider.getActiveDescendantId && ((node) => {
      return options.accessibilityProvider.getActiveDescendantId(node.element);
    })
  }), filter: options.filter && {
    filter(e, parentVisibility) {
      return options.filter.filter(e.element, parentVisibility);
    }
  }, keyboardNavigationLabelProvider: options.keyboardNavigationLabelProvider && Object.assign(Object.assign({}, options.keyboardNavigationLabelProvider), { getKeyboardNavigationLabel(e) {
    return options.keyboardNavigationLabelProvider.getKeyboardNavigationLabel(e.element);
  } }), sorter: void 0, expandOnlyOnTwistieClick: typeof options.expandOnlyOnTwistieClick === "undefined" ? void 0 : typeof options.expandOnlyOnTwistieClick !== "function" ? options.expandOnlyOnTwistieClick : (e) => options.expandOnlyOnTwistieClick(e.element), additionalScrollHeight: options.additionalScrollHeight });
}
function dfs(node, fn) {
  fn(node);
  node.children.forEach((child) => dfs(child, fn));
}
class AsyncDataTree {
  constructor(user, container, delegate, renderers, dataSource, options = {}) {
    this.user = user;
    this.dataSource = dataSource;
    this.nodes = /* @__PURE__ */ new Map();
    this.subTreeRefreshPromises = /* @__PURE__ */ new Map();
    this.refreshPromises = /* @__PURE__ */ new Map();
    this._onDidRender = new event.Emitter();
    this._onDidChangeNodeSlowState = new event.Emitter();
    this.nodeMapper = new tree.WeakMapper((node) => new AsyncDataTreeNodeWrapper(node));
    this.disposables = new lifecycle.DisposableStore();
    this.identityProvider = options.identityProvider;
    this.autoExpandSingleChildren = typeof options.autoExpandSingleChildren === "undefined" ? false : options.autoExpandSingleChildren;
    this.sorter = options.sorter;
    this.collapseByDefault = options.collapseByDefault;
    this.tree = this.createTree(user, container, delegate, renderers, options);
    this.root = createAsyncDataTreeNode({
      element: void 0,
      parent: null,
      hasChildren: true
    });
    if (this.identityProvider) {
      this.root = Object.assign(Object.assign({}, this.root), { id: null });
    }
    this.nodes.set(null, this.root);
    this.tree.onDidChangeCollapseState(this._onDidChangeCollapseState, this, this.disposables);
  }
  get onDidChangeFocus() {
    return event.Event.map(this.tree.onDidChangeFocus, asTreeEvent);
  }
  get onDidChangeSelection() {
    return event.Event.map(this.tree.onDidChangeSelection, asTreeEvent);
  }
  get onMouseDblClick() {
    return event.Event.map(this.tree.onMouseDblClick, asTreeMouseEvent);
  }
  get onPointer() {
    return event.Event.map(this.tree.onPointer, asTreeMouseEvent);
  }
  get onDidFocus() {
    return this.tree.onDidFocus;
  }
  get onDidChangeModel() {
    return this.tree.onDidChangeModel;
  }
  get onDidChangeCollapseState() {
    return this.tree.onDidChangeCollapseState;
  }
  get onDidDispose() {
    return this.tree.onDidDispose;
  }
  createTree(user, container, delegate, renderers, options) {
    const objectTreeDelegate = new abstractTree.ComposedTreeDelegate(delegate);
    const objectTreeRenderers = renderers.map((r) => new AsyncDataTreeRenderer(r, this.nodeMapper, this._onDidChangeNodeSlowState.event));
    const objectTreeOptions = asObjectTreeOptions(options) || {};
    return new objectTree.ObjectTree(user, container, objectTreeDelegate, objectTreeRenderers, objectTreeOptions);
  }
  updateOptions(options = {}) {
    this.tree.updateOptions(options);
  }
  // Widget
  getHTMLElement() {
    return this.tree.getHTMLElement();
  }
  get scrollTop() {
    return this.tree.scrollTop;
  }
  set scrollTop(scrollTop) {
    this.tree.scrollTop = scrollTop;
  }
  domFocus() {
    this.tree.domFocus();
  }
  layout(height, width) {
    this.tree.layout(height, width);
  }
  style(styles) {
    this.tree.style(styles);
  }
  // Model
  getInput() {
    return this.root.element;
  }
  setInput(input, viewState) {
    return __awaiter(this, void 0, void 0, function* () {
      this.refreshPromises.forEach((promise) => promise.cancel());
      this.refreshPromises.clear();
      this.root.element = input;
      const viewStateContext = viewState && { viewState, focus: [], selection: [] };
      yield this._updateChildren(input, true, false, viewStateContext);
      if (viewStateContext) {
        this.tree.setFocus(viewStateContext.focus);
        this.tree.setSelection(viewStateContext.selection);
      }
      if (viewState && typeof viewState.scrollTop === "number") {
        this.scrollTop = viewState.scrollTop;
      }
    });
  }
  _updateChildren(element = this.root.element, recursive = true, rerender = false, viewStateContext, options) {
    return __awaiter(this, void 0, void 0, function* () {
      if (typeof this.root.element === "undefined") {
        throw new tree.TreeError(this.user, "Tree input not set");
      }
      if (this.root.refreshPromise) {
        yield this.root.refreshPromise;
        yield event.Event.toPromise(this._onDidRender.event);
      }
      const node = this.getDataNode(element);
      yield this.refreshAndRenderNode(node, recursive, viewStateContext, options);
      if (rerender) {
        try {
          this.tree.rerender(node);
        } catch (_a) {
        }
      }
    });
  }
  // View
  rerender(element) {
    if (element === void 0 || element === this.root.element) {
      this.tree.rerender();
      return;
    }
    const node = this.getDataNode(element);
    this.tree.rerender(node);
  }
  // Tree
  getNode(element = this.root.element) {
    const dataNode = this.getDataNode(element);
    const node = this.tree.getNode(dataNode === this.root ? null : dataNode);
    return this.nodeMapper.map(node);
  }
  collapse(element, recursive = false) {
    const node = this.getDataNode(element);
    return this.tree.collapse(node === this.root ? null : node, recursive);
  }
  expand(element, recursive = false) {
    return __awaiter(this, void 0, void 0, function* () {
      if (typeof this.root.element === "undefined") {
        throw new tree.TreeError(this.user, "Tree input not set");
      }
      if (this.root.refreshPromise) {
        yield this.root.refreshPromise;
        yield event.Event.toPromise(this._onDidRender.event);
      }
      const node = this.getDataNode(element);
      if (this.tree.hasElement(node) && !this.tree.isCollapsible(node)) {
        return false;
      }
      if (node.refreshPromise) {
        yield this.root.refreshPromise;
        yield event.Event.toPromise(this._onDidRender.event);
      }
      if (node !== this.root && !node.refreshPromise && !this.tree.isCollapsed(node)) {
        return false;
      }
      const result = this.tree.expand(node === this.root ? null : node, recursive);
      if (node.refreshPromise) {
        yield this.root.refreshPromise;
        yield event.Event.toPromise(this._onDidRender.event);
      }
      return result;
    });
  }
  setSelection(elements, browserEvent) {
    const nodes = elements.map((e) => this.getDataNode(e));
    this.tree.setSelection(nodes, browserEvent);
  }
  getSelection() {
    const nodes = this.tree.getSelection();
    return nodes.map((n) => n.element);
  }
  setFocus(elements, browserEvent) {
    const nodes = elements.map((e) => this.getDataNode(e));
    this.tree.setFocus(nodes, browserEvent);
  }
  getFocus() {
    const nodes = this.tree.getFocus();
    return nodes.map((n) => n.element);
  }
  reveal(element, relativeTop) {
    this.tree.reveal(this.getDataNode(element), relativeTop);
  }
  // Tree navigation
  getParentElement(element) {
    const node = this.tree.getParentElement(this.getDataNode(element));
    return node && node.element;
  }
  getFirstElementChild(element = this.root.element) {
    const dataNode = this.getDataNode(element);
    const node = this.tree.getFirstElementChild(dataNode === this.root ? null : dataNode);
    return node && node.element;
  }
  // Implementation
  getDataNode(element) {
    const node = this.nodes.get(element === this.root.element ? null : element);
    if (!node) {
      throw new tree.TreeError(this.user, `Data tree node not found: ${element}`);
    }
    return node;
  }
  refreshAndRenderNode(node, recursive, viewStateContext, options) {
    return __awaiter(this, void 0, void 0, function* () {
      yield this.refreshNode(node, recursive, viewStateContext);
      this.render(node, viewStateContext, options);
    });
  }
  refreshNode(node, recursive, viewStateContext) {
    return __awaiter(this, void 0, void 0, function* () {
      let result;
      this.subTreeRefreshPromises.forEach((refreshPromise, refreshNode) => {
        if (!result && intersects(refreshNode, node)) {
          result = refreshPromise.then(() => this.refreshNode(node, recursive, viewStateContext));
        }
      });
      if (result) {
        return result;
      }
      return this.doRefreshSubTree(node, recursive, viewStateContext);
    });
  }
  doRefreshSubTree(node, recursive, viewStateContext) {
    return __awaiter(this, void 0, void 0, function* () {
      let done;
      node.refreshPromise = new Promise((c) => done = c);
      this.subTreeRefreshPromises.set(node, node.refreshPromise);
      node.refreshPromise.finally(() => {
        node.refreshPromise = void 0;
        this.subTreeRefreshPromises.delete(node);
      });
      try {
        const childrenToRefresh = yield this.doRefreshNode(node, recursive, viewStateContext);
        node.stale = false;
        yield async.Promises.settled(childrenToRefresh.map((child) => this.doRefreshSubTree(child, recursive, viewStateContext)));
      } finally {
        done();
      }
    });
  }
  doRefreshNode(node, recursive, viewStateContext) {
    return __awaiter(this, void 0, void 0, function* () {
      node.hasChildren = !!this.dataSource.hasChildren(node.element);
      let childrenPromise;
      if (!node.hasChildren) {
        childrenPromise = Promise.resolve(iterator.Iterable.empty());
      } else {
        const children = this.doGetChildren(node);
        if (types.isIterable(children)) {
          childrenPromise = Promise.resolve(children);
        } else {
          const slowTimeout = async.timeout(800);
          slowTimeout.then(() => {
            node.slow = true;
            this._onDidChangeNodeSlowState.fire(node);
          }, (_) => null);
          childrenPromise = children.finally(() => slowTimeout.cancel());
        }
      }
      try {
        const children = yield childrenPromise;
        return this.setChildren(node, children, recursive, viewStateContext);
      } catch (err) {
        if (node !== this.root && this.tree.hasElement(node)) {
          this.tree.collapse(node);
        }
        if (errors.isCancellationError(err)) {
          return [];
        }
        throw err;
      } finally {
        if (node.slow) {
          node.slow = false;
          this._onDidChangeNodeSlowState.fire(node);
        }
      }
    });
  }
  doGetChildren(node) {
    let result = this.refreshPromises.get(node);
    if (result) {
      return result;
    }
    const children = this.dataSource.getChildren(node.element);
    if (types.isIterable(children)) {
      return this.processChildren(children);
    } else {
      result = async.createCancelablePromise(() => __awaiter(this, void 0, void 0, function* () {
        return this.processChildren(yield children);
      }));
      this.refreshPromises.set(node, result);
      return result.finally(() => {
        this.refreshPromises.delete(node);
      });
    }
  }
  _onDidChangeCollapseState({ node, deep }) {
    if (node.element === null) {
      return;
    }
    if (!node.collapsed && node.element.stale) {
      if (deep) {
        this.collapse(node.element.element);
      } else {
        this.refreshAndRenderNode(node.element, false).catch(errors.onUnexpectedError);
      }
    }
  }
  setChildren(node, childrenElementsIterable, recursive, viewStateContext) {
    const childrenElements = [...childrenElementsIterable];
    if (node.children.length === 0 && childrenElements.length === 0) {
      return [];
    }
    const nodesToForget = /* @__PURE__ */ new Map();
    const childrenTreeNodesById = /* @__PURE__ */ new Map();
    for (const child of node.children) {
      nodesToForget.set(child.element, child);
      if (this.identityProvider) {
        const collapsed = this.tree.isCollapsed(child);
        childrenTreeNodesById.set(child.id, { node: child, collapsed });
      }
    }
    const childrenToRefresh = [];
    const children = childrenElements.map((element) => {
      const hasChildren = !!this.dataSource.hasChildren(element);
      if (!this.identityProvider) {
        const asyncDataTreeNode = createAsyncDataTreeNode({ element, parent: node, hasChildren });
        if (hasChildren && this.collapseByDefault && !this.collapseByDefault(element)) {
          asyncDataTreeNode.collapsedByDefault = false;
          childrenToRefresh.push(asyncDataTreeNode);
        }
        return asyncDataTreeNode;
      }
      const id = this.identityProvider.getId(element).toString();
      const result = childrenTreeNodesById.get(id);
      if (result) {
        const asyncDataTreeNode = result.node;
        nodesToForget.delete(asyncDataTreeNode.element);
        this.nodes.delete(asyncDataTreeNode.element);
        this.nodes.set(element, asyncDataTreeNode);
        asyncDataTreeNode.element = element;
        asyncDataTreeNode.hasChildren = hasChildren;
        if (recursive) {
          if (result.collapsed) {
            asyncDataTreeNode.children.forEach((node2) => dfs(node2, (node3) => this.nodes.delete(node3.element)));
            asyncDataTreeNode.children.splice(0, asyncDataTreeNode.children.length);
            asyncDataTreeNode.stale = true;
          } else {
            childrenToRefresh.push(asyncDataTreeNode);
          }
        } else if (hasChildren && this.collapseByDefault && !this.collapseByDefault(element)) {
          asyncDataTreeNode.collapsedByDefault = false;
          childrenToRefresh.push(asyncDataTreeNode);
        }
        return asyncDataTreeNode;
      }
      const childAsyncDataTreeNode = createAsyncDataTreeNode({ element, parent: node, id, hasChildren });
      if (viewStateContext && viewStateContext.viewState.focus && viewStateContext.viewState.focus.indexOf(id) > -1) {
        viewStateContext.focus.push(childAsyncDataTreeNode);
      }
      if (viewStateContext && viewStateContext.viewState.selection && viewStateContext.viewState.selection.indexOf(id) > -1) {
        viewStateContext.selection.push(childAsyncDataTreeNode);
      }
      if (viewStateContext && viewStateContext.viewState.expanded && viewStateContext.viewState.expanded.indexOf(id) > -1) {
        childrenToRefresh.push(childAsyncDataTreeNode);
      } else if (hasChildren && this.collapseByDefault && !this.collapseByDefault(element)) {
        childAsyncDataTreeNode.collapsedByDefault = false;
        childrenToRefresh.push(childAsyncDataTreeNode);
      }
      return childAsyncDataTreeNode;
    });
    for (const node2 of nodesToForget.values()) {
      dfs(node2, (node3) => this.nodes.delete(node3.element));
    }
    for (const child of children) {
      this.nodes.set(child.element, child);
    }
    node.children.splice(0, node.children.length, ...children);
    if (node !== this.root && this.autoExpandSingleChildren && children.length === 1 && childrenToRefresh.length === 0) {
      children[0].collapsedByDefault = false;
      childrenToRefresh.push(children[0]);
    }
    return childrenToRefresh;
  }
  render(node, viewStateContext, options) {
    const children = node.children.map((node2) => this.asTreeElement(node2, viewStateContext));
    const objectTreeOptions = options && Object.assign(Object.assign({}, options), { diffIdentityProvider: options.diffIdentityProvider && {
      getId(node2) {
        return options.diffIdentityProvider.getId(node2.element);
      }
    } });
    this.tree.setChildren(node === this.root ? null : node, children, objectTreeOptions);
    if (node !== this.root) {
      this.tree.setCollapsible(node, node.hasChildren);
    }
    this._onDidRender.fire();
  }
  asTreeElement(node, viewStateContext) {
    if (node.stale) {
      return {
        element: node,
        collapsible: node.hasChildren,
        collapsed: true
      };
    }
    let collapsed;
    if (viewStateContext && viewStateContext.viewState.expanded && node.id && viewStateContext.viewState.expanded.indexOf(node.id) > -1) {
      collapsed = false;
    } else {
      collapsed = node.collapsedByDefault;
    }
    node.collapsedByDefault = void 0;
    return {
      element: node,
      children: node.hasChildren ? iterator.Iterable.map(node.children, (child) => this.asTreeElement(child, viewStateContext)) : [],
      collapsible: node.hasChildren,
      collapsed
    };
  }
  processChildren(children) {
    if (this.sorter) {
      children = [...children].sort(this.sorter.compare.bind(this.sorter));
    }
    return children;
  }
  dispose() {
    this.disposables.dispose();
  }
}
class CompressibleAsyncDataTreeNodeWrapper {
  constructor(node) {
    this.node = node;
  }
  get element() {
    return {
      elements: this.node.element.elements.map((e) => e.element),
      incompressible: this.node.element.incompressible
    };
  }
  get children() {
    return this.node.children.map((node) => new CompressibleAsyncDataTreeNodeWrapper(node));
  }
  get depth() {
    return this.node.depth;
  }
  get visibleChildrenCount() {
    return this.node.visibleChildrenCount;
  }
  get visibleChildIndex() {
    return this.node.visibleChildIndex;
  }
  get collapsible() {
    return this.node.collapsible;
  }
  get collapsed() {
    return this.node.collapsed;
  }
  get visible() {
    return this.node.visible;
  }
  get filterData() {
    return this.node.filterData;
  }
}
class CompressibleAsyncDataTreeRenderer {
  constructor(renderer, nodeMapper, compressibleNodeMapperProvider, onDidChangeTwistieState) {
    this.renderer = renderer;
    this.nodeMapper = nodeMapper;
    this.compressibleNodeMapperProvider = compressibleNodeMapperProvider;
    this.onDidChangeTwistieState = onDidChangeTwistieState;
    this.renderedNodes = /* @__PURE__ */ new Map();
    this.disposables = [];
    this.templateId = renderer.templateId;
  }
  renderTemplate(container) {
    const templateData = this.renderer.renderTemplate(container);
    return { templateData };
  }
  renderElement(node, index, templateData, height) {
    this.renderer.renderElement(this.nodeMapper.map(node), index, templateData.templateData, height);
  }
  renderCompressedElements(node, index, templateData, height) {
    this.renderer.renderCompressedElements(this.compressibleNodeMapperProvider().map(node), index, templateData.templateData, height);
  }
  renderTwistie(element, twistieElement) {
    if (element.slow) {
      twistieElement.classList.add(...codicons.Codicon.treeItemLoading.classNamesArray);
      return true;
    } else {
      twistieElement.classList.remove(...codicons.Codicon.treeItemLoading.classNamesArray);
      return false;
    }
  }
  disposeElement(node, index, templateData, height) {
    if (this.renderer.disposeElement) {
      this.renderer.disposeElement(this.nodeMapper.map(node), index, templateData.templateData, height);
    }
  }
  disposeCompressedElements(node, index, templateData, height) {
    if (this.renderer.disposeCompressedElements) {
      this.renderer.disposeCompressedElements(this.compressibleNodeMapperProvider().map(node), index, templateData.templateData, height);
    }
  }
  disposeTemplate(templateData) {
    this.renderer.disposeTemplate(templateData.templateData);
  }
  dispose() {
    this.renderedNodes.clear();
    this.disposables = lifecycle.dispose(this.disposables);
  }
}
function asCompressibleObjectTreeOptions(options) {
  const objectTreeOptions = options && asObjectTreeOptions(options);
  return objectTreeOptions && Object.assign(Object.assign({}, objectTreeOptions), { keyboardNavigationLabelProvider: objectTreeOptions.keyboardNavigationLabelProvider && Object.assign(Object.assign({}, objectTreeOptions.keyboardNavigationLabelProvider), { getCompressedNodeKeyboardNavigationLabel(els) {
    return options.keyboardNavigationLabelProvider.getCompressedNodeKeyboardNavigationLabel(els.map((e) => e.element));
  } }) });
}
class CompressibleAsyncDataTree extends AsyncDataTree {
  constructor(user, container, virtualDelegate, compressionDelegate, renderers, dataSource, options = {}) {
    super(user, container, virtualDelegate, renderers, dataSource, options);
    this.compressionDelegate = compressionDelegate;
    this.compressibleNodeMapper = new tree.WeakMapper((node) => new CompressibleAsyncDataTreeNodeWrapper(node));
    this.filter = options.filter;
  }
  createTree(user, container, delegate, renderers, options) {
    const objectTreeDelegate = new abstractTree.ComposedTreeDelegate(delegate);
    const objectTreeRenderers = renderers.map((r) => new CompressibleAsyncDataTreeRenderer(r, this.nodeMapper, () => this.compressibleNodeMapper, this._onDidChangeNodeSlowState.event));
    const objectTreeOptions = asCompressibleObjectTreeOptions(options) || {};
    return new objectTree.CompressibleObjectTree(user, container, objectTreeDelegate, objectTreeRenderers, objectTreeOptions);
  }
  asTreeElement(node, viewStateContext) {
    return Object.assign({ incompressible: this.compressionDelegate.isIncompressible(node.element) }, super.asTreeElement(node, viewStateContext));
  }
  updateOptions(options = {}) {
    this.tree.updateOptions(options);
  }
  render(node, viewStateContext) {
    if (!this.identityProvider) {
      return super.render(node, viewStateContext);
    }
    const getId = (element) => this.identityProvider.getId(element).toString();
    const getUncompressedIds = (nodes) => {
      const result = /* @__PURE__ */ new Set();
      for (const node2 of nodes) {
        const compressedNode = this.tree.getCompressedTreeNode(node2 === this.root ? null : node2);
        if (!compressedNode.element) {
          continue;
        }
        for (const node3 of compressedNode.element.elements) {
          result.add(getId(node3.element));
        }
      }
      return result;
    };
    const oldSelection = getUncompressedIds(this.tree.getSelection());
    const oldFocus = getUncompressedIds(this.tree.getFocus());
    super.render(node, viewStateContext);
    const selection = this.getSelection();
    let didChangeSelection = false;
    const focus = this.getFocus();
    let didChangeFocus = false;
    const visit = (node2) => {
      const compressedNode = node2.element;
      if (compressedNode) {
        for (let i = 0; i < compressedNode.elements.length; i++) {
          const id = getId(compressedNode.elements[i].element);
          const element = compressedNode.elements[compressedNode.elements.length - 1].element;
          if (oldSelection.has(id) && selection.indexOf(element) === -1) {
            selection.push(element);
            didChangeSelection = true;
          }
          if (oldFocus.has(id) && focus.indexOf(element) === -1) {
            focus.push(element);
            didChangeFocus = true;
          }
        }
      }
      node2.children.forEach(visit);
    };
    visit(this.tree.getCompressedTreeNode(node === this.root ? null : node));
    if (didChangeSelection) {
      this.setSelection(selection);
    }
    if (didChangeFocus) {
      this.setFocus(focus);
    }
  }
  // For compressed async data trees, `TreeVisibility.Recurse` doesn't currently work
  // and we have to filter everything beforehand
  // Related to #85193 and #85835
  processChildren(children) {
    if (this.filter) {
      children = iterator.Iterable.filter(children, (e) => {
        const result = this.filter.filter(
          e,
          1
          /* Visible */
        );
        const visibility = getVisibility(result);
        if (visibility === 2) {
          throw new Error("Recursive tree visibility not supported in async data compressed trees");
        }
        return visibility === 1;
      });
    }
    return super.processChildren(children);
  }
}
function getVisibility(filterResult) {
  if (typeof filterResult === "boolean") {
    return filterResult ? 1 : 0;
  } else if (indexTreeModel.isFilterResult(filterResult)) {
    return indexTreeModel.getVisibleState(filterResult.visibility);
  } else {
    return indexTreeModel.getVisibleState(filterResult);
  }
}
exports.AsyncDataTree = AsyncDataTree;
exports.CompressibleAsyncDataTree = CompressibleAsyncDataTree;
