/**
 * Player-height spacer observer.
 *
 * The audio player docks `position: fixed` to the viewport bottom, so it sits
 * outside normal flow and would overlap page content. A spacer div in the layout
 * reserves the equivalent space — but the player's height is not constant: it
 * reflows across the four breakpoints and grows when an error banner appears. A
 * static height can't track that, so we mirror the player's live border-box
 * height into the `--player-height` custom property on :root and let the spacer
 * read it. One observer at a time, re-pointed on each `observe` call; the var
 * resets to 0 on `unobserve` (player minimized / disposed) so the spacer
 * collapses.
 */

const HEIGHT_VAR = '--player-height';
let observer: ResizeObserver | null = null;

function writeHeight(px: number): void {
    // Round up so sub-pixel heights never leave a hairline of overlap.
    document.documentElement.style.setProperty(HEIGHT_VAR, `${Math.ceil(px)}px`);
}

export function observe(element: Element): void {
    unobserve();
    if (!element) return;

    observer = new ResizeObserver(entries => {
        const entry = entries[0];
        if (!entry) return;
        // Prefer the border-box measurement; fall back to contentRect on the
        // (older) engines that don't populate borderBoxSize.
        const box = entry.borderBoxSize?.[0];
        writeHeight(box ? box.blockSize : entry.contentRect.height);
    });
    observer.observe(element);

    // Seed synchronously so the spacer is correct on this frame, before the
    // first ResizeObserver callback fires.
    writeHeight(element.getBoundingClientRect().height);
}

export function unobserve(): void {
    observer?.disconnect();
    observer = null;
    writeHeight(0);
}
