// src/js-tools/three-utils/subset.ts
import {
  BufferGeometry,
  Uint32BufferAttribute
} from "three";
function createSubsetFeatureMap(data) {
  const map = {};
  let offset = 0;
  let indexOffset = 0;
  for (const { id, vertCount, indices } of data) {
    let shiftedIndices = map[id];
    if (!shiftedIndices) {
      shiftedIndices = [];
      map[id] = shiftedIndices;
    }
    const shifted = new Uint32Array(indices.length);
    for (let i = 0; i < indices.length; ++i) {
      shifted[i] = indices[i] + offset;
    }
    shiftedIndices.push({
      indexStart: indexOffset,
      indices: shifted
    });
    offset += vertCount;
    indexOffset += indices.length;
  }
  return map;
}
var SubsetGeometry = class _SubsetGeometry extends BufferGeometry {
  constructor(attributes, featureInfos) {
    super();
    this._ids = /* @__PURE__ */ new Set();
    const indexCount = featureInfos.reduce(
      (sum, info) => sum + info.indices.length,
      0
    );
    for (const [name, attr] of Object.entries(attributes)) {
      this.setAttribute(name, attr);
    }
    this.setIndex(
      new Uint32BufferAttribute(Array(indexCount).fill(0), 1, false)
    );
    this._featureInfos = featureInfos;
    this._featureMap = createSubsetFeatureMap(featureInfos);
    this._state = "empty";
  }
  addId(id) {
    if (this._featureMap[id] && this._state !== "full" && this.index) {
      const features = this._featureMap[id];
      for (const { indexStart, indices } of features) {
        for (let i = 0; i < indices.length; ++i) {
          this.index.array[indexStart + i] = indices[i];
        }
        this.index.addUpdateRange(indexStart, indices.length);
      }
      this.index.needsUpdate = true;
      this._ids.add(id);
      this._state = "partial";
    }
  }
  removeId(id) {
    if (this._featureMap[id] && this._state !== "empty" && this.index) {
      const features = this._featureMap[id];
      for (const { indexStart, indices } of features) {
        for (let i = 0; i < indices.length; ++i) {
          this.index.array[indexStart + i] = 0;
        }
        this.index.addUpdateRange(indexStart, indices.length);
      }
      this.index.needsUpdate = true;
      this._ids.delete(id);
      this._state = "partial";
    }
  }
  addAllIds() {
    if (this._state !== "full" && this.index) {
      for (const [id, features] of Object.entries(this._featureMap)) {
        this._ids.add(parseInt(id));
        for (const { indexStart, indices } of features) {
          for (let i = 0; i < indices.length; ++i) {
            this.index.array[indexStart + i] = indices[i];
          }
        }
      }
      this.index.addUpdateRange(0, this.index.count);
      this.index.needsUpdate = true;
      this._state = "full";
    }
  }
  clearIds() {
    if (this._state !== "empty" && this.index) {
      this.index.array.fill(0);
      this.index.addUpdateRange(0, this.index.count);
      this.index.needsUpdate = true;
      this._ids.clear();
      this._state = "empty";
    }
  }
  hasId(id) {
    return this._ids.has(id);
  }
  getIds() {
    return Array.from(this._ids);
  }
  copy(source) {
    const index = this.getIndex();
    super.copy(source);
    this.setIndex(index);
    return this;
  }
  clone() {
    const newGeometry = new _SubsetGeometry(
      {
        position: this.getAttribute("position")
      },
      this._featureInfos
    );
    newGeometry.copy(this);
    for (const id of this.getIds()) {
      newGeometry.addId(id);
    }
    return newGeometry;
  }
};

export {
  SubsetGeometry
};
