"use strict";
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const dom = require("../../dom.js");
const sash = require("../sash/sash.js");
const scrollableElement = require("../scrollbar/scrollableElement.js");
const arrays = require("../../../common/arrays.js");
const color = require("../../../common/color.js");
const event = require("../../../common/event.js");
const lifecycle = require("../../../common/lifecycle.js");
const numbers = require("../../../common/numbers.js");
const scrollable = require("../../../common/scrollable.js");
const types = require("../../../common/types.js");
require("./splitview.css.js");
const defaultStyles = {
  separatorBorder: color.Color.transparent
};
class ViewItem {
  constructor(container, view, size, disposable) {
    this.container = container;
    this.view = view;
    this.disposable = disposable;
    this._cachedVisibleSize = void 0;
    if (typeof size === "number") {
      this._size = size;
      this._cachedVisibleSize = void 0;
      container.classList.add("visible");
    } else {
      this._size = 0;
      this._cachedVisibleSize = size.cachedVisibleSize;
    }
  }
  set size(size) {
    this._size = size;
  }
  get size() {
    return this._size;
  }
  get visible() {
    return typeof this._cachedVisibleSize === "undefined";
  }
  setVisible(visible, size) {
    if (visible === this.visible) {
      return;
    }
    if (visible) {
      this.size = numbers.clamp(this._cachedVisibleSize, this.viewMinimumSize, this.viewMaximumSize);
      this._cachedVisibleSize = void 0;
    } else {
      this._cachedVisibleSize = typeof size === "number" ? size : this.size;
      this.size = 0;
    }
    this.container.classList.toggle("visible", visible);
    if (this.view.setVisible) {
      this.view.setVisible(visible);
    }
  }
  get minimumSize() {
    return this.visible ? this.view.minimumSize : 0;
  }
  get viewMinimumSize() {
    return this.view.minimumSize;
  }
  get maximumSize() {
    return this.visible ? this.view.maximumSize : 0;
  }
  get viewMaximumSize() {
    return this.view.maximumSize;
  }
  get priority() {
    return this.view.priority;
  }
  get snap() {
    return !!this.view.snap;
  }
  set enabled(enabled) {
    this.container.style.pointerEvents = enabled ? "" : "none";
  }
  layout(offset, layoutContext) {
    this.layoutContainer(offset);
    this.view.layout(this.size, offset, layoutContext);
  }
  dispose() {
    this.disposable.dispose();
    return this.view;
  }
}
class VerticalViewItem extends ViewItem {
  layoutContainer(offset) {
    this.container.style.top = `${offset}px`;
    this.container.style.height = `${this.size}px`;
  }
}
class HorizontalViewItem extends ViewItem {
  layoutContainer(offset) {
    this.container.style.left = `${offset}px`;
    this.container.style.width = `${this.size}px`;
  }
}
var State;
(function(State2) {
  State2[State2["Idle"] = 0] = "Idle";
  State2[State2["Busy"] = 1] = "Busy";
})(State || (State = {}));
exports.Sizing = void 0;
(function(Sizing) {
  Sizing.Distribute = { type: "distribute" };
  function Split(index) {
    return { type: "split", index };
  }
  Sizing.Split = Split;
  function Invisible(cachedVisibleSize) {
    return { type: "invisible", cachedVisibleSize };
  }
  Sizing.Invisible = Invisible;
})(exports.Sizing || (exports.Sizing = {}));
class SplitView extends lifecycle.Disposable {
  /**
   * Create a new {@link SplitView} instance.
   */
  constructor(container, options = {}) {
    var _a, _b, _c, _d, _e;
    super();
    this.size = 0;
    this.contentSize = 0;
    this.proportions = void 0;
    this.viewItems = [];
    this.sashItems = [];
    this.state = State.Idle;
    this._onDidSashChange = this._register(new event.Emitter());
    this._onDidSashReset = this._register(new event.Emitter());
    this._startSnappingEnabled = true;
    this._endSnappingEnabled = true;
    this.onDidSashChange = this._onDidSashChange.event;
    this.onDidSashReset = this._onDidSashReset.event;
    this.orientation = (_a = options.orientation) !== null && _a !== void 0 ? _a : 0;
    this.inverseAltBehavior = (_b = options.inverseAltBehavior) !== null && _b !== void 0 ? _b : false;
    this.proportionalLayout = (_c = options.proportionalLayout) !== null && _c !== void 0 ? _c : true;
    this.getSashOrthogonalSize = options.getSashOrthogonalSize;
    this.el = document.createElement("div");
    this.el.classList.add("monaco-split-view2");
    this.el.classList.add(this.orientation === 0 ? "vertical" : "horizontal");
    container.appendChild(this.el);
    this.sashContainer = dom.append(this.el, dom.$(".sash-container"));
    this.viewContainer = dom.$(".split-view-container");
    this.scrollable = new scrollable.Scrollable({
      forceIntegerValues: true,
      smoothScrollDuration: 125,
      scheduleAtNextAnimationFrame: dom.scheduleAtNextAnimationFrame
    });
    this.scrollableElement = this._register(new scrollableElement.SmoothScrollableElement(this.viewContainer, {
      vertical: this.orientation === 0 ? (_d = options.scrollbarVisibility) !== null && _d !== void 0 ? _d : 1 : 2,
      horizontal: this.orientation === 1 ? (_e = options.scrollbarVisibility) !== null && _e !== void 0 ? _e : 1 : 2
      /* Hidden */
    }, this.scrollable));
    this.onDidScroll = this.scrollableElement.onScroll;
    this._register(this.onDidScroll((e) => {
      this.viewContainer.scrollTop = e.scrollTop;
      this.viewContainer.scrollLeft = e.scrollLeft;
    }));
    dom.append(this.el, this.scrollableElement.getDomNode());
    this.style(options.styles || defaultStyles);
    if (options.descriptor) {
      this.size = options.descriptor.size;
      options.descriptor.views.forEach((viewDescriptor, index) => {
        const sizing = types.isUndefined(viewDescriptor.visible) || viewDescriptor.visible ? viewDescriptor.size : { type: "invisible", cachedVisibleSize: viewDescriptor.size };
        const view = viewDescriptor.view;
        this.doAddView(view, sizing, index, true);
      });
      this.contentSize = this.viewItems.reduce((r, i) => r + i.size, 0);
      this.saveProportions();
    }
  }
  get orthogonalStartSash() {
    return this._orthogonalStartSash;
  }
  get orthogonalEndSash() {
    return this._orthogonalEndSash;
  }
  get startSnappingEnabled() {
    return this._startSnappingEnabled;
  }
  get endSnappingEnabled() {
    return this._endSnappingEnabled;
  }
  /**
   * A reference to a sash, perpendicular to all sashes in this {@link SplitView},
   * located at the left- or top-most side of the SplitView.
   * Corner sashes will be created automatically at the intersections.
   */
  set orthogonalStartSash(sash2) {
    for (const sashItem of this.sashItems) {
      sashItem.sash.orthogonalStartSash = sash2;
    }
    this._orthogonalStartSash = sash2;
  }
  /**
   * A reference to a sash, perpendicular to all sashes in this {@link SplitView},
   * located at the right- or bottom-most side of the SplitView.
   * Corner sashes will be created automatically at the intersections.
   */
  set orthogonalEndSash(sash2) {
    for (const sashItem of this.sashItems) {
      sashItem.sash.orthogonalEndSash = sash2;
    }
    this._orthogonalEndSash = sash2;
  }
  /**
   * Enable/disable snapping at the beginning of this {@link SplitView}.
   */
  set startSnappingEnabled(startSnappingEnabled) {
    if (this._startSnappingEnabled === startSnappingEnabled) {
      return;
    }
    this._startSnappingEnabled = startSnappingEnabled;
    this.updateSashEnablement();
  }
  /**
   * Enable/disable snapping at the end of this {@link SplitView}.
   */
  set endSnappingEnabled(endSnappingEnabled) {
    if (this._endSnappingEnabled === endSnappingEnabled) {
      return;
    }
    this._endSnappingEnabled = endSnappingEnabled;
    this.updateSashEnablement();
  }
  style(styles) {
    if (styles.separatorBorder.isTransparent()) {
      this.el.classList.remove("separator-border");
      this.el.style.removeProperty("--separator-border");
    } else {
      this.el.classList.add("separator-border");
      this.el.style.setProperty("--separator-border", styles.separatorBorder.toString());
    }
  }
  /**
   * Add a {@link IView view} to this {@link SplitView}.
   *
   * @param view The view to add.
   * @param size Either a fixed size, or a dynamic {@link Sizing} strategy.
   * @param index The index to insert the view on.
   * @param skipLayout Whether layout should be skipped.
   */
  addView(view, size, index = this.viewItems.length, skipLayout) {
    this.doAddView(view, size, index, skipLayout);
  }
  /**
   * Layout the {@link SplitView}.
   *
   * @param size The entire size of the {@link SplitView}.
   * @param layoutContext An optional layout context to pass along to {@link IView views}.
   */
  layout(size, layoutContext) {
    const previousSize = Math.max(this.size, this.contentSize);
    this.size = size;
    this.layoutContext = layoutContext;
    if (!this.proportions) {
      const indexes = arrays.range(this.viewItems.length);
      const lowPriorityIndexes = indexes.filter(
        (i) => this.viewItems[i].priority === 1
        /* Low */
      );
      const highPriorityIndexes = indexes.filter(
        (i) => this.viewItems[i].priority === 2
        /* High */
      );
      this.resize(this.viewItems.length - 1, size - previousSize, void 0, lowPriorityIndexes, highPriorityIndexes);
    } else {
      for (let i = 0; i < this.viewItems.length; i++) {
        const item = this.viewItems[i];
        item.size = numbers.clamp(Math.round(this.proportions[i] * size), item.minimumSize, item.maximumSize);
      }
    }
    this.distributeEmptySpace();
    this.layoutViews();
  }
  saveProportions() {
    if (this.proportionalLayout && this.contentSize > 0) {
      this.proportions = this.viewItems.map((i) => i.size / this.contentSize);
    }
  }
  onSashStart({ sash: sash2, start, alt }) {
    for (const item of this.viewItems) {
      item.enabled = false;
    }
    const index = this.sashItems.findIndex((item) => item.sash === sash2);
    const disposable = lifecycle.combinedDisposable(dom.addDisposableListener(document.body, "keydown", (e) => resetSashDragState(this.sashDragState.current, e.altKey)), dom.addDisposableListener(document.body, "keyup", () => resetSashDragState(this.sashDragState.current, false)));
    const resetSashDragState = (start2, alt2) => {
      const sizes = this.viewItems.map((i) => i.size);
      let minDelta = Number.NEGATIVE_INFINITY;
      let maxDelta = Number.POSITIVE_INFINITY;
      if (this.inverseAltBehavior) {
        alt2 = !alt2;
      }
      if (alt2) {
        const isLastSash = index === this.sashItems.length - 1;
        if (isLastSash) {
          const viewItem = this.viewItems[index];
          minDelta = (viewItem.minimumSize - viewItem.size) / 2;
          maxDelta = (viewItem.maximumSize - viewItem.size) / 2;
        } else {
          const viewItem = this.viewItems[index + 1];
          minDelta = (viewItem.size - viewItem.maximumSize) / 2;
          maxDelta = (viewItem.size - viewItem.minimumSize) / 2;
        }
      }
      let snapBefore;
      let snapAfter;
      if (!alt2) {
        const upIndexes = arrays.range(index, -1);
        const downIndexes = arrays.range(index + 1, this.viewItems.length);
        const minDeltaUp = upIndexes.reduce((r, i) => r + (this.viewItems[i].minimumSize - sizes[i]), 0);
        const maxDeltaUp = upIndexes.reduce((r, i) => r + (this.viewItems[i].viewMaximumSize - sizes[i]), 0);
        const maxDeltaDown = downIndexes.length === 0 ? Number.POSITIVE_INFINITY : downIndexes.reduce((r, i) => r + (sizes[i] - this.viewItems[i].minimumSize), 0);
        const minDeltaDown = downIndexes.length === 0 ? Number.NEGATIVE_INFINITY : downIndexes.reduce((r, i) => r + (sizes[i] - this.viewItems[i].viewMaximumSize), 0);
        const minDelta2 = Math.max(minDeltaUp, minDeltaDown);
        const maxDelta2 = Math.min(maxDeltaDown, maxDeltaUp);
        const snapBeforeIndex = this.findFirstSnapIndex(upIndexes);
        const snapAfterIndex = this.findFirstSnapIndex(downIndexes);
        if (typeof snapBeforeIndex === "number") {
          const viewItem = this.viewItems[snapBeforeIndex];
          const halfSize = Math.floor(viewItem.viewMinimumSize / 2);
          snapBefore = {
            index: snapBeforeIndex,
            limitDelta: viewItem.visible ? minDelta2 - halfSize : minDelta2 + halfSize,
            size: viewItem.size
          };
        }
        if (typeof snapAfterIndex === "number") {
          const viewItem = this.viewItems[snapAfterIndex];
          const halfSize = Math.floor(viewItem.viewMinimumSize / 2);
          snapAfter = {
            index: snapAfterIndex,
            limitDelta: viewItem.visible ? maxDelta2 + halfSize : maxDelta2 - halfSize,
            size: viewItem.size
          };
        }
      }
      this.sashDragState = { start: start2, current: start2, index, sizes, minDelta, maxDelta, alt: alt2, snapBefore, snapAfter, disposable };
    };
    resetSashDragState(start, alt);
  }
  onSashChange({ current }) {
    const { index, start, sizes, alt, minDelta, maxDelta, snapBefore, snapAfter } = this.sashDragState;
    this.sashDragState.current = current;
    const delta = current - start;
    const newDelta = this.resize(index, delta, sizes, void 0, void 0, minDelta, maxDelta, snapBefore, snapAfter);
    if (alt) {
      const isLastSash = index === this.sashItems.length - 1;
      const newSizes = this.viewItems.map((i) => i.size);
      const viewItemIndex = isLastSash ? index : index + 1;
      const viewItem = this.viewItems[viewItemIndex];
      const newMinDelta = viewItem.size - viewItem.maximumSize;
      const newMaxDelta = viewItem.size - viewItem.minimumSize;
      const resizeIndex = isLastSash ? index - 1 : index + 1;
      this.resize(resizeIndex, -newDelta, newSizes, void 0, void 0, newMinDelta, newMaxDelta);
    }
    this.distributeEmptySpace();
    this.layoutViews();
  }
  onSashEnd(index) {
    this._onDidSashChange.fire(index);
    this.sashDragState.disposable.dispose();
    this.saveProportions();
    for (const item of this.viewItems) {
      item.enabled = true;
    }
  }
  onViewChange(item, size) {
    const index = this.viewItems.indexOf(item);
    if (index < 0 || index >= this.viewItems.length) {
      return;
    }
    size = typeof size === "number" ? size : item.size;
    size = numbers.clamp(size, item.minimumSize, item.maximumSize);
    if (this.inverseAltBehavior && index > 0) {
      this.resize(index - 1, Math.floor((item.size - size) / 2));
      this.distributeEmptySpace();
      this.layoutViews();
    } else {
      item.size = size;
      this.relayout([index], void 0);
    }
  }
  /**
   * Resize a {@link IView view} within the {@link SplitView}.
   *
   * @param index The {@link IView view} index.
   * @param size The {@link IView view} size.
   */
  resizeView(index, size) {
    if (this.state !== State.Idle) {
      throw new Error("Cant modify splitview");
    }
    this.state = State.Busy;
    if (index < 0 || index >= this.viewItems.length) {
      return;
    }
    const indexes = arrays.range(this.viewItems.length).filter((i) => i !== index);
    const lowPriorityIndexes = [...indexes.filter(
      (i) => this.viewItems[i].priority === 1
      /* Low */
    ), index];
    const highPriorityIndexes = indexes.filter(
      (i) => this.viewItems[i].priority === 2
      /* High */
    );
    const item = this.viewItems[index];
    size = Math.round(size);
    size = numbers.clamp(size, item.minimumSize, Math.min(item.maximumSize, this.size));
    item.size = size;
    this.relayout(lowPriorityIndexes, highPriorityIndexes);
    this.state = State.Idle;
  }
  /**
   * Distribute the entire {@link SplitView} size among all {@link IView views}.
   */
  distributeViewSizes() {
    const flexibleViewItems = [];
    let flexibleSize = 0;
    for (const item of this.viewItems) {
      if (item.maximumSize - item.minimumSize > 0) {
        flexibleViewItems.push(item);
        flexibleSize += item.size;
      }
    }
    const size = Math.floor(flexibleSize / flexibleViewItems.length);
    for (const item of flexibleViewItems) {
      item.size = numbers.clamp(size, item.minimumSize, item.maximumSize);
    }
    const indexes = arrays.range(this.viewItems.length);
    const lowPriorityIndexes = indexes.filter(
      (i) => this.viewItems[i].priority === 1
      /* Low */
    );
    const highPriorityIndexes = indexes.filter(
      (i) => this.viewItems[i].priority === 2
      /* High */
    );
    this.relayout(lowPriorityIndexes, highPriorityIndexes);
  }
  /**
   * Returns the size of a {@link IView view}.
   */
  getViewSize(index) {
    if (index < 0 || index >= this.viewItems.length) {
      return -1;
    }
    return this.viewItems[index].size;
  }
  doAddView(view, size, index = this.viewItems.length, skipLayout) {
    if (this.state !== State.Idle) {
      throw new Error("Cant modify splitview");
    }
    this.state = State.Busy;
    const container = dom.$(".split-view-view");
    if (index === this.viewItems.length) {
      this.viewContainer.appendChild(container);
    } else {
      this.viewContainer.insertBefore(container, this.viewContainer.children.item(index));
    }
    const onChangeDisposable = view.onDidChange((size2) => this.onViewChange(item, size2));
    const containerDisposable = lifecycle.toDisposable(() => this.viewContainer.removeChild(container));
    const disposable = lifecycle.combinedDisposable(onChangeDisposable, containerDisposable);
    let viewSize;
    if (typeof size === "number") {
      viewSize = size;
    } else if (size.type === "split") {
      viewSize = this.getViewSize(size.index) / 2;
    } else if (size.type === "invisible") {
      viewSize = { cachedVisibleSize: size.cachedVisibleSize };
    } else {
      viewSize = view.minimumSize;
    }
    const item = this.orientation === 0 ? new VerticalViewItem(container, view, viewSize, disposable) : new HorizontalViewItem(container, view, viewSize, disposable);
    this.viewItems.splice(index, 0, item);
    if (this.viewItems.length > 1) {
      let opts = { orthogonalStartSash: this.orthogonalStartSash, orthogonalEndSash: this.orthogonalEndSash };
      const sash$1 = this.orientation === 0 ? new sash.Sash(this.sashContainer, { getHorizontalSashTop: (s) => this.getSashPosition(s), getHorizontalSashWidth: this.getSashOrthogonalSize }, Object.assign(Object.assign({}, opts), {
        orientation: 1
        /* HORIZONTAL */
      })) : new sash.Sash(this.sashContainer, { getVerticalSashLeft: (s) => this.getSashPosition(s), getVerticalSashHeight: this.getSashOrthogonalSize }, Object.assign(Object.assign({}, opts), {
        orientation: 0
        /* VERTICAL */
      }));
      const sashEventMapper = this.orientation === 0 ? (e) => ({ sash: sash$1, start: e.startY, current: e.currentY, alt: e.altKey }) : (e) => ({ sash: sash$1, start: e.startX, current: e.currentX, alt: e.altKey });
      const onStart = event.Event.map(sash$1.onDidStart, sashEventMapper);
      const onStartDisposable = onStart(this.onSashStart, this);
      const onChange = event.Event.map(sash$1.onDidChange, sashEventMapper);
      const onChangeDisposable2 = onChange(this.onSashChange, this);
      const onEnd = event.Event.map(sash$1.onDidEnd, () => this.sashItems.findIndex((item2) => item2.sash === sash$1));
      const onEndDisposable = onEnd(this.onSashEnd, this);
      const onDidResetDisposable = sash$1.onDidReset(() => {
        const index2 = this.sashItems.findIndex((item2) => item2.sash === sash$1);
        const upIndexes = arrays.range(index2, -1);
        const downIndexes = arrays.range(index2 + 1, this.viewItems.length);
        const snapBeforeIndex = this.findFirstSnapIndex(upIndexes);
        const snapAfterIndex = this.findFirstSnapIndex(downIndexes);
        if (typeof snapBeforeIndex === "number" && !this.viewItems[snapBeforeIndex].visible) {
          return;
        }
        if (typeof snapAfterIndex === "number" && !this.viewItems[snapAfterIndex].visible) {
          return;
        }
        this._onDidSashReset.fire(index2);
      });
      const disposable2 = lifecycle.combinedDisposable(onStartDisposable, onChangeDisposable2, onEndDisposable, onDidResetDisposable, sash$1);
      const sashItem = { sash: sash$1, disposable: disposable2 };
      this.sashItems.splice(index - 1, 0, sashItem);
    }
    container.appendChild(view.element);
    let highPriorityIndexes;
    if (typeof size !== "number" && size.type === "split") {
      highPriorityIndexes = [size.index];
    }
    if (!skipLayout) {
      this.relayout([index], highPriorityIndexes);
    }
    this.state = State.Idle;
    if (!skipLayout && typeof size !== "number" && size.type === "distribute") {
      this.distributeViewSizes();
    }
  }
  relayout(lowPriorityIndexes, highPriorityIndexes) {
    const contentSize = this.viewItems.reduce((r, i) => r + i.size, 0);
    this.resize(this.viewItems.length - 1, this.size - contentSize, void 0, lowPriorityIndexes, highPriorityIndexes);
    this.distributeEmptySpace();
    this.layoutViews();
    this.saveProportions();
  }
  resize(index, delta, sizes = this.viewItems.map((i) => i.size), lowPriorityIndexes, highPriorityIndexes, overloadMinDelta = Number.NEGATIVE_INFINITY, overloadMaxDelta = Number.POSITIVE_INFINITY, snapBefore, snapAfter) {
    if (index < 0 || index >= this.viewItems.length) {
      return 0;
    }
    const upIndexes = arrays.range(index, -1);
    const downIndexes = arrays.range(index + 1, this.viewItems.length);
    if (highPriorityIndexes) {
      for (const index2 of highPriorityIndexes) {
        arrays.pushToStart(upIndexes, index2);
        arrays.pushToStart(downIndexes, index2);
      }
    }
    if (lowPriorityIndexes) {
      for (const index2 of lowPriorityIndexes) {
        arrays.pushToEnd(upIndexes, index2);
        arrays.pushToEnd(downIndexes, index2);
      }
    }
    const upItems = upIndexes.map((i) => this.viewItems[i]);
    const upSizes = upIndexes.map((i) => sizes[i]);
    const downItems = downIndexes.map((i) => this.viewItems[i]);
    const downSizes = downIndexes.map((i) => sizes[i]);
    const minDeltaUp = upIndexes.reduce((r, i) => r + (this.viewItems[i].minimumSize - sizes[i]), 0);
    const maxDeltaUp = upIndexes.reduce((r, i) => r + (this.viewItems[i].maximumSize - sizes[i]), 0);
    const maxDeltaDown = downIndexes.length === 0 ? Number.POSITIVE_INFINITY : downIndexes.reduce((r, i) => r + (sizes[i] - this.viewItems[i].minimumSize), 0);
    const minDeltaDown = downIndexes.length === 0 ? Number.NEGATIVE_INFINITY : downIndexes.reduce((r, i) => r + (sizes[i] - this.viewItems[i].maximumSize), 0);
    const minDelta = Math.max(minDeltaUp, minDeltaDown, overloadMinDelta);
    const maxDelta = Math.min(maxDeltaDown, maxDeltaUp, overloadMaxDelta);
    let snapped = false;
    if (snapBefore) {
      const snapView = this.viewItems[snapBefore.index];
      const visible = delta >= snapBefore.limitDelta;
      snapped = visible !== snapView.visible;
      snapView.setVisible(visible, snapBefore.size);
    }
    if (!snapped && snapAfter) {
      const snapView = this.viewItems[snapAfter.index];
      const visible = delta < snapAfter.limitDelta;
      snapped = visible !== snapView.visible;
      snapView.setVisible(visible, snapAfter.size);
    }
    if (snapped) {
      return this.resize(index, delta, sizes, lowPriorityIndexes, highPriorityIndexes, overloadMinDelta, overloadMaxDelta);
    }
    delta = numbers.clamp(delta, minDelta, maxDelta);
    for (let i = 0, deltaUp = delta; i < upItems.length; i++) {
      const item = upItems[i];
      const size = numbers.clamp(upSizes[i] + deltaUp, item.minimumSize, item.maximumSize);
      const viewDelta = size - upSizes[i];
      deltaUp -= viewDelta;
      item.size = size;
    }
    for (let i = 0, deltaDown = delta; i < downItems.length; i++) {
      const item = downItems[i];
      const size = numbers.clamp(downSizes[i] - deltaDown, item.minimumSize, item.maximumSize);
      const viewDelta = size - downSizes[i];
      deltaDown += viewDelta;
      item.size = size;
    }
    return delta;
  }
  distributeEmptySpace(lowPriorityIndex) {
    const contentSize = this.viewItems.reduce((r, i) => r + i.size, 0);
    let emptyDelta = this.size - contentSize;
    const indexes = arrays.range(this.viewItems.length - 1, -1);
    const lowPriorityIndexes = indexes.filter(
      (i) => this.viewItems[i].priority === 1
      /* Low */
    );
    const highPriorityIndexes = indexes.filter(
      (i) => this.viewItems[i].priority === 2
      /* High */
    );
    for (const index of highPriorityIndexes) {
      arrays.pushToStart(indexes, index);
    }
    for (const index of lowPriorityIndexes) {
      arrays.pushToEnd(indexes, index);
    }
    if (typeof lowPriorityIndex === "number") {
      arrays.pushToEnd(indexes, lowPriorityIndex);
    }
    for (let i = 0; emptyDelta !== 0 && i < indexes.length; i++) {
      const item = this.viewItems[indexes[i]];
      const size = numbers.clamp(item.size + emptyDelta, item.minimumSize, item.maximumSize);
      const viewDelta = size - item.size;
      emptyDelta -= viewDelta;
      item.size = size;
    }
  }
  layoutViews() {
    this.contentSize = this.viewItems.reduce((r, i) => r + i.size, 0);
    let offset = 0;
    for (const viewItem of this.viewItems) {
      viewItem.layout(offset, this.layoutContext);
      offset += viewItem.size;
    }
    this.sashItems.forEach((item) => item.sash.layout());
    this.updateSashEnablement();
    this.updateScrollableElement();
  }
  updateScrollableElement() {
    if (this.orientation === 0) {
      this.scrollableElement.setScrollDimensions({
        height: this.size,
        scrollHeight: this.contentSize
      });
    } else {
      this.scrollableElement.setScrollDimensions({
        width: this.size,
        scrollWidth: this.contentSize
      });
    }
  }
  updateSashEnablement() {
    let previous = false;
    const collapsesDown = this.viewItems.map((i) => previous = i.size - i.minimumSize > 0 || previous);
    previous = false;
    const expandsDown = this.viewItems.map((i) => previous = i.maximumSize - i.size > 0 || previous);
    const reverseViews = [...this.viewItems].reverse();
    previous = false;
    const collapsesUp = reverseViews.map((i) => previous = i.size - i.minimumSize > 0 || previous).reverse();
    previous = false;
    const expandsUp = reverseViews.map((i) => previous = i.maximumSize - i.size > 0 || previous).reverse();
    let position = 0;
    for (let index = 0; index < this.sashItems.length; index++) {
      const { sash: sash2 } = this.sashItems[index];
      const viewItem = this.viewItems[index];
      position += viewItem.size;
      const min = !(collapsesDown[index] && expandsUp[index + 1]);
      const max = !(expandsDown[index] && collapsesUp[index + 1]);
      if (min && max) {
        const upIndexes = arrays.range(index, -1);
        const downIndexes = arrays.range(index + 1, this.viewItems.length);
        const snapBeforeIndex = this.findFirstSnapIndex(upIndexes);
        const snapAfterIndex = this.findFirstSnapIndex(downIndexes);
        const snappedBefore = typeof snapBeforeIndex === "number" && !this.viewItems[snapBeforeIndex].visible;
        const snappedAfter = typeof snapAfterIndex === "number" && !this.viewItems[snapAfterIndex].visible;
        if (snappedBefore && collapsesUp[index] && (position > 0 || this.startSnappingEnabled)) {
          sash2.state = 1;
        } else if (snappedAfter && collapsesDown[index] && (position < this.contentSize || this.endSnappingEnabled)) {
          sash2.state = 2;
        } else {
          sash2.state = 0;
        }
      } else if (min && !max) {
        sash2.state = 1;
      } else if (!min && max) {
        sash2.state = 2;
      } else {
        sash2.state = 3;
      }
    }
  }
  getSashPosition(sash2) {
    let position = 0;
    for (let i = 0; i < this.sashItems.length; i++) {
      position += this.viewItems[i].size;
      if (this.sashItems[i].sash === sash2) {
        return position;
      }
    }
    return 0;
  }
  findFirstSnapIndex(indexes) {
    for (const index of indexes) {
      const viewItem = this.viewItems[index];
      if (!viewItem.visible) {
        continue;
      }
      if (viewItem.snap) {
        return index;
      }
    }
    for (const index of indexes) {
      const viewItem = this.viewItems[index];
      if (viewItem.visible && viewItem.maximumSize - viewItem.minimumSize > 0) {
        return void 0;
      }
      if (!viewItem.visible && viewItem.snap) {
        return index;
      }
    }
    return void 0;
  }
  dispose() {
    super.dispose();
    lifecycle.dispose(this.viewItems);
    this.viewItems = [];
    this.sashItems.forEach((i) => i.disposable.dispose());
    this.sashItems = [];
  }
}
exports.SplitView = SplitView;
