import idrefs from '../dom/idrefs';
import accessibleText from '../text/accessible-text';
import { nodeLookup } from '../../core/utils';

/**
 * Get the accessible name based on aria-labelledby
 *
 * @deprecated Do not use Element directly. Pass VirtualNode instead
 * @param {VirtualNode|Element} element
 * @param {Object} context
 * @property {Bool} inLabelledByContext Whether or not the lookup is part of aria-labelledby reference
 * @property {Bool} inControlContext Whether or not the lookup is part of a native label reference
 * @property {Element} startNode First node in accessible name computation
 * @property {Bool} debug Enable logging for formControlValue
 * @return {string} Concatenated text value for referenced elements
 */
function arialabelledbyText(element, context = {}) {
  const { vNode } = nodeLookup(element);
  if (vNode?.props.nodeType !== 1) {
    return '';
  }

  /**
   * Note: The there are significant difference in how many "leads" browsers follow.
   * - Firefox stops after the first IDREF, so it
   * 		doesn't follow aria-labelledby after a for:>ID ref.
   * - Chrome seems to just keep iterating no matter how many levels deep.
   * - AccName-AAM 1.1 suggests going one level deep, but to treat
   * 		each ref type separately.
   *
   * Axe-core's implementation behaves most closely like Firefox as it seems
   *  to be the common denominator. Main difference is that Firefox
   *  includes the value of form controls in addition to aria-label(s),
   *  something no other browser seems to do. Axe doesn't do that.
   */
  if (
    vNode.props.nodeType !== 1 ||
    context.inLabelledByContext ||
    context.inControlContext ||
    !vNode.attr('aria-labelledby')
  ) {
    return '';
  }

  const refs = idrefs(vNode, 'aria-labelledby').filter(elm => elm);
  return refs.reduce((accessibleName, elm) => {
    const accessibleNameAdd = accessibleText(elm, {
      // Prevent the infinite reference loop:
      inLabelledByContext: true,
      startNode: context.startNode || vNode,
      ...context
    });

    if (!accessibleName) {
      return accessibleNameAdd;
    } else {
      return `${accessibleName} ${accessibleNameAdd}`;
    }
  }, '');
}

export default arialabelledbyText;
