import { debug } from '@sentry/core';
import { getReactNavigationIntegration, reactNavigationIntegration } from './reactnavigation';
export const INTEGRATION_NAME = 'ExpoRouter';
const POLL_INTERVAL_MS = 50;
const POLL_MAX_DURATION_MS = 5000;
/**
 * Integration that connects Expo Router with `reactNavigationIntegration` without
 * requiring the user to manually pass a `useNavigationContainerRef()` ref.
 *
 * @example
 * ```ts
 * Sentry.init({
 *   integrations: [Sentry.expoRouterIntegration()],
 * });
 * ```
 */
export const expoRouterIntegration = (options = {}) => {
    let pollTimer;
    const afterAllSetup = (client) => {
        var _a;
        const store = tryGetExpoRouterStore();
        if (!store) {
            // expo-router not installed
            return;
        }
        if (!store.navigationRef) {
            debug.warn(`${INTEGRATION_NAME} Found expo-router router-store but it does not expose a \`navigationRef\`. ` +
                `This likely means the installed expo-router version is incompatible with this integration.`);
            return;
        }
        // reuse the user's reactNavigationIntegration if they registered one manually.
        // Otherwise, create and add one.
        let reactNavigation = getReactNavigationIntegration(client);
        if (!reactNavigation) {
            reactNavigation = reactNavigationIntegration(options);
            client.addIntegration(reactNavigation);
        }
        const navigationRef = store.navigationRef;
        (_a = reactNavigation._setRouteOverrideProvider) === null || _a === void 0 ? void 0 : _a.call(reactNavigation, () => buildExpoRouterRouteOverride(store));
        if (navigationRef.current) {
            reactNavigation.registerNavigationContainer(navigationRef);
            return;
        }
        // Otherwise, poll until the Root Layout mounts and Expo Router sets `.current`.
        const startedAt = Date.now();
        const poll = () => {
            if (!navigationRef.current) {
                if (Date.now() - startedAt >= POLL_MAX_DURATION_MS) {
                    debug.warn(`${INTEGRATION_NAME} Timed out waiting for Expo Router navigation container.`);
                    pollTimer = undefined;
                    return;
                }
                pollTimer = setTimeout(poll, POLL_INTERVAL_MS);
                return;
            }
            reactNavigation === null || reactNavigation === void 0 ? void 0 : reactNavigation.registerNavigationContainer(navigationRef);
            pollTimer = undefined;
        };
        pollTimer = setTimeout(poll, POLL_INTERVAL_MS);
        client.on('close', () => {
            if (pollTimer !== undefined) {
                clearTimeout(pollTimer);
                pollTimer = undefined;
            }
        });
    };
    return {
        name: INTEGRATION_NAME,
        afterAllSetup,
    };
};
function tryGetExpoRouterStore() {
    var _a;
    try {
        // eslint-disable-next-line @typescript-eslint/no-var-requires
        const mod = require('expo-router/build/global-state/router-store');
        return (_a = mod === null || mod === void 0 ? void 0 : mod.store) !== null && _a !== void 0 ? _a : null;
    }
    catch (_b) {
        return null;
    }
}
/**
 * Builds a templated pathname from Expo Router's `segments`
 *
 * Examples:
 *   ['(tabs)', 'profile', '[id]']  -> '/profile/[id]'
 *   ['posts', '[...slug]']         -> '/posts/[...slug]'
 *   []                              -> '/'
 */
export function buildExpoRouterTemplatedPath(segments) {
    if (!segments || segments.length === 0) {
        return '/';
    }
    const filtered = segments.filter(s => !(s.startsWith('(') && s.endsWith(')')));
    return filtered.length === 0 ? '/' : `/${filtered.join('/')}`;
}
function buildExpoRouterRouteOverride(store) {
    var _a, _b;
    let info;
    try {
        info = (_a = store.getRouteInfo) === null || _a === void 0 ? void 0 : _a.call(store);
    }
    catch (_c) {
        return undefined;
    }
    if (!info) {
        return undefined;
    }
    const templatedPath = buildExpoRouterTemplatedPath(info.segments);
    return {
        templatedPath,
        concreteUrl: (_b = info.pathnameWithParams) !== null && _b !== void 0 ? _b : info.pathname,
        params: info.params,
    };
}
//# sourceMappingURL=expoRouterIntegration.js.map