"use client";
import { useEffect, useMemo } from "react";
import { useEditContext } from "../client/editContext";
import { normalizeItemId, useNodeIndicators, } from "../tree-indicators/useNodeIndicators";
const PUBLISHED_PROVIDER_ID = "published";
const PUBLISHED_PROVIDERS = [PUBLISHED_PROVIDER_ID];
export function collectSharedDatasourceIds(component, ids = new Set()) {
    if (!component)
        return ids;
    if (component.isShared && component.datasourceItem?.id) {
        ids.add(component.datasourceItem.id);
    }
    for (const placeholder of component.placeholders ?? []) {
        for (const child of placeholder.components ?? []) {
            collectSharedDatasourceIds(child, ids);
        }
    }
    return ids;
}
/**
 * Publish-state lookup for the shared datasources on a page.
 *
 * Fetches the "published" tree indicator for each shared component's
 * datasource item and refreshes when a publish job finishes or a shared
 * datasource is edited.
 */
export function useSharedComponentPublishState(page, language) {
    const editContext = useEditContext();
    // Keep the array identity stable across page-model rebuilds so the
    // indicator hook only refetches when the set of datasources changes.
    const idsKey = useMemo(() => Array.from(collectSharedDatasourceIds(page?.rootComponent))
        .sort()
        .join("|"), [page?.rootComponent]);
    const nodeIds = useMemo(() => (idsKey ? idsKey.split("|") : []), [idsKey]);
    const { indicators, refresh } = useNodeIndicators({
        nodeIds,
        visibleProviders: PUBLISHED_PROVIDERS,
        language: language ?? "en",
        enabled: nodeIds.length > 0 && !!language,
    });
    const addSocketMessageListener = editContext?.addSocketMessageListener;
    const itemsRepository = editContext?.itemsRepository;
    // Refetch when one of this user's publish jobs reaches a terminal state.
    useEffect(() => {
        if (!addSocketMessageListener || nodeIds.length === 0)
            return;
        const unsubscribe = addSocketMessageListener((message) => {
            if ((message.type === "operation:completed" ||
                message.type === "operation:failed") &&
                message.payload?.type === "publish-item") {
                refresh();
            }
        });
        return unsubscribe;
    }, [addSocketMessageListener, nodeIds.length, refresh]);
    // Refetch shared datasources that are edited (a new revision means the
    // published copy is stale).
    useEffect(() => {
        if (!itemsRepository?.subscribeItemsChanged || nodeIds.length === 0) {
            return;
        }
        const idSet = new Set(nodeIds.map(normalizeItemId));
        const unsubscribe = itemsRepository.subscribeItemsChanged((changes) => {
            const changedIds = changes
                .map((change) => change.item.id)
                .filter((id) => idSet.has(normalizeItemId(id)));
            if (changedIds.length > 0) {
                refresh(changedIds);
            }
        });
        return unsubscribe;
    }, [itemsRepository, nodeIds, refresh]);
    return useMemo(() => (datasourceItemId) => datasourceItemId
        ? indicators[normalizeItemId(datasourceItemId)]?.[PUBLISHED_PROVIDER_ID]
        : undefined, [indicators]);
}
//# sourceMappingURL=useSharedComponentPublishState.js.map