import { isNothing, isSome, unwrapOptional } from "@jet/environment/types/optional";
import * as models from "../../../api/models";
import * as filtering from "../../filtering";
import * as adLockups from "../../lockups/ad-lockups";
import * as lockups from "../../lockups/lockups";
import * as serverData from "../../../foundation/json-parsing/server-data";
import * as mediaAttributes from "../../../foundation/media/attributes";
import * as mediaDataStructure from "../../../foundation/media/data-structure";
import * as mediaRelationships from "../../../foundation/media/relationships";
import { searchLandingPageAdShelfIdentifier, searchLandingPagePositionInfo } from "../../ads/on-device-ad-stitch";
import { createArtworkForResource } from "../../content/artwork/artwork";
import * as content from "../../content/content";
import * as metricsHelpersPage from "../../metrics/helpers/page";
import * as metricsHelpersClicks from "../../metrics/helpers/clicks";
import * as metricsHelpersImpressions from "../../metrics/helpers/impressions";
import * as metricsHelpersLocation from "../../metrics/helpers/location";
import { createChartsCategoryShelf } from "../content/search-categories";
import { MediumAdLockupWithScreenshotsBackground, } from "../../../api/models";
import * as adStitch from "../../ads/ad-stitcher";
import * as adIncidents from "../../ads/ad-incident-recorder";
import * as searchShelves from "../content/search-shelves";
import { CollectionShelfDisplayStyle } from "../../editorial-pages/editorial-page-types";
import { buildBrick } from "../../editorial-pages/editorial-page-shelf-builder/editorial-page-collection-shelf-builder/editorial-page-brick-collection-shelf-builder";
import { iconFromData } from "../../content/content";
import * as searchHistoryShelf from "../shelves/search-history-shelf";
import { adLogger } from "../search-ads";
import { asString } from "../../../foundation/json-parsing/server-data";
import { addImpressionsFieldsToAd } from "../../metrics/helpers/impressions";
import { makeSearchResultsPageIntent } from "../../../api/intents/search-results-page-intent";
import { getLocale } from "../../locale";
import { actionFor } from "../../../foundation/runtime/action-provider";
import * as impressionDemotion from "../../personalization/on-device-impression-demotion";
import { applySearchAdMissedOpportunityToShelvesIfNeeded } from "../../ads/ad-common";
// #region Shelf Creation
export function firstShelfMarkerMatchingUseCase(dataContainer, searchLandingPageContext, onDevicePersonalizationUseCase) {
    const shelfData = dataContainer.data;
    if (serverData.isNullOrEmpty(shelfData)) {
        return null;
    }
    for (const dataItem of shelfData) {
        if (serverData.isNullOrEmpty(dataItem)) {
            continue;
        }
        /// Skip shelf if not valid for context page type.
        const shelfMetadata = serverData.asDictionary(dataItem, "meta");
        const shelfPageType = pageTypeFromShelfMetaCategory(shelfMetadata === null || shelfMetadata === void 0 ? void 0 : shelfMetadata.category);
        if (shelfPageType !== searchLandingPageContext.pageType) {
            continue;
        }
        if (onDevicePersonalizationUseCase ===
            mediaAttributes.attributeAsString(dataItem, "onDevicePersonalizationUseCase")) {
            return dataItem;
        }
    }
    return null;
}
/**
 * Inserts the shelf made from the data container into the grouping parse context
 * @param objectGraph The App Store dependency graph
 * @param dataContainer The response data
 * @param searchLandingPageContext The context for the search page, e.g. landing or focus
 */
export function insertShelvesIntoSearchPageContext(objectGraph, dataContainer, searchLandingPageContext) {
    var _a;
    const shelfData = dataContainer.data;
    if (serverData.isNullOrEmpty(shelfData)) {
        return;
    }
    // index to compare adPositionInfo
    let builtShelves = 0;
    const supportsFocus = objectGraph.bag.mediaAPISearchFocusEnabled && isSome(searchLandingPageContext.pageType);
    for (const dataItem of shelfData) {
        if (serverData.isNullOrEmpty(dataItem)) {
            continue;
        }
        /// Skip shelf if not valid for context page type.
        if (supportsFocus) {
            const shelfMetadata = serverData.asDictionary(dataItem, "meta");
            const shelfPageType = pageTypeFromShelfMetaCategory(shelfMetadata === null || shelfMetadata === void 0 ? void 0 : shelfMetadata.category);
            if (isSome(shelfPageType) && shelfPageType !== searchLandingPageContext.pageType) {
                continue;
            }
        }
        const adMeta = dataContainer.meta || null;
        const adUnitShelf = shelfFromAdStitcher(objectGraph, searchLandingPageContext, builtShelves, adMeta);
        if (isSome(adUnitShelf)) {
            searchLandingPageContext.shelves.push(adUnitShelf);
            metricsHelpersLocation.nextPosition(searchLandingPageContext.metricsLocationTracker);
        }
        /// Get the necessary metadata for the shelf
        const shelfKind = mediaAttributes.attributeAsString(dataItem, "contentKind");
        const shelfAttributes = searchShelves.shelfAttributesFromData(objectGraph, dataItem, shelfKind);
        const shelfContext = searchLandingPageShelfContext(objectGraph, dataItem, shelfAttributes, searchLandingPageContext, shelfKind);
        /// Push the shelf content location so each shelf has the correct parent and starting index
        metricsHelpersLocation.pushContentLocation(objectGraph, shelfContext.metricsOptions, (_a = shelfAttributes.title) !== null && _a !== void 0 ? _a : "");
        /// Create the shelf
        const shelf = createShelf(objectGraph, dataItem, searchLandingPageContext, shelfContext, shelfAttributes, shelfKind);
        /// Pop the shelf location
        metricsHelpersLocation.popLocation(searchLandingPageContext.metricsLocationTracker);
        /// If the shelf is empty, skip it
        if (serverData.isNullOrEmpty(shelf)) {
            continue;
        }
        /// Add impressions for the shelf
        metricsHelpersImpressions.addImpressionFields(objectGraph, shelf, shelfContext.metricsOptions);
        applySearchAdMissedOpportunityToShelvesIfNeeded(objectGraph, [shelf], "searchLanding", shelfContext.metricsOptions.id, searchLandingPageContext.metricsPageInformation);
        /// Add the shelf to the page context for processing later
        searchLandingPageContext.shelves.push(shelf);
        builtShelves += 1;
        /// Make sure each shelf is represented by its own impressions index position
        metricsHelpersLocation.nextPosition(searchLandingPageContext.metricsLocationTracker);
    }
}
function pageTypeFromShelfMetaCategory(category) {
    switch (category) {
        case "search-landing":
            return searchShelves.SearchPageType.Landing;
        case "search-focus":
            return searchShelves.SearchPageType.Focus;
        default:
            return undefined;
    }
}
/**
 * Creates the appropriate shelf for the shelf's type
 * @param objectGraph The App Store Object Graph
 * @param data The data representing this shelf
 * @param pageContext The context for the shelf's page
 * @param shelfContext The context for the shelf
 * @param shelfAttributes The attributes for the shelf
 * @param shelfKind The content kind for the shelf
 * @returns A shelf if supported, null otherwise
 */
function createShelf(objectGraph, data, pageContext, shelfContext, shelfAttributes, shelfKind) {
    switch (shelfKind) {
        case models.SearchLandingPageContentKind.Suggestion:
            if (objectGraph.client.isVision || objectGraph.client.isWeb) {
                return createSuggestedLinksShelf(objectGraph, data, pageContext, shelfAttributes, shelfContext);
            }
            else if (pageContext.pageType === searchShelves.SearchPageType.Focus) {
                return createSuggestedSearchesShelf(objectGraph, data, pageContext, shelfAttributes, shelfContext);
            }
            else {
                return createSuggestedLinkActionsShelf(objectGraph, data, pageContext, shelfAttributes, shelfContext);
            }
        case models.SearchLandingPageContentKind.CategoriesAndCharts:
            return createChartsCategoryShelf(objectGraph, data, false, shelfAttributes, pageContext, shelfContext);
        case models.SearchLandingPageContentKind.Apps:
            return createLockupsShelf(objectGraph, data, pageContext, shelfAttributes, shelfContext);
        case models.SearchLandingPageContentKind.EditorialCollection:
            if (objectGraph.client.isVision || objectGraph.client.isWeb) {
                return buildBrickShelf(objectGraph, data, pageContext, shelfAttributes, shelfContext);
            }
            else {
                return null;
            }
        default:
            return createShelfFromMarker(objectGraph, data, pageContext, shelfContext, shelfAttributes);
    }
}
/**
 * Creates the appropriate shelf for the shelf's type
 * @param objectGraph The App Store Object Graph
 * @param data The data representing this shelf
 * @param pageContext The context for the shelf's page
 * @param shelfContext The context for the shelf
 * @param shelfAttributes The attributes for the shelf
 * @returns A shelf if supported, null otherwise
 */
function createShelfFromMarker(objectGraph, data, pageContext, shelfContext, shelfAttributes) {
    if (data.type !== "search-recommendations-marker") {
        return null;
    }
    switch (mediaAttributes.attributeAsString(data, "onDevicePersonalizationUseCase")) {
        case "recentSearches":
            return searchHistoryShelf.createShelfWithContext(objectGraph, pageContext, shelfAttributes);
        default:
            return null;
    }
}
/**
 * Creates the appropriate shelf for the shelf's type
 * @param objectGraph The App Store Object Graph
 * @param data The data representing this shelf
 * @param pageContext The context for the shelf's page
 */
function createMediumAdLockupWithScreenshotsBackgroundShelf(objectGraph, data, pageContext) {
    var _a, _b, _c;
    const shelf = new models.Shelf("mediumAdLockupWithScreenshotsBackground");
    shelf.isHorizontal = false;
    const offerEnvironment = "dark";
    const offerStyle = "white";
    const metricsOptions = metricsHelpersImpressions.impressionOptions(objectGraph, data, asString(data.attributes.name), {
        pageInformation: pageContext.metricsPageInformation,
        locationTracker: pageContext.metricsLocationTracker,
        targetType: "card",
        recoMetricsData: mediaDataStructure.metricsFromMediaApiObject(data),
        isAdvert: adLockups.isAdvert(objectGraph, data),
    });
    metricsOptions.kind = "adItem";
    // Set up iAdInfo
    metricsOptions.pageInformation.iAdInfo.apply(objectGraph, data);
    const lockupOptions = {
        offerEnvironment: offerEnvironment,
        offerStyle: offerStyle,
        metricsOptions: {
            pageInformation: pageContext.metricsPageInformation,
            locationTracker: pageContext.metricsLocationTracker,
            recoMetricsData: mediaDataStructure.metricsFromMediaApiObject(data),
            isAdvert: adLockups.isAdvert(objectGraph, data),
            disableFastImpressionsForAds: true,
        },
        artworkUseCase: content.artworkUseCaseFromShelfStyle(objectGraph, "mediumAdLockupWithScreenshotsBackground"),
        canDisplayArcadeOfferButton: content.shelfContentTypeCanDisplayArcadeOfferButtons(objectGraph, "mediumAdLockupWithScreenshotsBackground"),
    };
    const videoConfiguration = {
        canPlayFullScreen: false,
        playbackControls: {},
    };
    let lockup = lockups.mixedMediaAdLockupFromData(objectGraph, data, lockupOptions, videoConfiguration, null, false);
    const platformScreenshots = lockup.screenshots[0];
    const templateString = adLockups.getTemplateTypeForMediumAdFromLockupWithScreenshots(platformScreenshots);
    pageContext.metricsPageInformation.iAdInfo.setTemplateType(templateString);
    const iconData = iconFromData(objectGraph, data, {
        useCase: 0 /* ArtworkUseCase.Default */,
        withJoeColorPlaceholder: true,
        overrideTextColorKey: "textColor2",
    });
    // Update the lockup value after setting the template type so that the value gets added to the lockup.
    lockup = lockups.mixedMediaAdLockupFromData(objectGraph, data, lockupOptions, videoConfiguration, null, false);
    if (objectGraph.props.enabled("advertSlotReporting")) {
        (_a = lockup.searchAdOpportunity) === null || _a === void 0 ? void 0 : _a.setTemplateType(templateString);
    }
    else {
        (_b = lockup.searchAd) === null || _b === void 0 ? void 0 : _b.setTemplateType(templateString);
    }
    const backgroundColor = iconData.backgroundColor;
    const secondaryTextColor = iconData.textColor;
    const mediumAd = new MediumAdLockupWithScreenshotsBackground(lockup, [platformScreenshots], true, secondaryTextColor, backgroundColor, (_c = objectGraph.bag.todayAdMediumLockupScreenshotsRiverSpeed) !== null && _c !== void 0 ? _c : 8);
    addImpressionsFieldsToAd(objectGraph, mediumAd, metricsOptions, metricsOptions.pageInformation.iAdInfo);
    mediumAd.clickAction = lockups.actionFromData(objectGraph, data, metricsOptions, null);
    shelf.items = [mediumAd];
    return shelf;
}
/**
 * Creates the appropriate shelf for the shelf's type
 * @param objectGraph The App Store Object Graph
 * @param data The data representing this shelf
 * @param pageContext The context for the shelf's page
 */
function createCondensedAdLockupWithIconBackgroundShelf(objectGraph, data, pageContext) {
    var _a, _b, _c;
    const shelf = new models.Shelf("condensedAdLockupWithIconBackground");
    shelf.isHorizontal = false;
    const offerEnvironment = "dark";
    const offerStyle = "white";
    const metricsOptions = metricsHelpersImpressions.impressionOptions(objectGraph, data, asString(data.attributes.name), {
        pageInformation: pageContext.metricsPageInformation,
        locationTracker: pageContext.metricsLocationTracker,
        targetType: "card",
        recoMetricsData: mediaDataStructure.metricsFromMediaApiObject(data),
        isAdvert: adLockups.isAdvert(objectGraph, data),
    });
    metricsOptions.kind = "adItem";
    // Set up iAdInfo
    metricsOptions.pageInformation.iAdInfo.apply(objectGraph, data);
    const lockupOptions = {
        offerEnvironment: offerEnvironment,
        offerStyle: offerStyle,
        metricsOptions: {
            pageInformation: pageContext.metricsPageInformation,
            locationTracker: pageContext.metricsLocationTracker,
            recoMetricsData: mediaDataStructure.metricsFromMediaApiObject(data),
            isAdvert: adLockups.isAdvert(objectGraph, data),
            disableFastImpressionsForAds: true,
        },
        artworkUseCase: content.artworkUseCaseFromShelfStyle(objectGraph, "condensedAdLockupWithIconBackground"),
        canDisplayArcadeOfferButton: content.shelfContentTypeCanDisplayArcadeOfferButtons(objectGraph, "condensedAdLockupWithIconBackground"),
    };
    (_a = pageContext.metricsPageInformation.iAdInfo) === null || _a === void 0 ? void 0 : _a.setTemplateType("APPLOCKUP");
    const videoConfiguration = {
        canPlayFullScreen: false,
        playbackControls: {},
    };
    const lockup = lockups.mixedMediaAdLockupFromData(objectGraph, data, lockupOptions, videoConfiguration, null, false);
    if (objectGraph.props.enabled("advertSlotReporting")) {
        (_b = lockup.searchAdOpportunity) === null || _b === void 0 ? void 0 : _b.setTemplateType("APPLOCKUP");
    }
    else {
        (_c = lockup.searchAd) === null || _c === void 0 ? void 0 : _c.setTemplateType("APPLOCKUP");
    }
    const condensedAd = new models.CondensedAdLockupWithIconBackground(lockup, lockup.icon);
    addImpressionsFieldsToAd(objectGraph, condensedAd, metricsOptions, metricsOptions.pageInformation.iAdInfo);
    shelf.items = [condensedAd];
    return shelf;
}
// #endregion
// #region Suggested Links/Actions Shelves
/**
 * Creates the suggested links shelf
 * @param objectGraph The App Store dependency graph
 * @param data The content items for the shelf
 * @param pageContext The context for the shelf's page
 * @param shelfAttributes The attributes for the shelf and its contents
 * @returns A shelf for the suggested links, or null if the shelf would be empty
 */
function createSuggestedLinkActionsShelf(objectGraph, data, pageContext, shelfAttributes, shelfContext) {
    var _a;
    const linkData = mediaRelationships.relationshipCollection(data, "contents");
    const items = [];
    const shelf = new models.Shelf("action");
    shelf.isHorizontal = false;
    shelf.title = shelfAttributes.title;
    shelf.presentationHints = { isWidthConstrained: true };
    for (const [linkIndex, link] of linkData.entries()) {
        const metricsBase = {
            targetType: "link",
            pageInformation: pageContext.metricsPageInformation,
            locationTracker: pageContext.metricsLocationTracker,
        };
        const searchAdAction = trendingSearchLinkActionFromData(objectGraph, link, pageContext, shelfAttributes);
        if (serverData.isNull(searchAdAction) || serverData.isNull(searchAdAction.action)) {
            continue;
        }
        metricsHelpersImpressions.addImpressionFields(objectGraph, searchAdAction.action, {
            ...metricsBase,
            kind: "link",
            softwareType: null,
            title: searchAdAction.action.title,
            id: `${linkIndex}`,
            idType: "sequential",
        });
        items.push(searchAdAction);
        metricsHelpersLocation.nextPosition(pageContext.metricsLocationTracker);
    }
    if (serverData.isNullOrEmpty(items)) {
        return null;
    }
    shelf.items = items;
    if (serverData.isNumber((_a = shelfAttributes.displayStyle) === null || _a === void 0 ? void 0 : _a.layoutSize)) {
        shelf.contentsMetadata = {
            type: "searchLandingTrendingSection",
            numberOfColumns: shelfAttributes.displayStyle.layoutSize,
        };
    }
    else if (objectGraph.client.isPhone || objectGraph.client.isPad) {
        shelf.contentsMetadata = {
            type: "searchLandingTrendingSection",
            numberOfColumns: items.length >= 6 ? 2 : 1,
        };
    }
    return shelf;
}
/**
 * Creates the suggested searches shelf for the focus page.
 * @param objectGraph The App Store dependency graph
 * @param data The content items for the shelf
 * @param pageContext The context for the shelf's page
 * @param shelfAttributes The attributes for the shelf and its contents
 * @returns A shelf for the suggested links, or null if the shelf would be empty
 */
function createSuggestedSearchesShelf(objectGraph, data, pageContext, shelfAttributes, shelfContext) {
    var _a, _b, _c;
    const linkData = mediaRelationships.relationshipCollection(data, "contents");
    if (isNothing(linkData)) {
        return null;
    }
    const items = [];
    const shelf = new models.Shelf("singleColumnList");
    shelf.isHorizontal = false;
    shelf.title = shelfAttributes.title;
    shelf.presentationHints = { isWidthConstrained: true };
    for (const [linkIndex, link] of linkData.entries()) {
        const searchTerm = mediaAttributes.attributeAsString(link, "searchTerm");
        if (isNothing(searchTerm) || searchTerm.length === 0) {
            continue; // search term is required
        }
        const displayTerm = (_a = mediaAttributes.attributeAsString(link, "displayTerm")) !== null && _a !== void 0 ? _a : searchTerm;
        const searchAction = createFocusPageSearchAction(objectGraph, displayTerm !== null && displayTerm !== void 0 ? displayTerm : "", searchTerm !== null && searchTerm !== void 0 ? searchTerm : "", undefined, pageContext.metricsLocationTracker, "suggested", undefined, /// MAINTAINER'S NOTE: In the future, we could use this to attribute the suggestion source to the search result fetch.
        pageContext.metricsPageInformation, (_b = shelfAttributes.searchLandingItemDisplayStyle) !== null && _b !== void 0 ? _b : undefined);
        if (isNothing(searchAction) || serverData.isNullOrEmpty(searchAction)) {
            continue;
        }
        metricsHelpersImpressions.addImpressionFields(objectGraph, searchAction, {
            targetType: "link",
            pageInformation: pageContext.metricsPageInformation,
            locationTracker: pageContext.metricsLocationTracker,
            kind: "link",
            softwareType: null,
            title: (_c = searchAction.title) !== null && _c !== void 0 ? _c : "",
            id: `${linkIndex}`,
            idType: "sequential",
        });
        items.push(searchAction);
        metricsHelpersLocation.nextPosition(pageContext.metricsLocationTracker);
    }
    if (serverData.isNullOrEmpty(items)) {
        return null;
    }
    shelf.items = items;
    return shelf;
}
/**
 * Creates the suggested links shelf
 * @param objectGraph The App Store dependency graph
 * @param data The content items for the shelf
 * @param pageContext The context for the shelf's page
 * @param shelfAttributes The attributes for the shelf and its contents
 * @returns A shelf for the suggested links, or null if the shelf would be empty
 */
function createSuggestedLinksShelf(objectGraph, data, pageContext, shelfAttributes, shelfContext) {
    var _a;
    const linkData = mediaRelationships.relationshipCollection(data, "contents");
    const links = [];
    const shelf = new models.Shelf("searchLink");
    shelf.isHorizontal = false;
    shelf.title = shelfAttributes.title;
    shelf.presentationHints = { isWidthConstrained: true };
    metricsHelpersImpressions.addImpressionFields(objectGraph, shelf, shelfContext.metricsOptions);
    for (const [linkIndex, link] of linkData.entries()) {
        const metricsBase = {
            targetType: "link",
            pageInformation: pageContext.metricsPageInformation,
            locationTracker: pageContext.metricsLocationTracker,
        };
        const searchLink = trendingSearchLinkFromData(objectGraph, link, pageContext, shelfAttributes);
        metricsHelpersImpressions.addImpressionFields(objectGraph, searchLink, {
            ...metricsBase,
            kind: "link",
            softwareType: null,
            title: searchLink.clickAction.title,
            id: `${linkIndex}`,
            idType: "sequential",
        });
        if (serverData.isNullOrEmpty(searchLink)) {
            continue;
        }
        links.push(searchLink);
        metricsHelpersLocation.nextPosition(pageContext.metricsLocationTracker);
    }
    if (serverData.isNullOrEmpty(links)) {
        return null;
    }
    shelf.items = links;
    if (serverData.isNumber((_a = shelfAttributes.displayStyle) === null || _a === void 0 ? void 0 : _a.layoutSize)) {
        shelf.contentsMetadata = {
            type: "searchLandingTrendingSection",
            numberOfColumns: shelfAttributes.displayStyle.layoutSize,
        };
    }
    else if (objectGraph.client.isPhone) {
        shelf.contentsMetadata = {
            type: "searchLandingTrendingSection",
            numberOfColumns: links.length >= 6 ? 2 : 1,
        };
    }
    return shelf;
}
/**
 * Creates a suggestion link action for the link data
 * NOTE: This is legacy and the newer SLP protocol uses `trendingSearchLinkFromData`
 * @param objectGraph The App Store dependency graph
 * @param link The data for an individual suggestion link
 * @param pageContext The page context for the search link
 * @param shelfAttributes The attributes for the shelf and its contents
 * @returns An action representing the suggestion link
 */
function trendingSearchLinkActionFromData(objectGraph, link, pageContext, shelfAttributes) {
    var _a, _b;
    /// We should always have search term, but not necessarily displayTerm.
    const searchTerm = mediaAttributes.attributeAsString(link, "searchTerm");
    if (isNothing(searchTerm) || searchTerm.length === 0) {
        return null;
    }
    const displayTerm = (_a = mediaAttributes.attributeAsString(link, "displayTerm")) !== null && _a !== void 0 ? _a : searchTerm;
    /// MAINTAINER'S NOTE: In the future, we could use this to attribute the suggestion source to the search result fetch.
    const searchAction = new models.SearchAction(displayTerm, searchTerm, null, "suggested", undefined, undefined);
    searchAction.artwork = createArtworkForSearchAction((_b = shelfAttributes.searchLandingItemDisplayStyle) !== null && _b !== void 0 ? _b : undefined, objectGraph);
    metricsHelpersClicks.addEventsToSearchAction(objectGraph, searchAction, "button", pageContext.metricsLocationTracker);
    return isSome(searchAction) ? new models.SearchAdAction(searchAction) : null;
}
/**
 * Creates a search action
 * @param objectGraph The App Store dependency graph
 * @param searchTerm The term to search for
 * @param entity The entity to scope the search to, e.g. apps, stories, arcade
 * @param metricsLocationTracker The metrics location tracker
 * @param origin The source the search was fired from
 * @param isFocusPage Whether the origin is in context of the focus page
 * @param displayStyle The style to display the action item
 * @returns An action representing a search
 */
export function createFocusPageSearchAction(objectGraph, title, searchTerm, entity, metricsLocationTracker, origin, source, metricsPageInformation = undefined, displayStyle) {
    if (serverData.isNullOrEmpty(searchTerm)) {
        return null;
    }
    // For Search Focus Page, text uses primary color and icon uses secondary color (instead of tintColor).
    const searchAction = new models.SearchAction(title, searchTerm, null, origin, entity !== null && entity !== void 0 ? entity : undefined, source, []);
    searchAction.artwork = createArtworkForSearchAction(displayStyle, objectGraph);
    metricsHelpersClicks.addEventsToSearchAction(objectGraph, searchAction, "button", metricsLocationTracker, metricsPageInformation);
    return searchAction;
}
function createArtworkForSearchAction(displayStyle, objectGraph) {
    var _a;
    if ((displayStyle === null || displayStyle === void 0 ? void 0 : displayStyle.iconKind) === models.SearchLandingPageShelfItemIconKind.Symbol && ((_a = displayStyle === null || displayStyle === void 0 ? void 0 : displayStyle.iconKind) === null || _a === void 0 ? void 0 : _a.length)) {
        return createArtworkForResource(objectGraph, `systemimage://${displayStyle.iconSymbol}`);
    }
    else if (objectGraph.client.isPhone || objectGraph.client.isVision) {
        return createArtworkForResource(objectGraph, "systemimage://magnifyingglass");
    }
    return undefined;
}
/**
 * Creates a suggestion link action for the link data
 * @param objectGraph The App Store dependency graph
 * @param link The data for an individual suggestion link
 * @param pageContext The page context for the search link
 * @param shelfAttributes The attributes for the shelf and its contents
 * @returns An action representing the suggestion link
 */
function trendingSearchLinkFromData(objectGraph, link, pageContext, shelfAttributes) {
    var _a, _b, _c;
    const searchTerm = mediaAttributes.attributeAsString(link, "searchTerm");
    if (isNothing(searchTerm) || searchTerm.length === 0) {
        return null;
    }
    const displayTerm = (_a = mediaAttributes.attributeAsString(link, "displayTerm")) !== null && _a !== void 0 ? _a : searchTerm; /// we should always have search term, but not necessarily displayTerm
    let searchAction;
    if (objectGraph.client.isWeb) {
        const intent = makeSearchResultsPageIntent({
            ...getLocale(objectGraph),
            origin: "suggested",
            term: displayTerm,
            platform: (_b = objectGraph.activeIntent) === null || _b === void 0 ? void 0 : _b.previewPlatform,
        });
        searchAction = unwrapOptional(actionFor(intent, objectGraph));
    }
    else {
        searchAction = new models.SearchAction(displayTerm, displayTerm, null, "suggested");
        metricsHelpersClicks.addEventsToSearchAction(objectGraph, searchAction, "button", pageContext.metricsLocationTracker);
    }
    const artwork = createArtworkForSearchAction((_c = shelfAttributes.searchLandingItemDisplayStyle) !== null && _c !== void 0 ? _c : undefined, objectGraph);
    return new models.SearchLink(displayTerm, searchAction, artwork, null);
}
// #endregion
// #region Discover Lockups Shelves
/**
 * Creates a shelf composed of lockups
 * @param objectGraph The App Store Object Graph
 * @param data The data representing this lockups shelf
 * @param pageContext The page context for the shelf
 * @param shelfAttributes The attributes for the shelf
 * @param shelfContext The context for the shelf
 * @returns A lockups shelf if any lockups could be made
 */
function createLockupsShelf(objectGraph, data, pageContext, shelfAttributes, shelfContext) {
    var _a, _b, _c, _d, _e;
    const filterType = 80894 /* filtering.Filter.All */;
    const items = [];
    let hasAdLockup = false;
    let shelfData = initialShelfContentsFromData(data);
    // Set metadata
    const shelf = new models.Shelf(shelfContext.shelfStyle);
    shelf.isHorizontal = false;
    shelf.title = shelfAttributes.title;
    if (objectGraph.client.isVision) {
        shelf.shouldFilterApps = !mediaAttributes.attributeAsBooleanOrFalse(data, "doNotFilter");
    }
    else {
        shelf.shouldFilterApps = false;
    }
    shelf.filteringExcludedItems = shelfContext.filteringExcludedItems;
    // Stitch First Position Ad (only if lockup array is nonempty)
    if (serverData.isDefinedNonNullNonEmpty(shelfData)) {
        const adLockup = lockupFromAdStitcher(objectGraph, pageContext, shelfContext);
        if (adLockup && adLockup instanceof models.Lockup) {
            hasAdLockup = true;
            items.push(adLockup);
            metricsHelpersLocation.nextPosition(pageContext.metricsLocationTracker);
            shelfData = shelfData.filter((shelfItem) => shelfItem.id !== adLockup.adamId); // Filter dupe
        }
    }
    // Determines whether all apps are displayed on SLP suggested apps shelf.
    const hasDisplayCount = isSome(shelfAttributes.displayCount);
    // If on device personalization is available, we need to personalize the data items. This reorders the shelf.
    if (serverData.isDefinedNonNullNonEmpty(shelfData)) {
        shelfData = impressionDemotion.personalizeDataItems(shelfData, (_a = pageContext.recoImpressionData) !== null && _a !== void 0 ? _a : {}, (_c = (_b = shelfContext.metricsOptions) === null || _b === void 0 ? void 0 : _b.recoMetricsData) !== null && _c !== void 0 ? _c : {});
    }
    // Build Lockups
    for (const lockupData of shelfData) {
        // If we encounter a type of app-events, this means they have been incorrectly programmed,
        // and we should throw the shelf away.
        if (lockupData.type === "app-events") {
            return null;
        }
        if (serverData.isNull(lockupData.attributes)) {
            continue;
        }
        // Filter out unwanted content
        if (filtering.shouldFilter(objectGraph, lockupData, filterType)) {
            continue;
        }
        const lockup = lockupFromData(objectGraph, lockupData, pageContext, shelfContext);
        if (lockup) {
            items.push(lockup);
            metricsHelpersLocation.nextPosition(pageContext.metricsLocationTracker);
        }
    }
    if (hasDisplayCount) {
        // number of apps displayed on SLP suggested shelf
        const displayCount = shelfAttributes.displayCount;
        shelf.items = items.slice(0, displayCount);
    }
    else {
        shelf.items = items;
    }
    if (hasDisplayCount) {
        const seeAllShelf = new models.Shelf(shelfContext.shelfStyle);
        if (hasAdLockup) {
            // Ad is the first item in array so we are dropping it here.
            seeAllShelf.items = items.splice(1, items.length - 1);
        }
        else {
            seeAllShelf.items = items;
        }
        // Setup Page
        const seeAllPage = new models.GenericPage([seeAllShelf]);
        seeAllPage.title = shelf.title;
        // Setup action
        const seeAllAction = new models.FlowAction("page");
        seeAllAction.pageUrl = shelfAttributes.seeAllLink;
        seeAllAction.title = objectGraph.loc.string("ACTION_SEE_ALL");
        seeAllAction.pageData = seeAllPage;
        // Connect action
        shelf.seeAllAction = seeAllAction;
        // Metrics
        metricsHelpersClicks.addClickEventToSeeAllAction(objectGraph, seeAllAction, seeAllAction.pageUrl, {
            pageInformation: pageContext.metricsPageInformation,
            locationTracker: pageContext.metricsLocationTracker,
        });
        const seeAllPageInformation = metricsHelpersPage.pageInformationForRoom(objectGraph, data.id);
        metricsHelpersPage.addMetricsEventsToPageWithInformation(objectGraph, seeAllPage, seeAllPageInformation);
    }
    // Honor A/B treatment for using horizontal shelf for suggested apps, which may have an optional rowsPerColumn defined.
    // NOTE: Client will choose an appropriate `rowsPerColumn` at display time, if not provided by server.
    if (((_d = shelfAttributes.displayStyle) === null || _d === void 0 ? void 0 : _d.layout) === "horizontal" /* models.GenericSearchPageShelfDisplayStyleLayout.Horizontal */) {
        shelf.isHorizontal = true;
        shelf.rowsPerColumn = (_e = shelfAttributes.displayStyle) === null || _e === void 0 ? void 0 : _e.layoutSize;
    }
    return shelf;
}
/**
 * Create a lockup for shelfContents to display within a grouping shelf
 * @param objectGraph
 * @param lockupData shelfContents to create lockup for.
 * @param pageContext The page context for the lockup
 * @param shelfContext The shelf context for the lockup
 */
function lockupFromData(objectGraph, lockupData, pageContext, shelfContext) {
    if (serverData.isNullOrEmpty(lockupData)) {
        return null;
    }
    if (shelfContext.shelfStyle !== "smallLockup") {
        return null;
    }
    let offerStyle = null;
    if (serverData.isDefinedNonNull(shelfContext.shelfBackground) &&
        (shelfContext.shelfBackground.type === "color" || shelfContext.shelfBackground.type === "interactive")) {
        offerStyle = "white";
    }
    // Create the lockup
    const lockupOptions = {
        metricsOptions: {
            pageInformation: pageContext.metricsPageInformation,
            locationTracker: pageContext.metricsLocationTracker,
            recoMetricsData: mediaDataStructure.metricsFromMediaApiObject(lockupData),
            isAdvert: adLockups.isAdvert(objectGraph, lockupData),
        },
        artworkUseCase: content.artworkUseCaseFromShelfStyle(objectGraph, shelfContext.shelfStyle),
        offerStyle: offerStyle,
        canDisplayArcadeOfferButton: content.shelfContentTypeCanDisplayArcadeOfferButtons(objectGraph, shelfContext.shelfStyle),
        isContainedInPreorderExclusiveShelf: false,
        shouldHideArcadeHeader: false,
    };
    const lockup = lockups.lockupFromData(objectGraph, lockupData, lockupOptions);
    if (serverData.isNull(lockup) || !lockup.isValid()) {
        return null;
    }
    return lockup;
}
/**
 * Performs `lockupFromData`, but additional with Ad stitch related side-effects.
 * @param objectGraph The AppStore dependency graph
 * @param pageContext The page context for the ad lockup
 * @param shelfContext The shelf context for the ad lockup
 */
function lockupFromAdStitcher(objectGraph, pageContext, shelfContext) {
    const task = adStitch.consumeTask(pageContext.adStitcher, shelfContext.adPositionInfo);
    if (serverData.isNull(task)) {
        return null; // no task for position
    }
    // Try to create lockup
    const lockupData = task.data;
    try {
        const lockup = lockupFromData(objectGraph, lockupData, pageContext, shelfContext);
        if (serverData.isDefinedNonNull(lockup)) {
            shelfContext.filteringExcludedItems = [lockupData.id];
        }
        else {
            adIncidents.recordLockupFromDataFailed(objectGraph, pageContext.adIncidentRecorder, lockupData);
        }
        return lockup;
    }
    catch (error) {
        adLogger(objectGraph, `Failed to create SLP ad lockup: ${error}`);
        adIncidents.recordLockupFromDataFailed(objectGraph, pageContext.adIncidentRecorder, lockupData);
        return null;
    }
}
// #endregion
// #region Brick Shelves
function buildBrickShelf(objectGraph, data, pageContext, shelfAttributes, shelfContext) {
    const items = [];
    const shelf = new models.Shelf("brick");
    shelf.isHorizontal = mediaAttributes.attributeAsString(data, "layoutDirection") === "Horizontal";
    const shelfContents = mediaRelationships.relationshipCollection(data, "contents");
    for (const itemData of shelfContents) {
        const metricsOptions = {
            ...shelfContext.metricsOptions,
            targetType: "brickMedium",
            recoMetricsData: mediaDataStructure.metricsFromMediaApiObject(itemData),
        };
        // Using the location tracker from the context will cause positions to be unintentionally incremented
        // by the lockup builder. Since we're only extracting icons we won't use the lockup metrics, so we can
        // pass in a new, unused, location tracker instead.
        const lockupMetricsOptions = {
            pageInformation: metricsOptions.pageInformation,
            locationTracker: metricsHelpersLocation.newLocationTracker(),
        };
        const brick = buildBrick(objectGraph, itemData, CollectionShelfDisplayStyle.BrickMedium, metricsOptions, lockupMetricsOptions);
        brick.clickAction = createPrimaryActionForComponentFromData(objectGraph, itemData, shelfContext);
        if (!brick.isValid()) {
            continue;
        }
        items.push(brick);
        metricsHelpersLocation.nextPosition(shelfContext.metricsOptions.locationTracker);
    }
    shelf.title = shelfAttributes.title;
    shelf.items = items;
    return shelf;
}
export function createPrimaryActionForComponentFromData(objectGraph, data, shelfContext) {
    const clickOptions = createBrickClickOptionsFromData(objectGraph, data, shelfContext);
    const primaryAction = lockups.actionFromData(objectGraph, data, clickOptions, null);
    return primaryAction;
}
function createBrickClickOptionsFromData(objectGraph, data, shelfContext) {
    const clickOptions = {
        ...shelfContext.metricsOptions,
        id: data.id,
        targetType: "brickMedium",
    };
    return clickOptions;
}
// #endregion
// #region Shelf Data Extraction
/**
 * Gets the initial raw shelf contents from the MAPI data object
 * @param mediaApiData The raw MAPI data
 * @returns A collection of data objects representing a shelf's contents
 */
function initialShelfContentsFromData(mediaApiData) {
    const shelfContents = mediaRelationships.relationship(mediaApiData, "contents");
    return shelfContents === null || shelfContents === void 0 ? void 0 : shelfContents.data;
}
// #endregion
// #region Context Generators
/**
 * Performs either `createMediumAdLockupWithScreenshotsBackgroundShelf` or `createCondensedAdLockupWithIconBackgroundShelf
 * depending on the format defined in adDisplayStyle, but with Ad stitch related side-effects.
 * @param objectGraph The AppStore dependency graph
 * @param pageContext The page context for the ad lockup
 * @param builtShelves The index of the current shelf
 * @param adMeta The SearchLandingPageAdMeta which includes adDisplayStyle
 */
function shelfFromAdStitcher(objectGraph, pageContext, builtShelves, adMeta) {
    var _a;
    const task = adStitch.consumeTask(pageContext.adStitcher, {
        shelfIdentifier: searchLandingPageAdShelfIdentifier,
        slot: builtShelves,
    });
    if (serverData.isNull(task)) {
        return null; // no task for position
    }
    const adData = task.data;
    try {
        switch ((_a = adMeta === null || adMeta === void 0 ? void 0 : adMeta.adDisplayStyle) === null || _a === void 0 ? void 0 : _a.format) {
            case "medium":
                return createMediumAdLockupWithScreenshotsBackgroundShelf(objectGraph, adData, pageContext);
            case "condensed":
                return createCondensedAdLockupWithIconBackgroundShelf(objectGraph, adData, pageContext);
            default:
                adIncidents.recordLockupFromDataFailed(objectGraph, pageContext.adIncidentRecorder, adData);
                return null;
        }
    }
    catch (error) {
        adLogger(objectGraph, `Failed to create SLP ad shelf: ${error}`);
        adIncidents.recordLockupFromDataFailed(objectGraph, pageContext.adIncidentRecorder, adData);
        return null;
    }
}
/**
 * Generates a shelf context for a search landing page shelf
 * @param objectGraph The App Store Object Graph
 * @param data The shelf's data object
 * @param shelfAttributes The shelf's attribtues
 * @param pageContext The context for the page containing the shelf
 * @param shelfContentKind The type of content the shelf contains
 * @returns A shelf context for a search landing page shelf
 */
function searchLandingPageShelfContext(objectGraph, data, shelfAttributes, pageContext, shelfContentKind = null) {
    const baseShelfContext = searchShelves.baseShelfContext(objectGraph, data, shelfAttributes, pageContext);
    switch (shelfContentKind) {
        case models.SearchLandingPageContentKind.Apps:
            return {
                ...baseShelfContext,
                shelfStyle: "smallLockup",
                adPositionInfo: searchLandingPagePositionInfo,
            };
        default:
            return baseShelfContext;
    }
}
// #endregion
//# sourceMappingURL=search-landing-shelf-controller.js.map