(function (root, factory) {
  if (typeof module === 'object' && module.exports) module.exports = factory;
  else root.createMobileTaskDock = factory;
})(typeof self !== 'undefined' ? self : this, function createMobileTaskDock(options) {
  const nav = options.nav;
  const buttons = options.buttons;
  const overlays = options.overlays || [];
  let launcher = null;
  let wasHidden = false;

  function select(name) {
    if (!buttons[name]) return false;
    Object.entries(buttons).forEach(([key, button]) => {
      if (key === name) button.setAttribute('aria-current', 'page');
      else button.removeAttribute('aria-current');
    });
    return true;
  }

  function refreshVisibility() {
    const hidden = overlays.some(overlay => overlay.open || overlay.classList.contains('open'));
    nav.hidden = hidden;
    if (options.sessionHud) {
      if (hidden) options.sessionHud.setAttribute('data-overlay-hidden', 'true');
      else options.sessionHud.removeAttribute('data-overlay-hidden');
    }
    if (wasHidden && !hidden && launcher) launcher.focus();
    wasHidden = hidden;
  }

  function openQueues() {
    if (!options.queueSheet || options.queueSheet.open) return;
    options.queueSheet.showModal();
  }

  function closeQueues(returnToToday = false) {
    options.queueSheet?.open && options.queueSheet.close();
    if (returnToToday) options.detour?.()?.finishDetour();
  }

  function start() {
    Object.entries(buttons).forEach(([name, button]) => {
      button.addEventListener('click', event => {
        launcher = event.currentTarget;
        select(name);
        if (name === 'queues') options.detour?.()?.beginDetour(name);
        options.actions?.[name]?.();
        if (name === 'queues' && options.queueSheet) openQueues();
      });
    });
    if (options.queueSheet) {
      options.queueClose?.addEventListener('click', () => closeQueues(true));
      options.queueSheet.addEventListener('cancel', event => {
        event.preventDefault();
        closeQueues(true);
      });
      options.queueSheet.addEventListener('close', () => buttons.queues?.focus());
      Object.entries(options.queueRows || {}).forEach(([name, row]) => {
        row.addEventListener('click', () => {
          closeQueues();
          options.onSelectQueue?.(name, row);
        });
      });
    }
    options.observe(refreshVisibility, overlays);
    refreshVisibility();
  }

  function updateWork(mode) {
    const text = {
      continue:'Continue', resume:'Resume', start:'Start', plan:'Plan', find:'Find',
      prepare:'Prepare', 'prepare-resume':'Resume prep',
      delivery:'Delivery', attention:'Attention', update:'Updates', agenda:'Agenda', filed:'Filed', later:'Later', draft:'Drafts',
    }[mode] || 'Work';
    const queue = ['Delivery', 'Attention', 'Updates', 'Agenda', 'Filed', 'Later', 'Drafts'].includes(text);
    if (options.workLabel) options.workLabel.textContent = text;
    const actionLabel = mode === 'prepare' ? 'Prepare Today' :
      mode === 'prepare-resume' ? 'Resume preparation' :
      queue ? (mode === 'update' ? 'Resume ' : 'Open ') + text :
      mode === 'find' ? 'Find work' : text + (mode === 'work' ? '' : ' Today');
    if (buttons.work) buttons.work.setAttribute('aria-label', actionLabel);
  }

  function updateAttention(count) {
    const total = Math.max(0, Number(count) || 0);
    const visible = total > 0;
    if (options.attentionBadge) {
      options.attentionBadge.textContent = String(total);
      options.attentionBadge.hidden = !visible;
    }
    if (buttons.attention) {
      buttons.attention.hidden = !visible;
      buttons.attention.setAttribute('aria-label', 'Attention, ' + total + ' items');
    }
    if (visible) nav.setAttribute('data-attention', 'true');
    else nav.removeAttribute('data-attention');
  }

  function updateQueues(counts) {
    const names = 'today agenda delivery attention update filed later draft'.split(' ');
    const normalized = Object.fromEntries(names.map(name => [name, Math.max(0, Number(counts?.[name]) || 0)]));
    const actionableNames = ['today', 'delivery', 'attention', 'update', 'filed', 'later', 'draft'];
    const active = actionableNames.reduce((total, name) => total + (normalized[name] > 0 ? 1 : 0), 0);
    Object.entries(options.queueCounts || {}).forEach(([name, element]) => {
      element.textContent = String(normalized[name] || 0);
    });
    options.queueRows?.update?.setAttribute(
      'aria-label', 'Updates, ' + normalized.update + ' unread conversations'
    );
    if (options.queueBadge) {
      options.queueBadge.textContent = active + ' active';
      options.queueBadge.hidden = active === 0;
    }
    if (options.deadlineBadge) {
      options.deadlineBadge.textContent = normalized.agenda + ' due';
      options.deadlineBadge.hidden = normalized.agenda === 0;
    }
    if (options.queueRows?.agenda) {
      if (normalized.agenda > 0) options.queueRows.agenda.setAttribute('data-deadlines', 'true');
      else options.queueRows.agenda.removeAttribute('data-deadlines');
    }
    const label = active === 0 && normalized.agenda === 0
      ? 'Queues: no active queues; no upcoming deadlines'
      : 'Queues: Today ' + normalized.today
        + ', Agenda ' + normalized.agenda + ' due'
        + ', Delivery ' + normalized.delivery
        + ', Attention ' + normalized.attention
        + ', Updates ' + normalized.update
        + ', Filed ' + normalized.filed
        + ', Later ' + normalized.later
        + ', Drafts ' + normalized.draft
        + '; ' + active + ' active ' + (active === 1 ? 'queue' : 'queues');
    buttons.queues?.setAttribute('aria-label', label);
  }

  return {start, select, refreshVisibility, updateAttention, updateQueues, updateWork};
});
