"use strict";
Object.defineProperty(exports, "__esModule", {
    value: true
});
function _export(target, all) {
    for(var name in all)Object.defineProperty(target, name, {
        enumerable: true,
        get: all[name]
    });
}
_export(exports, {
    collectMetadata: function() {
        return collectMetadata;
    },
    resolveMetadata: function() {
        return resolveMetadata;
    },
    accumulateMetadata: function() {
        return accumulateMetadata;
    }
});
const _defaultmetadata = require("./default-metadata");
const _resolveopengraph = require("./resolvers/resolve-opengraph");
const _resolvetitle = require("./resolvers/resolve-title");
const _utils = require("./generate/utils");
const _clientreference = require("../client-reference");
const _appdirmodule = require("../../server/lib/app-dir-module");
const _interopdefault = require("../interop-default");
const _resolvebasics = require("./resolvers/resolve-basics");
const _resolveicons = require("./resolvers/resolve-icons");
const _tracer = require("../../server/lib/trace/tracer");
const _constants = require("../../server/lib/trace/constants");
const _constants1 = require("../../shared/lib/constants");
function mergeStaticMetadata(metadata, staticFilesMetadata) {
    if (!staticFilesMetadata) return;
    const { icon , apple , openGraph , twitter , manifest  } = staticFilesMetadata;
    if (icon || apple) {
        metadata.icons = {
            icon: icon || [],
            apple: apple || []
        };
    }
    if (twitter) {
        const resolvedTwitter = (0, _resolveopengraph.resolveTwitter)({
            ...metadata.twitter,
            images: twitter
        }, metadata.metadataBase);
        metadata.twitter = resolvedTwitter;
    }
    if (openGraph) {
        const resolvedOpenGraph = (0, _resolveopengraph.resolveOpenGraph)({
            ...metadata.openGraph,
            images: openGraph
        }, metadata.metadataBase);
        metadata.openGraph = resolvedOpenGraph;
    }
    if (manifest) {
        metadata.manifest = manifest;
    }
    return metadata;
}
// Merge the source metadata into the resolved target metadata.
function merge({ target , source , staticFilesMetadata , titleTemplates , options  }) {
    // If there's override metadata, prefer it otherwise fallback to the default metadata.
    const metadataBase = typeof (source == null ? void 0 : source.metadataBase) !== "undefined" ? source.metadataBase : target.metadataBase;
    for(const key_ in source){
        const key = key_;
        switch(key){
            case "title":
                {
                    target.title = (0, _resolvetitle.resolveTitle)(source.title, titleTemplates.title);
                    break;
                }
            case "alternates":
                {
                    target.alternates = (0, _resolvebasics.resolveAlternates)(source.alternates, metadataBase, {
                        pathname: options.pathname
                    });
                    break;
                }
            case "openGraph":
                {
                    target.openGraph = (0, _resolveopengraph.resolveOpenGraph)(source.openGraph, metadataBase);
                    if (target.openGraph) {
                        target.openGraph.title = (0, _resolvetitle.resolveTitle)(target.openGraph.title, titleTemplates.openGraph);
                    }
                    break;
                }
            case "twitter":
                {
                    target.twitter = (0, _resolveopengraph.resolveTwitter)(source.twitter, metadataBase);
                    if (target.twitter) {
                        target.twitter.title = (0, _resolvetitle.resolveTitle)(target.twitter.title, titleTemplates.twitter);
                    }
                    break;
                }
            case "verification":
                target.verification = (0, _resolvebasics.resolveVerification)(source.verification);
                break;
            case "viewport":
                {
                    target.viewport = (0, _resolvebasics.resolveViewport)(source.viewport);
                    break;
                }
            case "icons":
                {
                    target.icons = (0, _resolveicons.resolveIcons)(source.icons);
                    break;
                }
            case "appleWebApp":
                target.appleWebApp = (0, _resolvebasics.resolveAppleWebApp)(source.appleWebApp);
                break;
            case "appLinks":
                target.appLinks = (0, _resolvebasics.resolveAppLinks)(source.appLinks);
                break;
            case "robots":
                {
                    target.robots = (0, _resolvebasics.resolveRobots)(source.robots);
                    break;
                }
            case "themeColor":
                {
                    target.themeColor = (0, _resolvebasics.resolveThemeColor)(source.themeColor);
                    break;
                }
            case "archives":
            case "assets":
            case "bookmarks":
            case "keywords":
                {
                    target[key] = (0, _utils.resolveAsArrayOrUndefined)(source[key]);
                    break;
                }
            case "authors":
                {
                    target[key] = (0, _utils.resolveAsArrayOrUndefined)(source.authors);
                    break;
                }
            // directly assign fields that fallback to null
            case "applicationName":
            case "description":
            case "generator":
            case "creator":
            case "publisher":
            case "category":
            case "classification":
            case "referrer":
            case "colorScheme":
            case "itunes":
            case "formatDetection":
            case "manifest":
                // @ts-ignore TODO: support inferring
                target[key] = source[key] || null;
                break;
            case "other":
                target.other = Object.assign({}, target.other, source.other);
                break;
            case "metadataBase":
                target.metadataBase = metadataBase;
                break;
            default:
                break;
        }
    }
    mergeStaticMetadata(target, staticFilesMetadata);
}
async function getDefinedMetadata(mod, props, route) {
    // Layer is a client component, we just skip it. It can't have metadata exported.
    // Return early to avoid accessing properties error for client references.
    if ((0, _clientreference.isClientReference)(mod)) {
        return null;
    }
    return (mod.generateMetadata ? (parent)=>(0, _tracer.getTracer)().trace(_constants.ResolveMetadataSpan.generateMetadata, {
            spanName: `generateMetadata ${route}`,
            attributes: {
                "next.page": route
            }
        }, ()=>mod.generateMetadata(props, parent)) : mod.metadata) || null;
}
async function collectStaticImagesFiles(metadata, props, type) {
    var _ref;
    if (!(metadata == null ? void 0 : metadata[type])) return undefined;
    const iconPromises = metadata[type].map(async (imageModule)=>(0, _interopdefault.interopDefault)(await imageModule(props)));
    return (iconPromises == null ? void 0 : iconPromises.length) > 0 ? (_ref = await Promise.all(iconPromises)) == null ? void 0 : _ref.flat() : undefined;
}
async function resolveStaticMetadata(components, props) {
    const { metadata  } = components;
    if (!metadata) return null;
    const [icon, apple, openGraph, twitter] = await Promise.all([
        collectStaticImagesFiles(metadata, props, "icon"),
        collectStaticImagesFiles(metadata, props, "apple"),
        collectStaticImagesFiles(metadata, props, "openGraph"),
        collectStaticImagesFiles(metadata, props, "twitter")
    ]);
    const staticMetadata = {
        icon,
        apple,
        openGraph,
        twitter,
        manifest: metadata.manifest
    };
    return staticMetadata;
}
async function collectMetadata({ tree , metadataItems: array , props , route  }) {
    const [mod, modType] = await (0, _appdirmodule.getLayoutOrPageModule)(tree);
    if (modType) {
        route += `/${modType}`;
    }
    const staticFilesMetadata = await resolveStaticMetadata(tree[2], props);
    const metadataExport = mod ? await getDefinedMetadata(mod, props, route) : null;
    array.push([
        metadataExport,
        staticFilesMetadata
    ]);
}
async function resolveMetadata({ tree , parentParams , metadataItems , treePrefix =[] , getDynamicParamFromSegment , searchParams  }) {
    const [segment, parallelRoutes, { page  }] = tree;
    const currentTreePrefix = [
        ...treePrefix,
        segment
    ];
    const isPage = typeof page !== "undefined";
    // Handle dynamic segment params.
    const segmentParam = getDynamicParamFromSegment(segment);
    /**
   * Create object holding the parent params and current params
   */ const currentParams = // Handle null case where dynamic param is optional
    segmentParam && segmentParam.value !== null ? {
        ...parentParams,
        [segmentParam.param]: segmentParam.value
    } : parentParams;
    const layerProps = {
        params: currentParams,
        ...isPage && {
            searchParams
        }
    };
    await collectMetadata({
        tree,
        metadataItems,
        props: layerProps,
        route: currentTreePrefix// __PAGE__ shouldn't be shown in a route
        .filter((s)=>s !== _constants1.PAGE_SEGMENT_KEY).join("/")
    });
    for(const key in parallelRoutes){
        const childTree = parallelRoutes[key];
        await resolveMetadata({
            tree: childTree,
            metadataItems,
            parentParams: currentParams,
            treePrefix: currentTreePrefix,
            searchParams,
            getDynamicParamFromSegment
        });
    }
    return metadataItems;
}
async function accumulateMetadata(metadataItems, options) {
    const resolvedMetadata = (0, _defaultmetadata.createDefaultMetadata)();
    const resolvers = [];
    const generateMetadataResults = [];
    let titleTemplates = {
        title: null,
        twitter: null,
        openGraph: null
    };
    // Loop over all metadata items again, merging synchronously any static object exports,
    // awaiting any static promise exports, and resolving parent metadata and awaiting any generated metadata
    let resolvingIndex = 0;
    for(let i = 0; i < metadataItems.length; i++){
        const [metadataExport, staticFilesMetadata] = metadataItems[i];
        let metadata = null;
        if (typeof metadataExport === "function") {
            if (!resolvers.length) {
                for(let j = i; j < metadataItems.length; j++){
                    const [preloadMetadataExport] = metadataItems[j];
                    // call each `generateMetadata function concurrently and stash their resolver
                    if (typeof preloadMetadataExport === "function") {
                        generateMetadataResults.push(preloadMetadataExport(new Promise((resolve)=>{
                            resolvers.push(resolve);
                        })));
                    }
                }
            }
            const resolveParent = resolvers[resolvingIndex];
            const generatedMetadata = generateMetadataResults[resolvingIndex++];
            // In dev we clone and freeze to prevent relying on mutating resolvedMetadata directly.
            // In prod we just pass resolvedMetadata through without any copying.
            const currentResolvedMetadata = process.env.NODE_ENV === "development" ? Object.freeze(require("next/dist/compiled/@edge-runtime/primitives/structured-clone").structuredClone(resolvedMetadata)) : resolvedMetadata;
            // This resolve should unblock the generateMetadata function if it awaited the parent
            // argument. If it didn't await the parent argument it might already have a value since it was
            // called concurrently. Regardless we await the return value before continuing on to the next layer
            resolveParent(currentResolvedMetadata);
            metadata = generatedMetadata instanceof Promise ? await generatedMetadata : generatedMetadata;
        } else if (metadataExport !== null && typeof metadataExport === "object") {
            // This metadataExport is the object form
            metadata = metadataExport;
        }
        merge({
            options,
            target: resolvedMetadata,
            source: metadata,
            staticFilesMetadata,
            titleTemplates
        });
        // If the layout is the same layer with page, skip the leaf layout and leaf page
        // The leaf layout and page are the last two items
        if (i < metadataItems.length - 2) {
            var _resolvedMetadata_title, _resolvedMetadata_openGraph, _resolvedMetadata_openGraph_title, _resolvedMetadata_twitter, _resolvedMetadata_twitter_title;
            titleTemplates = {
                title: ((_resolvedMetadata_title = resolvedMetadata.title) == null ? void 0 : _resolvedMetadata_title.template) || null,
                openGraph: ((_resolvedMetadata_openGraph = resolvedMetadata.openGraph) == null ? void 0 : (_resolvedMetadata_openGraph_title = _resolvedMetadata_openGraph.title) == null ? void 0 : _resolvedMetadata_openGraph_title.template) || null,
                twitter: ((_resolvedMetadata_twitter = resolvedMetadata.twitter) == null ? void 0 : (_resolvedMetadata_twitter_title = _resolvedMetadata_twitter.title) == null ? void 0 : _resolvedMetadata_twitter_title.template) || null
            };
        }
    }
    return resolvedMetadata;
}

//# sourceMappingURL=resolve-metadata.js.map