const channelName = "parhelia-editor-session-id-claims";
function createBrowserChannel() {
    if (typeof BroadcastChannel === "undefined")
        return null;
    return new BroadcastChannel(channelName);
}
/**
 * Claims a stored editor session id for this tab.
 *
 * Browsers copy sessionStorage into a duplicated/new child tab. Without this
 * handshake, both tabs reuse the copied id and alternately overwrite the same
 * server-side session's current item. Existing tabs answer probes for their id;
 * a colliding tab then creates a new id before EditorShell is mounted.
 */
export function claimEditorSessionId(initialSessionId, createSessionId, options) {
    const channel = (options?.createChannel ?? createBrowserChannel)();
    if (!channel) {
        return {
            resolvedSessionId: Promise.resolve(initialSessionId),
            updateSessionId: () => { },
            close: () => { },
        };
    }
    const claimantId = createSessionId();
    let currentSessionId = initialSessionId;
    let collisionDetected = false;
    let closed = false;
    let timer;
    channel.onmessage = (event) => {
        const message = event.data;
        if (!message ||
            message.sessionId !== currentSessionId ||
            typeof message.claimantId !== "string") {
            return;
        }
        if (message.type === "probe") {
            if (message.claimantId === claimantId)
                return;
            channel.postMessage({
                type: "occupied",
                sessionId: currentSessionId,
                claimantId: message.claimantId,
            });
        }
        else if (message.type === "occupied" &&
            message.claimantId === claimantId) {
            collisionDetected = true;
        }
    };
    const resolvedSessionId = new Promise((resolve) => {
        channel.postMessage({
            type: "probe",
            sessionId: currentSessionId,
            claimantId,
        });
        timer = setTimeout(() => {
            if (closed)
                return;
            if (collisionDetected)
                currentSessionId = createSessionId();
            resolve(currentSessionId);
        }, options?.settleMs ?? 75);
    });
    return {
        resolvedSessionId,
        updateSessionId: (sessionId) => {
            currentSessionId = sessionId;
        },
        close: () => {
            closed = true;
            if (timer)
                clearTimeout(timer);
            channel.close();
        },
    };
}
//# sourceMappingURL=sessionIdClaim.js.map