import '../core/settings.mjs';
import '../color.mjs';
import '../constants.mjs';
import '../extensions.mjs';
import '../math/const.mjs';
import { Rectangle } from '../math/shapes/Rectangle.mjs';
import '../math/groupD8.mjs';
import '../math/Transform.mjs';
import '../runner.mjs';
import '../ticker/settings.mjs';
import '../ticker/const.mjs';
import '../ticker/Ticker.mjs';
import '../ticker/TickerPlugin.mjs';
import '../utils/settings.mjs';
import '../utils/is_mobile/index.mjs';
import '../utils/color/premultiply.mjs';
import '../utils/media/BoundingBox.mjs';
import { getResolutionOfUrl } from '../utils/network/getResolutionOfUrl.mjs';
import '../core/autoDetectRenderer.mjs';
import '../core/background/BackgroundSystem.mjs';
import '../core/batch/BatchRenderer.mjs';
import '../core/shader/Program.mjs';
import '../core/batch/BatchSystem.mjs';
import '../core/context/ContextSystem.mjs';
import '../core/filters/Filter.mjs';
import '../core/filters/FilterSystem.mjs';
import { BaseTexture } from '../core/textures/BaseTexture.mjs';
import '../core/framebuffer/FramebufferSystem.mjs';
import '../core/framebuffer/MultisampleSystem.mjs';
import '../core/geometry/BufferSystem.mjs';
import '../core/geometry/GeometrySystem.mjs';
import '../core/mask/MaskSystem.mjs';
import '../core/mask/ScissorSystem.mjs';
import '../core/mask/StencilSystem.mjs';
import '../core/plugin/PluginSystem.mjs';
import '../core/projection/ProjectionSystem.mjs';
import '../core/render/ObjectRendererSystem.mjs';
import '../core/Renderer.mjs';
import '../core/renderTexture/GenerateTextureSystem.mjs';
import { Texture } from '../core/textures/Texture.mjs';
import '../core/renderTexture/RenderTexturePool.mjs';
import '../core/renderTexture/RenderTextureSystem.mjs';
import '../core/shader/ShaderSystem.mjs';
import '../core/startup/StartupSystem.mjs';
import '../core/state/StateSystem.mjs';
import '../core/textures/TextureGCSystem.mjs';
import '../core/textures/TextureSystem.mjs';
import '../core/transformFeedback/TransformFeedbackSystem.mjs';
import '../core/view/ViewSystem.mjs';
import '../core/textures/resources/index.mjs';

class Spritesheet {
  /**
   * @param texture - Reference to the source BaseTexture object.
   * @param {object} data - Spritesheet image data.
   * @param resolutionFilename - The filename to consider when determining
   *        the resolution of the spritesheet. If not provided, the imageUrl will
   *        be used on the BaseTexture.
   */
  constructor(texture, data, resolutionFilename = null) {
    this.linkedSheets = [];
    this._texture = texture instanceof Texture ? texture : null;
    this.baseTexture = texture instanceof BaseTexture ? texture : this._texture.baseTexture;
    this.textures = {};
    this.animations = {};
    this.data = data;
    const resource = this.baseTexture.resource;
    this.resolution = this._updateResolution(resolutionFilename || (resource ? resource.url : null));
    this._frames = this.data.frames;
    this._frameKeys = Object.keys(this._frames);
    this._batchIndex = 0;
    this._callback = null;
  }
  /**
   * Generate the resolution from the filename or fallback
   * to the meta.scale field of the JSON data.
   * @param resolutionFilename - The filename to use for resolving
   *        the default resolution.
   * @returns Resolution to use for spritesheet.
   */
  _updateResolution(resolutionFilename = null) {
    const { scale } = this.data.meta;
    let resolution = getResolutionOfUrl(resolutionFilename, null);
    if (resolution === null) {
      resolution = parseFloat(scale ?? "1");
    }
    if (resolution !== 1) {
      this.baseTexture.setResolution(resolution);
    }
    return resolution;
  }
  /**
   * Parser spritesheet from loaded data. This is done asynchronously
   * to prevent creating too many Texture within a single process.
   * @method PIXI.Spritesheet#parse
   */
  parse() {
    return new Promise((resolve) => {
      this._callback = resolve;
      this._batchIndex = 0;
      if (this._frameKeys.length <= Spritesheet.BATCH_SIZE) {
        this._processFrames(0);
        this._processAnimations();
        this._parseComplete();
      } else {
        this._nextBatch();
      }
    });
  }
  /**
   * Process a batch of frames
   * @param initialFrameIndex - The index of frame to start.
   */
  _processFrames(initialFrameIndex) {
    let frameIndex = initialFrameIndex;
    const maxFrames = Spritesheet.BATCH_SIZE;
    while (frameIndex - initialFrameIndex < maxFrames && frameIndex < this._frameKeys.length) {
      const i = this._frameKeys[frameIndex];
      const data = this._frames[i];
      const rect = data.frame;
      if (rect) {
        let frame = null;
        let trim = null;
        const sourceSize = data.trimmed !== false && data.sourceSize ? data.sourceSize : data.frame;
        const orig = new Rectangle(0, 0, Math.floor(sourceSize.w) / this.resolution, Math.floor(sourceSize.h) / this.resolution);
        if (data.rotated) {
          frame = new Rectangle(Math.floor(rect.x) / this.resolution, Math.floor(rect.y) / this.resolution, Math.floor(rect.h) / this.resolution, Math.floor(rect.w) / this.resolution);
        } else {
          frame = new Rectangle(Math.floor(rect.x) / this.resolution, Math.floor(rect.y) / this.resolution, Math.floor(rect.w) / this.resolution, Math.floor(rect.h) / this.resolution);
        }
        if (data.trimmed !== false && data.spriteSourceSize) {
          trim = new Rectangle(Math.floor(data.spriteSourceSize.x) / this.resolution, Math.floor(data.spriteSourceSize.y) / this.resolution, Math.floor(rect.w) / this.resolution, Math.floor(rect.h) / this.resolution);
        }
        this.textures[i] = new Texture(this.baseTexture, frame, orig, trim, data.rotated ? 2 : 0, data.anchor, data.borders);
        Texture.addToCache(this.textures[i], i);
      }
      frameIndex++;
    }
  }
  /** Parse animations config. */
  _processAnimations() {
    const animations = this.data.animations || {};
    for (const animName in animations) {
      this.animations[animName] = [];
      for (let i = 0; i < animations[animName].length; i++) {
        const frameName = animations[animName][i];
        this.animations[animName].push(this.textures[frameName]);
      }
    }
  }
  /** The parse has completed. */
  _parseComplete() {
    const callback = this._callback;
    this._callback = null;
    this._batchIndex = 0;
    callback.call(this, this.textures);
  }
  /** Begin the next batch of textures. */
  _nextBatch() {
    this._processFrames(this._batchIndex * Spritesheet.BATCH_SIZE);
    this._batchIndex++;
    setTimeout(() => {
      if (this._batchIndex * Spritesheet.BATCH_SIZE < this._frameKeys.length) {
        this._nextBatch();
      } else {
        this._processAnimations();
        this._parseComplete();
      }
    }, 0);
  }
  /**
   * Destroy Spritesheet and don't use after this.
   * @param {boolean} [destroyBase=false] - Whether to destroy the base texture as well
   */
  destroy(destroyBase = false) {
    for (const i in this.textures) {
      this.textures[i].destroy();
    }
    this._frames = null;
    this._frameKeys = null;
    this.data = null;
    this.textures = null;
    if (destroyBase) {
      this._texture?.destroy();
      this.baseTexture.destroy();
    }
    this._texture = null;
    this.baseTexture = null;
    this.linkedSheets = [];
  }
}
Spritesheet.BATCH_SIZE = 1e3;

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