import { ObservablePoint } from '../../../maths/ObservablePoint.mjs';
import { uid } from '../../../utils/data/uid.mjs';
import { updateQuadBounds } from '../../../utils/updateQuadBounds.mjs';
import { Texture } from '../../renderers/shared/texture/Texture.mjs';
import { emptyViewObserver } from '../../renderers/shared/View.mjs';

class SpriteView {
  constructor(texture) {
    this.renderPipeId = "sprite";
    this.owner = emptyViewObserver;
    this.uid = uid("spriteView");
    this.batched = true;
    /** @internal */
    this._didUpdate = false;
    this._bounds = [0, 1, 0, 0];
    this._sourceBounds = [0, 1, 0, 0];
    this._boundsDirty = true;
    this._sourceBoundsDirty = true;
    this.anchor = new ObservablePoint(
      this,
      texture.layout.defaultAnchor?.x || 0,
      texture.layout.defaultAnchor?.y || 0
    );
    this.texture = texture;
  }
  set texture(value) {
    value || (value = Texture.EMPTY);
    if (this._texture === value)
      return;
    if (this._texture) {
      this._texture.off("update", this.onUpdate, this);
    }
    value.on("update", this.onUpdate, this);
    this._texture = value;
    this.onUpdate();
  }
  get texture() {
    return this._texture;
  }
  get bounds() {
    if (this._boundsDirty) {
      this._updateBounds();
      this._boundsDirty = false;
    }
    return this._bounds;
  }
  get sourceBounds() {
    if (this._sourceBoundsDirty) {
      this._updateSourceBounds();
      this._sourceBoundsDirty = false;
    }
    return this._sourceBounds;
  }
  // passed local space..
  containsPoint(point) {
    const width = this._texture.frameWidth;
    const height = this._texture.frameHeight;
    const x1 = -width * this.anchor.x;
    let y1 = 0;
    if (point.x >= x1 && point.x < x1 + width) {
      y1 = -height * this.anchor.y;
      if (point.y >= y1 && point.y < y1 + height) {
        return true;
      }
    }
    return false;
  }
  addBounds(bounds) {
    const trim = this._texture._layout.trim;
    if (trim) {
      const sourceBounds = this.sourceBounds;
      bounds.addFrame(sourceBounds[0], sourceBounds[2], sourceBounds[1], sourceBounds[3]);
    } else {
      const _bounds = this.bounds;
      bounds.addFrame(_bounds[0], _bounds[2], _bounds[1], _bounds[3]);
    }
  }
  /**
   * @internal
   */
  onUpdate() {
    this._didUpdate = true;
    this._sourceBoundsDirty = this._boundsDirty = true;
    this.owner.onViewUpdate();
  }
  _updateBounds() {
    updateQuadBounds(this._bounds, this.anchor, this._texture, 0);
  }
  _updateSourceBounds() {
    const anchor = this.anchor;
    const texture = this._texture;
    const textureSource = texture._source;
    const layout = texture.layout;
    const orig = layout.orig;
    const sourceBounds = this._sourceBounds;
    const width = textureSource.width * orig.width;
    const height = textureSource.height * orig.height;
    sourceBounds[1] = -anchor._x * width;
    sourceBounds[0] = sourceBounds[1] + width;
    sourceBounds[3] = -anchor._y * height;
    sourceBounds[2] = sourceBounds[3] + height;
  }
  /**
   * Destroys this sprite renderable and optionally its texture.
   * @param options - Options parameter. A boolean will act as if all options
   *  have been set to that value
   * @param {boolean} [options.texture=false] - Should it destroy the current texture of the renderable as well
   * @param {boolean} [options.textureSource=false] - Should it destroy the textureSource of the renderable as well
   */
  destroy(options = false) {
    this.anchor = null;
    const destroyTexture = typeof options === "boolean" ? options : options?.texture;
    if (destroyTexture) {
      const destroyTextureSource = typeof options === "boolean" ? options : options?.textureSource;
      this._texture.destroy(destroyTextureSource);
    }
    this._texture = null;
    this._bounds = null;
    this._sourceBounds = null;
  }
}

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