import { Cache } from '../../assets/cache/Cache.mjs';
import { ObservablePoint } from '../../maths/ObservablePoint.mjs';
import { uid } from '../../utils/data/uid.mjs';
import { emptyViewObserver } from '../renderers/shared/View.mjs';
import { BitmapFont } from './bitmap/BitmapFont.mjs';
import { BitmapFontManager } from './bitmap/BitmapFontManager.mjs';
import { DynamicBitmapFont } from './bitmap/DynamicBitmapFont.mjs';
import { CanvasTextMetrics } from './canvas/CanvasTextMetrics.mjs';
import { measureHtmlText } from './html/utils/measureHtmlText..mjs';
import { HTMLTextStyle } from './HtmlTextStyle.mjs';
import { ensureTextStyle } from './shared/utils/ensureTextStyle.mjs';

const map = {
  canvas: "text",
  html: "htmlText",
  bitmap: "bitmapText"
};
class TextView {
  constructor(options) {
    this.uid = uid("textView");
    this.renderPipeId = "text";
    this.owner = emptyViewObserver;
    this.batched = true;
    this.resolution = null;
    /** @internal */
    this._didUpdate = true;
    this._bounds = [0, 1, 0, 0];
    this._boundsDirty = true;
    this.text = options.text ?? "";
    const renderMode = options.renderMode ?? this._detectRenderType(options.style);
    this._renderMode = renderMode;
    this._style = ensureTextStyle(renderMode, options.style);
    this.renderPipeId = map[renderMode];
    this.anchor = new ObservablePoint(this, 0, 0);
    this.resolution = options.resolution ?? null;
  }
  set text(value) {
    value = value.toString();
    if (this._text === value)
      return;
    this._text = value;
    this.onUpdate();
  }
  get text() {
    return this._text;
  }
  get style() {
    return this._style;
  }
  set style(style) {
    style = style || {};
    this._style?.off("update", this.onUpdate, this);
    this._style = ensureTextStyle(this._renderMode, style);
    this._style.on("update", this.onUpdate, this);
    this.onUpdate();
  }
  get bounds() {
    if (this._boundsDirty) {
      this._updateBounds();
      this._boundsDirty = false;
    }
    return this._bounds;
  }
  addBounds(bounds) {
    const _bounds = this.bounds;
    bounds.addFrame(
      _bounds[0],
      _bounds[2],
      _bounds[1],
      _bounds[3]
    );
  }
  containsPoint(point) {
    const width = this.bounds[2];
    const height = this.bounds[3];
    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;
  }
  /** @internal */
  onUpdate() {
    this._didUpdate = true;
    this._boundsDirty = true;
    this.owner.onViewUpdate();
  }
  /** @internal */
  _getKey() {
    return `${this.text}:${this._style.styleKey}`;
  }
  _updateBounds() {
    const bounds = this._bounds;
    const padding = this._style.padding;
    const anchor = this.anchor;
    if (this.renderPipeId === "bitmapText") {
      const bitmapMeasurement = BitmapFontManager.measureText(this.text, this._style);
      const scale = bitmapMeasurement.scale;
      const offset = bitmapMeasurement.offsetY * scale;
      const width = bitmapMeasurement.width * scale;
      const height = bitmapMeasurement.height * scale;
      bounds[0] = -anchor._x * width - padding;
      bounds[1] = bounds[0] + width;
      bounds[2] = -anchor._y * (height + offset) - padding;
      bounds[3] = bounds[2] + height;
    } else if (this.renderPipeId === "htmlText") {
      const htmlMeasurement = measureHtmlText(this.text, this._style);
      const { width, height } = htmlMeasurement;
      bounds[0] = -anchor._x * width - padding;
      bounds[1] = bounds[0] + width;
      bounds[2] = -anchor._y * height - padding;
      bounds[3] = bounds[2] + height;
    } else {
      const canvasMeasurement = CanvasTextMetrics.measureText(this.text, this._style);
      const { width, height } = canvasMeasurement;
      bounds[0] = -anchor._x * width - padding;
      bounds[1] = bounds[0] + width;
      bounds[2] = -anchor._y * height - padding;
      bounds[3] = bounds[2] + height;
    }
  }
  _detectRenderType(style) {
    if (style instanceof HTMLTextStyle) {
      return "html";
    }
    const fontData = Cache.get(style?.fontFamily);
    if (fontData instanceof DynamicBitmapFont || fontData instanceof BitmapFont) {
      return "bitmap";
    }
    return "canvas";
  }
  /**
   * Destroys this text renderable and optionally its style 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 texture of the text style
   * @param {boolean} [options.textureSource=false] - Should it destroy the textureSource of the text style
   */
  destroy(options = false) {
    this.owner = null;
    this._bounds = null;
    this.anchor = null;
    this._style.destroy(options);
    this._style = null;
    this._text = null;
  }
}

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