"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ViewSlot = void 0;
exports.triggersToScreens = triggersToScreens;
exports.stateToAction = stateToAction;
const href_1 = require("../link/href");
const sortRoutes_1 = require("../sortRoutes");
const useScreens_1 = require("../useScreens");
const Slot_1 = require("./Slot");
const constants_1 = require("../constants");
exports.ViewSlot = Slot_1.Slot;
function triggersToScreens(triggers, layoutRouteNode, linking, initialRouteName, parentTriggerMap, routeInfo, contextKey) {
    const configs = [];
    for (const trigger of triggers) {
        if (trigger.name in parentTriggerMap) {
            const parentTrigger = parentTriggerMap[trigger.name];
            throw new Error(`Trigger ${JSON.stringify({
                name: trigger.name,
                href: trigger.href,
            })} has the same name as parent trigger ${JSON.stringify({
                name: parentTrigger.name,
                href: parentTrigger.href,
            })}. Triggers must have unique names.`);
        }
        if (trigger.type === 'external') {
            configs.push(trigger);
            continue;
        }
        let resolvedHref = (0, href_1.resolveHref)(trigger.href);
        if (resolvedHref.startsWith('../')) {
            throw new Error('Trigger href cannot link to a parent directory');
        }
        const segmentsWithoutGroups = contextKey.split('/').filter((segment) => {
            return !(segment.startsWith('(') && segment.endsWith(')'));
        });
        resolvedHref = (0, href_1.resolveHrefStringWithSegments)(resolvedHref, {
            ...routeInfo,
            segments: segmentsWithoutGroups,
        }, { relativeToDirectory: true });
        let state = linking.getStateFromPath?.(resolvedHref, linking.config)?.routes[0];
        if (!state) {
            // This shouldn't occur, as you should get the global +not-found
            console.warn(`Unable to find screen for trigger ${JSON.stringify(trigger)}. Does this point to a valid screen?`);
            continue;
        }
        let routeState = state;
        if (routeState.name === constants_1.NOT_FOUND_ROUTE_NAME) {
            if (process.env.NODE_ENV !== 'production') {
                console.warn(`Tab trigger '${trigger.name}' has the href '${trigger.href}' which points to a +not-found route.`);
            }
            continue;
        }
        const targetStateName = layoutRouteNode.route || '__root';
        // The state object is the current state from the rootNavigator
        // We need to work out the state for just this trigger
        while (state?.state) {
            if (state.name === targetStateName)
                break;
            state = state.state.routes[state.state.index ?? state.state.routes.length - 1];
        }
        routeState = state.state?.routes[state.state.index ?? state.state.routes.length - 1] || state;
        const routeNode = layoutRouteNode.children.find((child) => child.route === routeState?.name);
        if (!routeNode) {
            console.warn(`Unable to find routeNode for trigger ${JSON.stringify(trigger)}. This might be a bug with Expo Router`);
            continue;
        }
        const duplicateTrigger = trigger.type === 'internal' &&
            configs.find((config) => {
                if (config.type === 'external') {
                    return false;
                }
                return config.routeNode.route === routeNode.route;
            });
        if (duplicateTrigger) {
            const duplicateTriggerText = `${JSON.stringify({ name: duplicateTrigger.name, href: duplicateTrigger.href })} and ${JSON.stringify({ name: trigger.name, href: trigger.href })}`;
            throw new Error(`A navigator cannot contain multiple trigger components that map to the same sub-segment. Consider adding a shared group and assigning a group to each trigger. Conflicting triggers:\n\t${duplicateTriggerText}.\nBoth triggers map to route ${routeNode.route}.`);
        }
        configs.push({
            ...trigger,
            href: resolvedHref,
            routeNode,
            action: stateToAction(state, layoutRouteNode.route),
        });
    }
    const sortFn = (0, sortRoutes_1.sortRoutesWithInitial)(initialRouteName);
    const sortedConfigs = configs.sort((a, b) => {
        // External routes should be last. They will eventually be dropped
        if (a.type === 'external' && b.type === 'external') {
            return 0;
        }
        else if (a.type === 'external') {
            return 1;
        }
        else if (b.type === 'external') {
            return -1;
        }
        return sortFn(a.routeNode, b.routeNode);
    });
    const children = [];
    const triggerMap = { ...parentTriggerMap };
    for (const [index, config] of sortedConfigs.entries()) {
        triggerMap[config.name] = { ...config, index };
        if (config.type === 'internal') {
            children.push((0, useScreens_1.routeToScreen)(config.routeNode));
        }
    }
    return {
        children,
        triggerMap,
    };
}
function stateToAction(state, startAtRoute) {
    const rootPayload = {};
    let payload = rootPayload;
    startAtRoute = startAtRoute === '' ? '__root' : startAtRoute;
    let foundStartingPoint = startAtRoute === undefined || !state?.state;
    while (state) {
        if (foundStartingPoint) {
            if (payload === rootPayload) {
                payload.name = state.name;
            }
            else {
                payload.screen = state.name;
            }
            payload.params = state.params ? { ...state.params } : {};
            state = state.state?.routes[state.state?.routes.length - 1];
            if (state) {
                payload.params ??= {};
                payload = payload.params;
            }
        }
        else {
            if (state.name === startAtRoute) {
                foundStartingPoint = true;
            }
            const nextState = state.state?.routes[state.state?.routes.length - 1];
            if (nextState) {
                state = nextState;
            }
        }
    }
    return {
        type: 'JUMP_TO',
        payload: rootPayload,
    };
}
//# sourceMappingURL=common.js.map