/**
 * Non-side-effect class export for `<image-ui>`.
 *
 * Importing this file gives you the class(es) without auto-registering the tag.
 * Useful for test isolation, subclassing with tag-name override, or selective
 * composition.
 *
 * The auto-register path stays at `@adia-ai/web-components/components/image`
 * (which imports this file + calls `defineIfFree()`).
 *
 * @see ../../USAGE.md#registration--auto-vs-explicit
 */

/**
 * <image-ui src="/photo.jpg" alt="Photo" width="300" height="200"></image-ui>
 * <image-ui src="/avatar.jpg" fit="cover" radius="full"></image-ui>
 * <image-ui src="/hero.jpg" size="full"></image-ui>
 * <image-ui src="/pixel.png" raw></image-ui>
 *
 * Lazy-loading image with skeleton fallback.
 * Shows skeleton-ui while loading, swaps to img on load.
 * Falls back to fallback URL or keeps skeleton on error.
 *
 * Size:   full (fills container width and height)
 * Radius: sm, md, lg, full
 * Fit:    cover (default), contain, fill, none
 * Raw:    strips chrome (no background, no radius) for edge-to-edge rendering
 */

import { UIElement } from '../../core/element.js';

export class UIImage extends UIElement {
  static properties = {
    src:      { type: String,  default: '',      reflect: true },
    alt:      { type: String,  default: '',      reflect: true },
    width:    { type: String,  default: '',      reflect: true },
    height:   { type: String,  default: '',      reflect: true },
    size:     { type: String,  default: '',      reflect: true },
    fit:      { type: String,  default: 'cover', reflect: true },
    radius:   { type: String,  default: '',      reflect: true },
    raw:      { type: Boolean, default: false,   reflect: true },
    fallback: { type: String,  default: '',      reflect: true },
  };

  static template = () => null;

  #img = null;
  #skeleton = null;

  connected() {
    this.#skeleton = this.querySelector(':scope > [slot="skeleton"]');
    if (!this.#skeleton) {
      this.#skeleton = document.createElement('skeleton-ui');
      this.#skeleton.setAttribute('slot', 'skeleton');
      this.#skeleton.setAttribute('width', '100%');
      this.#skeleton.setAttribute('height', '100%');
      this.appendChild(this.#skeleton);
    }

    this.#img = this.querySelector(':scope > [slot="image"]');
    if (!this.#img) {
      this.#img = document.createElement('img');
      this.#img.setAttribute('slot', 'image');
      this.#img.loading = 'lazy';
      this.appendChild(this.#img);
    }
    this.#img.addEventListener('load', this.#onLoad);
    this.#img.addEventListener('error', this.#onError);

    this.#applySize();
  }

  render() {
    if (!this.#img) return;

    if (this.#img.getAttribute('src') !== this.src) {
      this.removeAttribute('data-loaded');
      this.removeAttribute('data-error');
      this.#img.src = this.src || '';
    }

    this.#img.alt = this.alt || '';
    this.#applySize();
  }

  #applySize() {
    if (this.width)  this.style.width  = this.width;
    if (this.height) this.style.height = this.height;
  }

  #onLoad = () => {
    this.setAttribute('data-loaded', '');
    this.removeAttribute('data-error');
  };

  #onError = () => {
    if (this.fallback && this.#img.src !== this.fallback) {
      this.#img.src = this.fallback;
    } else {
      this.setAttribute('data-error', '');
    }
  };

  disconnected() {
    if (this.#img) {
      this.#img.removeEventListener('load', this.#onLoad);
      this.#img.removeEventListener('error', this.#onError);
    }
    this.#img = null;
    this.#skeleton = null;
  }
}
