import EventEmitter from 'eventemitter3';
import { Cache } from '../../../../assets/cache/Cache.mjs';
import { uid } from '../../../../utils/data/uid.mjs';
import { deprecation, v8_0_0 } from '../../../../utils/logging/deprecation.mjs';
import { NOOP } from '../../../../utils/NOOP.mjs';
import { BufferImageSource } from './sources/BufferImageSource.mjs';
import { TextureSource } from './sources/TextureSource.mjs';
import { TextureLayout } from './TextureLayout.mjs';
import { TextureMatrix } from './TextureMatrix.mjs';

class Texture extends EventEmitter {
  constructor({ source, layout, label, frame } = {}) {
    super();
    this.id = uid("texture");
    this.styleSourceKey = 0;
    this.label = label;
    this.source = source?.source ?? new TextureSource();
    layout = layout instanceof TextureLayout ? layout : new TextureLayout(layout);
    if (frame) {
      const { width, height } = this._source;
      layout.frame.x = frame.x / width;
      layout.frame.y = frame.y / height;
      layout.frame.width = frame.width / width;
      layout.frame.height = frame.height / height;
      layout.updateUvs();
    }
    this.layout = layout;
    this.destroyed = false;
  }
  static from(id) {
    if (typeof id === "string") {
      return Cache.get(id);
    } else if (id instanceof TextureSource) {
      return new Texture({ source: id });
    }
    return new Texture({
      source: new TextureSource(id)
    });
  }
  static fromBuffer(options) {
    return new Texture({
      source: BufferImageSource.from({
        ...options,
        style: {
          scaleMode: "nearest"
        }
      })
    });
  }
  set source(value) {
    if (this._source) {
      this._source.off("resize", this.onUpdate, this);
    }
    this._source = value;
    value.on("resize", this.onUpdate, this);
    this.emit("update", this);
  }
  get source() {
    return this._source;
  }
  get layout() {
    return this._layout;
  }
  set layout(value) {
    this._layout?.off("update", this.onUpdate, this);
    this._layout = value;
    value.on("update", this.onUpdate, this);
    this.emit("update", this);
  }
  get textureMatrix() {
    if (!this._textureMatrix) {
      this._textureMatrix = new TextureMatrix(this);
    }
    return this._textureMatrix;
  }
  set frameWidth(value) {
    this._layout.frame.width = value / this._source.width;
  }
  get frameWidth() {
    return this._source.pixelWidth / this._source._resolution * this._layout.frame.width;
  }
  set frameHeight(value) {
    this._layout.frame.height = value / this._source.height;
  }
  get frameHeight() {
    return this._source.pixelHeight / this._source._resolution * this._layout.frame.height;
  }
  set frameX(value) {
    if (value === 0) {
      this._layout.frame.x = 0;
      return;
    }
    this._layout.frame.x = this._source.width / value;
  }
  get frameX() {
    return this._source.width * this._layout.frame.x;
  }
  set frameY(value) {
    if (value === 0) {
      this._layout.frame.y = 0;
      return;
    }
    this._layout.frame.y = this._source.height / value;
  }
  get frameY() {
    return this._source.height * this._layout.frame.y;
  }
  /** The width of the Texture in pixels. */
  get width() {
    return this._source.width * this._layout.orig.width;
  }
  /** The height of the Texture in pixels. */
  get height() {
    return this._source.height * this._layout.orig.height;
  }
  /**
   * Destroys this texture
   * @param destroySource - Destroy the source when the texture is destroyed.
   */
  destroy(destroySource = false) {
    if (this._layout) {
      this._layout.destroy();
      this._layout = null;
    }
    if (this._source) {
      if (destroySource) {
        this._source.destroy();
        this._source = null;
      }
    }
    this._textureMatrix = null;
    this.destroyed = true;
    this.emit("destroy", this);
    this.removeAllListeners();
  }
  /**
   * @internal
   */
  onUpdate() {
    this.emit("update", this);
  }
  /** @deprecated since 8.0.0 */
  get baseTexture() {
    deprecation(v8_0_0, "Texture.baseTexture is now Texture.source");
    return this._source;
  }
}
Texture.EMPTY = new Texture({});
Texture.EMPTY.label = "EMPTY";
Texture.EMPTY.destroy = NOOP;

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