'use strict';

require('../core/settings.js');
require('../color.js');
require('../constants.js');
require('../extensions.js');
require('../math/const.js');
require('../math/groupD8.js');
require('../math/Transform.js');
require('../runner.js');
var settings = require('../settings/settings.js');
require('../ticker/settings.js');
require('../ticker/const.js');
require('../ticker/Ticker.js');
require('../ticker/TickerPlugin.js');
require('../utils/settings.js');
require('../utils/is_mobile/index.js');
var path = require('../utils/path.js');
var hex = require('../utils/color/hex.js');
require('../utils/color/premultiply.js');
require('../utils/media/BoundingBox.js');
require('../core/autoDetectRenderer.js');
require('../core/background/BackgroundSystem.js');
require('../core/batch/BatchRenderer.js');
require('../core/shader/Program.js');
require('../core/batch/BatchSystem.js');
require('../core/context/ContextSystem.js');
require('../core/filters/Filter.js');
require('../core/filters/FilterSystem.js');
require('../core/textures/BaseTexture.js');
require('../core/framebuffer/FramebufferSystem.js');
require('../core/framebuffer/MultisampleSystem.js');
require('../core/geometry/BufferSystem.js');
require('../core/geometry/GeometrySystem.js');
require('../core/mask/MaskSystem.js');
require('../core/mask/ScissorSystem.js');
require('../core/mask/StencilSystem.js');
require('../core/plugin/PluginSystem.js');
require('../core/projection/ProjectionSystem.js');
require('../core/render/ObjectRendererSystem.js');
require('../core/Renderer.js');
require('../core/renderTexture/GenerateTextureSystem.js');
require('../core/renderTexture/RenderTexturePool.js');
require('../core/renderTexture/RenderTextureSystem.js');
require('../core/shader/ShaderSystem.js');
require('../core/startup/StartupSystem.js');
require('../core/state/StateSystem.js');
require('../core/textures/TextureGCSystem.js');
require('../core/textures/TextureSystem.js');
require('../core/transformFeedback/TransformFeedbackSystem.js');
require('../core/view/ViewSystem.js');
require('../core/textures/resources/index.js');
require('../text/const.js');
require('../text/Text.js');
require('../text/TextMetrics.js');
var TextStyle = require('../text/TextStyle.js');

class HTMLTextStyle extends TextStyle.TextStyle {
  constructor() {
    super(...arguments);
    this._fonts = [];
    this._overrides = [];
    this._stylesheet = "";
    this.fontsDirty = false;
  }
  /**
   * Convert a TextStyle to HTMLTextStyle
   * @param originalStyle
   * @example
   * import {TextStyle } from 'pixi.js';
   * import {HTMLTextStyle} from '@vaux/text-html';
   * const style = new TextStyle();
   * const htmlStyle = HTMLTextStyle.from(style);
   */
  static from(originalStyle) {
    return new HTMLTextStyle(Object.keys(HTMLTextStyle.defaultOptions).reduce((obj, prop) => ({ ...obj, [prop]: originalStyle[prop] }), {}));
  }
  /** Clear the current font */
  cleanFonts() {
    if (this._fonts.length > 0) {
      this._fonts.forEach((font) => {
        URL.revokeObjectURL(font.src);
        font.refs--;
        if (font.refs === 0) {
          if (font.fontFace) {
            document.fonts.delete(font.fontFace);
          }
          delete HTMLTextStyle.availableFonts[font.originalUrl];
        }
      });
      this.fontFamily = "Arial";
      this._fonts.length = 0;
      this.styleID++;
      this.fontsDirty = true;
    }
  }
  /**
   * Because of how HTMLText renders, fonts need to be imported
   * @param url
   * @param options
   */
  loadFont(url, options = {}) {
    const { availableFonts } = HTMLTextStyle;
    if (availableFonts[url]) {
      const font = availableFonts[url];
      this._fonts.push(font);
      font.refs++;
      this.styleID++;
      this.fontsDirty = true;
      return Promise.resolve();
    }
    return settings.settings.ADAPTER.fetch(url).then((response) => response.blob()).then(async (blob) => new Promise((resolve, reject) => {
      const src = URL.createObjectURL(blob);
      const reader = new FileReader();
      reader.onload = () => resolve([src, reader.result]);
      reader.onerror = reject;
      reader.readAsDataURL(blob);
    })).then(async ([src, dataSrc]) => {
      const font = Object.assign({
        family: path.path.basename(url, path.path.extname(url)),
        weight: "normal",
        style: "normal",
        display: "auto",
        src,
        dataSrc,
        refs: 1,
        originalUrl: url,
        fontFace: null
      }, options);
      availableFonts[url] = font;
      this._fonts.push(font);
      this.styleID++;
      const fontFace = new FontFace(font.family, `url(${font.src})`, {
        weight: font.weight,
        style: font.style,
        display: font.display
      });
      font.fontFace = fontFace;
      await fontFace.load();
      document.fonts.add(fontFace);
      await document.fonts.ready;
      this.styleID++;
      this.fontsDirty = true;
    });
  }
  /**
   * Add a style override, this can be any CSS property
   * it will override any built-in style. This is the
   * property and the value as a string (e.g., `color: red`).
   * This will override any other internal style.
   * @param {string} value - CSS style(s) to add.
   * @example
   * style.addOverride('background-color: red');
   */
  addOverride(...value) {
    const toAdd = value.filter((v) => !this._overrides.includes(v));
    if (toAdd.length > 0) {
      this._overrides.push(...toAdd);
      this.styleID++;
    }
  }
  /**
   * Remove any overrides that match the value.
   * @param {string} value - CSS style to remove.
   * @example
   * style.removeOverride('background-color: red');
   */
  removeOverride(...value) {
    const toRemove = value.filter((v) => this._overrides.includes(v));
    if (toRemove.length > 0) {
      this._overrides = this._overrides.filter((v) => !toRemove.includes(v));
      this.styleID++;
    }
  }
  /**
   * Internally converts all of the style properties into CSS equivalents.
   * @param scale
   * @returns The CSS style string, for setting `style` property of root HTMLElement.
   */
  toCSS(scale) {
    return [
      `transform: scale(${scale})`,
      `transform-origin: top left`,
      "display: inline-block",
      `color: ${this.normalizeColor(this.fill)}`,
      `font-size: ${this.fontSize}px`,
      `font-family: ${this.fontFamily}`,
      `font-weight: ${this.fontWeight}`,
      `font-style: ${this.fontStyle}`,
      `font-variant: ${this.fontVariant}`,
      `letter-spacing: ${this.letterSpacing}px`,
      `text-align: ${this.align}`,
      `padding: ${this.padding}px`,
      `white-space: ${this.whiteSpace}`,
      ...this.lineHeight ? [`line-height: ${this.lineHeight}px`] : [],
      ...this.wordWrap ? [
        `word-wrap: ${this.breakWords ? "break-all" : "break-word"}`,
        `max-width: ${this.wordWrapWidth}px`
      ] : [],
      ...this.strokeThickness ? [
        `-webkit-text-stroke-width: ${this.strokeThickness}px`,
        `-webkit-text-stroke-color: ${this.normalizeColor(this.stroke)}`,
        `text-stroke-width: ${this.strokeThickness}px`,
        `text-stroke-color: ${this.normalizeColor(this.stroke)}`,
        "paint-order: stroke"
      ] : [],
      ...this.dropShadow ? [this.dropShadowToCSS()] : [],
      ...this._overrides
    ].join(";");
  }
  /** Get the font CSS styles from the loaded font, If available. */
  toGlobalCSS() {
    return this._fonts.reduce((result, font) => `${result}
            @font-face {
                font-family: "${font.family}";
                src: url('${font.dataSrc}');
                font-weight: ${font.weight};
                font-style: ${font.style};
                font-display: ${font.display};
            }`, this._stylesheet);
  }
  /** Internal stylesheet contents, useful for creating rules for rendering */
  get stylesheet() {
    return this._stylesheet;
  }
  set stylesheet(value) {
    if (this._stylesheet !== value) {
      this._stylesheet = value;
      this.styleID++;
    }
  }
  /**
   * Convert numerical colors into hex-strings
   * @param color
   */
  normalizeColor(color) {
    if (Array.isArray(color)) {
      color = hex.rgb2hex(color);
    }
    if (typeof color === "number") {
      return hex.hex2string(color);
    }
    return color;
  }
  /** Convert the internal drop-shadow settings to CSS text-shadow */
  dropShadowToCSS() {
    let color = this.normalizeColor(this.dropShadowColor);
    const alpha = this.dropShadowAlpha;
    const x = Math.round(Math.cos(this.dropShadowAngle) * this.dropShadowDistance);
    const y = Math.round(Math.sin(this.dropShadowAngle) * this.dropShadowDistance);
    if (color.startsWith("#") && alpha < 1) {
      color += (alpha * 255 | 0).toString(16).padStart(2, "0");
    }
    const position = `${x}px ${y}px`;
    if (this.dropShadowBlur > 0) {
      return `text-shadow: ${position} ${this.dropShadowBlur}px ${color}`;
    }
    return `text-shadow: ${position} ${color}`;
  }
  /** Resets all properties to the defaults specified in TextStyle.prototype._default */
  reset() {
    Object.assign(this, HTMLTextStyle.defaultOptions);
  }
  /**
   * Called after the image is loaded but before drawing to the canvas.
   * Mostly used to handle Safari's font loading bug.
   * @ignore
   */
  onBeforeDraw() {
    const { fontsDirty: prevFontsDirty } = this;
    this.fontsDirty = false;
    if (this.isSafari && this._fonts.length > 0 && prevFontsDirty) {
      return new Promise((resolve) => setTimeout(resolve, 100));
    }
    return Promise.resolve();
  }
  /**
   * Proving that Safari is the new IE
   * @ignore
   */
  get isSafari() {
    const { userAgent } = settings.settings.ADAPTER.getNavigator();
    return /^((?!chrome|android).)*safari/i.test(userAgent);
  }
  set fillGradientStops(_value) {
    console.warn("[HTMLTextStyle] fillGradientStops is not supported by HTMLText");
  }
  get fillGradientStops() {
    return super.fillGradientStops;
  }
  set fillGradientType(_value) {
    console.warn("[HTMLTextStyle] fillGradientType is not supported by HTMLText");
  }
  get fillGradientType() {
    return super.fillGradientType;
  }
  set miterLimit(_value) {
    console.warn("[HTMLTextStyle] miterLimit is not supported by HTMLText");
  }
  get miterLimit() {
    return super.miterLimit;
  }
  set trim(_value) {
    console.warn("[HTMLTextStyle] trim is not supported by HTMLText");
  }
  get trim() {
    return super.trim;
  }
  set textBaseline(_value) {
    console.warn("[HTMLTextStyle] textBaseline is not supported by HTMLText");
  }
  get textBaseline() {
    return super.textBaseline;
  }
  set leading(_value) {
    console.warn("[HTMLTextStyle] leading is not supported by HTMLText");
  }
  get leading() {
    return super.leading;
  }
  set lineJoin(_value) {
    console.warn("[HTMLTextStyle] lineJoin is not supported by HTMLText");
  }
  get lineJoin() {
    return super.lineJoin;
  }
}
HTMLTextStyle.availableFonts = {};
HTMLTextStyle.defaultOptions = {
  /** Align */
  align: "left",
  /** Break words */
  breakWords: false,
  /** Drop shadow */
  dropShadow: false,
  /** Drop shadow alpha */
  dropShadowAlpha: 1,
  /**
   * Drop shadow angle
   * @type {number}
   * @default Math.PI / 6
   */
  dropShadowAngle: Math.PI / 6,
  /** Drop shadow blur */
  dropShadowBlur: 0,
  /** Drop shadow color */
  dropShadowColor: "black",
  /** Drop shadow distance */
  dropShadowDistance: 5,
  /** Fill */
  fill: "black",
  /** Font family */
  fontFamily: "Arial",
  /** Font size */
  fontSize: 26,
  /** Font style */
  fontStyle: "normal",
  /** Font variant */
  fontVariant: "normal",
  /** Font weight */
  fontWeight: "normal",
  /** Letter spacing */
  letterSpacing: 0,
  /** Line height */
  lineHeight: 0,
  /** Padding */
  padding: 0,
  /** Stroke */
  stroke: "black",
  /** Stroke thickness */
  strokeThickness: 0,
  /** White space */
  whiteSpace: "normal",
  /** Word wrap */
  wordWrap: false,
  /** Word wrap width */
  wordWrapWidth: 100
};

exports.HTMLTextStyle = HTMLTextStyle;
//# sourceMappingURL=HTMLTextStyle.js.map
