import EventEmitter from 'eventemitter3';
import { Bounds } from '../../../../scene/container/bounds/Bounds.mjs';
import { uid } from '../../../../utils/data/uid.mjs';
import { Buffer } from '../buffer/Buffer.mjs';
import { ensureIsBuffer } from './utils/ensureIsBuffer.mjs';
import { getGeometryBounds } from './utils/getGeometryBounds.mjs';

"use strict";
function ensureIsAttribute(attribute) {
  if (attribute instanceof Buffer || Array.isArray(attribute) || attribute.BYTES_PER_ELEMENT) {
    attribute = {
      buffer: attribute
    };
  }
  attribute.buffer = ensureIsBuffer(attribute.buffer, false);
  return attribute;
}
class Geometry extends EventEmitter {
  /**
   * Create a new instance of a geometry
   * @param options - The options for the geometry.
   */
  constructor(options) {
    const { attributes, indexBuffer, topology } = options;
    super();
    /** The unique id of the geometry. */
    this.uid = uid("geometry");
    /**
     * the layout key will be generated by WebGPU all geometries that have the same structure
     * will have the same layout key. This is used to cache the pipeline layout
     * @internal
     * @ignore
     */
    this._layoutKey = 0;
    /** the instance count of the geometry to draw */
    this.instanceCount = 1;
    this._bounds = new Bounds();
    this._boundsDirty = true;
    this.attributes = attributes;
    this.buffers = [];
    this.instanceCount = options.instanceCount || 1;
    for (const i in attributes) {
      const attribute = attributes[i] = ensureIsAttribute(attributes[i]);
      const bufferIndex = this.buffers.indexOf(attribute.buffer);
      if (bufferIndex === -1) {
        this.buffers.push(attribute.buffer);
        attribute.buffer.on("update", this.onBufferUpdate, this);
        attribute.buffer.on("change", this.onBufferUpdate, this);
      }
    }
    if (indexBuffer) {
      this.indexBuffer = ensureIsBuffer(indexBuffer, true);
      this.buffers.push(this.indexBuffer);
    }
    this.topology = topology || "triangle-list";
  }
  onBufferUpdate() {
    this._boundsDirty = true;
    this.emit("update", this);
  }
  /**
   * Returns the requested attribute.
   * @param id - The name of the attribute required
   * @returns - The attribute requested.
   */
  getAttribute(id) {
    return this.attributes[id];
  }
  /**
   * Returns the index buffer
   * @returns - The index buffer.
   */
  getIndex() {
    return this.indexBuffer;
  }
  /**
   * Returns the requested buffer.
   * @param id - The name of the buffer required.
   * @returns - The buffer requested.
   */
  getBuffer(id) {
    return this.getAttribute(id).buffer;
  }
  /**
   * Used to figure out how many vertices there are in this geometry
   * @returns the number of vertices in the geometry
   */
  getSize() {
    for (const i in this.attributes) {
      const attribute = this.attributes[i];
      const buffer = attribute.buffer;
      return buffer.data.length / (attribute.stride / 4 || attribute.size);
    }
    return 0;
  }
  /** Returns the bounds of the geometry. */
  get bounds() {
    if (!this._boundsDirty)
      return this._bounds;
    this._boundsDirty = false;
    return getGeometryBounds(this, "aPosition", this._bounds);
  }
  /**
   * destroys the geometry.
   * @param destroyBuffers - destroy the buffers associated with this geometry
   */
  destroy(destroyBuffers = false) {
    this.emit("destroy", this);
    this.removeAllListeners();
    if (destroyBuffers) {
      this.buffers.forEach((buffer) => buffer.destroy());
    }
    this.attributes = null;
    this.buffers = null;
    this.indexBuffer = null;
    this._bounds = null;
  }
}

export { Geometry };
//# sourceMappingURL=Geometry.mjs.map
