-- Toast notification behavior: auto-dismiss for non-alert levels,
-- sticky with manual close for alert level, hover pauses the timer.
-- See app/common/widgets/toast.html.jinja2 for the markup contract.

-- The dismiss-timer logic uses setTimeout/clearTimeout, which are JS
-- globals not directly expressible in hyperscript syntax. We dispatch
-- those through `js(el) ... end` escape blocks so the surrounding
-- behavior stays in idiomatic hyperscript.

def _toastScheduleDismiss(el)
  if no el then exit end
  if el.classList.contains('alert') then exit end
  if el.classList.contains('dismiss') then exit end
  js(el)
    const tid = setTimeout(() => {
      if (!el.classList.contains('dismiss')) {
        el.classList.add('dismiss');
        el.addEventListener('animationend', () => el.remove(), { once: true });
      }
    }, 5000);
    el.dataset.toastTimer = tid;
  end
end

def _toastClearTimer(el)
  if no el then exit end
  js(el)
    if (el.dataset.toastTimer) {
      clearTimeout(parseInt(el.dataset.toastTimer));
      delete el.dataset.toastTimer;
    }
  end
end

def dismissToast(el)
  if no el then exit end
  if el.classList.contains('dismiss') then exit end
  call _toastClearTimer(el)
  js(el)
    el.classList.add('dismiss');
    el.addEventListener('animationend', () => el.remove(), { once: true });
  end
end

-- Client-created alert toast for failures with no server-rendered response
-- (htmx 4xx/5xx and network errors — wired up in static/js/global.js).
-- Mirrors the toast.html.jinja2 markup contract. textContent, not `put into`,
-- so the message can never be interpreted as HTML.
def errorToast(message)
  set stack to #toast-stack
  if no stack then exit end
  make a <div.toast.alert/> called toast
  set toast's @role to 'alert'
  set toast's @aria-live to 'assertive'
  set toast's @data-script to 'install toastBehavior'
  set toast's textContent to message
  make a <button.toast-close/> called closeBtn
  set closeBtn's @type to 'button'
  set closeBtn's @aria-label to 'Dismiss'
  set closeBtn's @data-script to 'on click call dismissToast(closest .toast)'
  set closeBtn's textContent to '×'
  put closeBtn at the end of toast
  js(toast) _hyperscript.processNode(toast) end
  put toast at the end of stack
end

-- toastBehavior MUST stay the last feature in this file: hyperscript 0.9.91's
-- program parser silently drops every feature that follows a behavior
-- (verified against _hyperscript.parse; defs after a behavior never register).
behavior toastBehavior
  init call _toastScheduleDismiss(me)
  on mouseenter call _toastClearTimer(me)
  on mouseleave call _toastScheduleDismiss(me)
end
