import { clamp } from '@/utils/math';
import { IProgressPreloaderResource } from '../types';

/**
 * Retrieves the load progress of a custom resource element based on its attributes.
 */
function getLoaded(element: Element) {
  let loaded = parseInt(element.getAttribute('data-loaded') || '0', 10);
  loaded = Number.isNaN(loaded) ? 0 : clamp(loaded, 0, Infinity);

  return loaded;
}

/**
 * Preloads a custom resource element by recursively checking its load progress until the target progress is reached.
 */
export function preloadCustomElement(
  { id, weight }: IProgressPreloaderResource,
  onLoad: (loadedWeight: number) => void,
) {
  if (!(id instanceof Element)) {
    return;
  }

  // If the load progress has reached or exceeded the target, resolve the promise
  if (getLoaded(id) >= weight) {
    onLoad(weight);

    return;
  }

  // Set up a mutation observer to monitor changes in the 'data-loaded' attribute
  const observer = new MutationObserver(() => {
    const loaded = getLoaded(id);
    onLoad(loaded);

    if (loaded >= weight) {
      observer.disconnect();
    }
  });

  observer.observe(id, {
    attributes: true,
    attributeFilter: ['data-loaded'],
  });
}
