import { state, property } from 'lit/decorators.js';
import FlowRdfElement from '../../internal/flow-ui-rdf-element.mjs';
import { watch } from '../../internal/watch.mjs';
import styles from './icon.styles.mjs';
import { watchIcon, unwatchIcon, getIconLibrary } from './library.mjs';

var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __decorateClass = (decorators, target, key, kind) => {
  var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
  for (var i = decorators.length - 1, decorator; i >= 0; i--)
    if (decorator = decorators[i])
      result = (kind ? decorator(target, key, result) : decorator(result)) || result;
  if (kind && result)
    __defProp(target, key, result);
  return result;
};
const CACHEABLE_ERROR = Symbol();
const RETRYABLE_ERROR = Symbol();
let parser;
const iconCache = /* @__PURE__ */ new Map();
const _FlowUiIcon = class _FlowUiIcon extends FlowRdfElement {
  constructor() {
    super(...arguments);
    this.svg = null;
    this.label = "";
    this.library = "default";
  }
  /** Given a URL, this function returns the resulting SVG element or an appropriate error symbol. */
  static async resolveIcon(url) {
    let fileData;
    try {
      fileData = await fetch(url, { mode: "cors" });
      if (!fileData.ok)
        return fileData.status === 410 ? CACHEABLE_ERROR : RETRYABLE_ERROR;
    } catch {
      return RETRYABLE_ERROR;
    }
    try {
      const div = document.createElement("div");
      div.innerHTML = await fileData.text();
      const svg = div.firstElementChild;
      if (svg?.tagName?.toLowerCase() !== "svg")
        return CACHEABLE_ERROR;
      if (!parser)
        parser = new DOMParser();
      const doc = parser.parseFromString(svg.outerHTML, "text/html");
      const svgEl = doc.body.querySelector("svg");
      if (!svgEl)
        return CACHEABLE_ERROR;
      svgEl.part.add("svg");
      return document.adoptNode(svgEl);
    } catch {
      return CACHEABLE_ERROR;
    }
  }
  connectedCallback() {
    super.connectedCallback();
    watchIcon(this);
  }
  firstUpdated() {
    this.setIcon();
  }
  disconnectedCallback() {
    super.disconnectedCallback();
    unwatchIcon(this);
  }
  getUrl() {
    const library = getIconLibrary(this.library);
    if (this.name && library) {
      return library.resolver(this.name);
    }
    return this.src;
  }
  handleLabelChange() {
    const hasLabel = typeof this.label === "string" && this.label.length > 0;
    if (hasLabel) {
      this.setAttribute("role", "img");
      this.setAttribute("aria-label", this.label);
      this.removeAttribute("aria-hidden");
    } else {
      this.removeAttribute("role");
      this.removeAttribute("aria-label");
      this.setAttribute("aria-hidden", "true");
    }
  }
  async setIcon() {
    const library = getIconLibrary(this.library);
    const url = this.getUrl();
    if (!url) {
      this.svg = null;
      return;
    }
    let iconResolver = iconCache.get(url);
    if (!iconResolver) {
      iconResolver = _FlowUiIcon.resolveIcon(url);
      iconCache.set(url, iconResolver);
    }
    const svg = await iconResolver;
    if (svg === RETRYABLE_ERROR) {
      iconCache.delete(url);
    }
    if (url !== this.getUrl()) {
      return;
    }
    switch (svg) {
      case RETRYABLE_ERROR:
      case CACHEABLE_ERROR:
        this.svg = null;
        this.emit("flow-ui-error");
        break;
      default:
        this.svg = svg.cloneNode(true);
        library?.mutator?.(this.svg);
        this.emit("flow-ui-load");
    }
  }
  render() {
    return this.svg;
  }
};
_FlowUiIcon.styles = styles;
__decorateClass([
  state()
], _FlowUiIcon.prototype, "svg", 2);
__decorateClass([
  property({ reflect: true })
], _FlowUiIcon.prototype, "name", 2);
__decorateClass([
  property()
], _FlowUiIcon.prototype, "src", 2);
__decorateClass([
  property()
], _FlowUiIcon.prototype, "label", 2);
__decorateClass([
  property({ reflect: true })
], _FlowUiIcon.prototype, "library", 2);
__decorateClass([
  watch("label")
], _FlowUiIcon.prototype, "handleLabelChange", 1);
__decorateClass([
  watch(["name", "src", "library"])
], _FlowUiIcon.prototype, "setIcon", 1);
let FlowUiIcon = _FlowUiIcon;

export { FlowUiIcon as default };
