import { isSome } from "@jet/environment";
import * as models from "../../../api/models";
import * as serverData from "../../../foundation/json-parsing/server-data";
import * as mediaDataFetching from "../../../foundation/media/data-fetching";
import * as mediaDataStructure from "../../../foundation/media/data-structure";
import { fetchData } from "../../../foundation/media/network";
import * as mediaRelationship from "../../../foundation/media/relationships";
import * as appPromotionCommon from "../../app-promotions/app-promotions-common";
import * as metricsHelpersUtil from "../../metrics/helpers/util";
import * as onDevicePersonalization from "../../personalization/on-device-personalization";
import * as placeholders from "../../placeholders/placeholders";
import { addVariantParametersToRequestForItems } from "../../product-page/product-page-variants";
import * as refresh from "../../refresh/page-refresh-controller";
import { GroupingShelfController } from "./grouping-shelf-controller";
import * as groupingShelfControllerCommon from "./grouping-shelf-controller-common";
import { attributeAsBooleanOrFalse } from "../../../foundation/media/attributes";
import { ResponseMetadata } from "../../../foundation/network/network";
import { shelfTitleAttributePathForFeaturedContentId } from "./grouping-shelf-controller-common";
import * as mediaAttributes from "../../../foundation/media/attributes";
export class GroupingAppEventShelfController extends GroupingShelfController {
    // region Constructors
    constructor() {
        super("GroupingAppEventShelfController");
        this.supportedFeaturedContentIds = new Set([
            519 /* groupingTypes.FeaturedContentID.AppStore_AppEventsMarker */,
            518 /* groupingTypes.FeaturedContentID.AppStore_PersonalizedAppEventsMarker */,
        ]);
    }
    // endregion
    // region Shelf Creation Prerequisites
    /**
     * For a given mediaApiData extract the actual shelfContents array needed to render this shelf
     *
     * @param mediaApiData The outer shelfContents object containing the shelf contents
     */
    initialShelfDataFromGroupingMediaApiData(objectGraph, mediaApiData) {
        return { shelfContents: mediaRelationship.relationshipCollection(mediaApiData, "contents") };
    }
    /**
     * For a given url that this controller handles, we should return a promise that will result in the `ShelfData`
     * needed to render this shelf
     *
     * @param objectGraph The App Store dependency graph
     * @param shelfUrl The url that this controller handled on a secondary fetch
     * @param parameters The extracted parameters from the shelf url
     */
    async secondaryShelfDataForShelfUrl(objectGraph, shelfUrl, shelfToken, parameters) {
        var _a;
        if (((_a = shelfToken.recommendationsHref) === null || _a === void 0 ? void 0 : _a.length) > 0) {
            try {
                const mediaApiData = await GroupingShelfController.secondaryGroupingShelfMediaApiData(objectGraph, shelfUrl, shelfToken, parameters);
                const shelfResponseData = mediaDataStructure.dataFromDataContainer(objectGraph, mediaApiData);
                const shelfContents = this.initialShelfDataFromGroupingMediaApiData(objectGraph, shelfResponseData);
                shelfContents.responseTimingValues = mediaApiData[ResponseMetadata.timingValues];
                const title = mediaAttributes.attributeAsString(shelfResponseData, shelfTitleAttributePathForFeaturedContentId(objectGraph, shelfToken.featuredContentId));
                if (serverData.isDefinedNonNull(title) && (title === null || title === void 0 ? void 0 : title.length) > 0) {
                    shelfContents.shelfTitle = title;
                }
                return shelfContents;
            }
            catch {
                return { shelfContents: [] };
            }
        }
        else {
            const appEvents = [];
            const contingentItems = [];
            const offerItems = [];
            for (const remainingItem of shelfToken.remainingItems) {
                switch (remainingItem.type) {
                    case "contingent-items":
                        contingentItems.push(remainingItem);
                        break;
                    case "offer-items":
                        offerItems.push(remainingItem);
                        break;
                    case "app-events":
                        appEvents.push(remainingItem);
                        break;
                    default:
                        break;
                }
            }
            const appEventsRequest = new mediaDataFetching.Request(objectGraph, appEvents);
            addVariantParametersToRequestForItems(objectGraph, appEventsRequest, appEvents);
            const contingentItemsRequest = new mediaDataFetching.Request(objectGraph, contingentItems);
            addVariantParametersToRequestForItems(objectGraph, contingentItemsRequest, contingentItems);
            const offerItemsRequest = new mediaDataFetching.Request(objectGraph, offerItems);
            addVariantParametersToRequestForItems(objectGraph, offerItemsRequest, offerItems);
            const hydrationResults = await Promise.all([
                this.fetchRemainingItems(objectGraph, appEventsRequest),
                this.fetchRemainingItems(objectGraph, contingentItemsRequest),
                this.fetchRemainingItems(objectGraph, offerItemsRequest),
            ]);
            const hydratedDataMap = { ...hydrationResults[0], ...hydrationResults[1], ...hydrationResults[2] };
            const shelfContents = [];
            for (const remainingItem of shelfToken.remainingItems) {
                const data = hydratedDataMap[remainingItem.id];
                if (isSome(data)) {
                    shelfContents.push(data);
                }
            }
            groupingShelfControllerCommon.flushRequestedItemsFromShelfToken(shelfToken, new Set([...offerItemsRequest.ids, ...contingentItemsRequest.ids, ...appEventsRequest.ids]));
            return { shelfContents: shelfContents };
        }
    }
    async fetchRemainingItems(objectGraph, remainingItemsRequest) {
        const apiDataMap = {};
        const addDataToMap = (data) => {
            for (const item of data.data) {
                apiDataMap[item.id] = item;
            }
        };
        if (remainingItemsRequest.ids.size > 0) {
            groupingShelfControllerCommon.prepareGroupingShelfRequest(objectGraph, remainingItemsRequest);
            try {
                await fetchData(objectGraph, remainingItemsRequest).then((mediaApiData) => {
                    addDataToMap(mediaApiData);
                });
            }
            catch (fetchError) {
                objectGraph.console.error("Error fetching remaining items", remainingItemsRequest.ids);
            }
        }
        return apiDataMap;
    }
    /**
     * For a given mediaApiData create an updated shelf token that contains all the additional data for this specific shelf type
     *
     * @param objectGraph The App Store dependency graph
     * @param baseShelfToken The base grouping shelf token created by the grouping-controller
     * @param mediaApiData The outer data object containing the FC properties and data
     * @param groupingParseContext The parse context for the grouping page so far
     */
    shelfTokenFromBaseTokenAndMediaApiData(objectGraph, mediaApiData, baseShelfToken, groupingParseContext) {
        const shouldPersonalizeData = baseShelfToken.featuredContentId === 518 /* groupingTypes.FeaturedContentID.AppStore_PersonalizedAppEventsMarker */;
        let personalizedDataResult = null;
        const shelfData = this.initialShelfDataFromGroupingMediaApiData(objectGraph, mediaApiData);
        if (shouldPersonalizeData && serverData.isDefinedNonNullNonEmpty(shelfData.shelfContents)) {
            personalizedDataResult = this.personalizedDataResultFromDataItems(objectGraph, shelfData.shelfContents);
        }
        const appEventShelfToken = {
            ...baseShelfToken,
            shouldPersonalizeData: shouldPersonalizeData,
            personalizedDataResult: personalizedDataResult,
        };
        const hasContents = serverData.isDefinedNonNullNonEmpty(shelfData.shelfContents);
        const shelfPersonalizationAvailable = !attributeAsBooleanOrFalse(mediaApiData, "noPersonalizationAvailable");
        if (!hasContents && shelfPersonalizationAvailable) {
            appEventShelfToken.recommendationsHref = mediaApiData.href;
            appEventShelfToken.isValidRecommendationsShelf = true;
        }
        else {
            appEventShelfToken.isValidRecommendationsShelf = hasContents;
        }
        return appEventShelfToken;
    }
    // endregion
    // region Metrics
    /**
     * Return the shelf metrics options to use for this specific shelf. Using the base options from the grouping
     * page controller
     *
     * @param objectGraph The App Store dependency graph
     * @param shelfToken The shelf shelfToken for this current shelf creation request
     * @param baseMetricsOptions The minimum set of metrics options for this shelf, created by the
     * grouping page controller
     */
    shelfMetricsOptionsFromBaseMetricsOptions(objectGraph, shelfToken, baseMetricsOptions) {
        const shelfMetricsOptions = { ...baseMetricsOptions };
        if (serverData.isDefinedNonNullNonEmpty(shelfToken.personalizedDataResult)) {
            const recoMetricsData = metricsHelpersUtil.combinedRecoMetricsDataFromMetricsData(baseMetricsOptions.recoMetricsData, shelfToken.personalizedDataResult.processingType, null);
            shelfMetricsOptions.recoMetricsData = recoMetricsData;
        }
        return shelfMetricsOptions;
    }
    // endregion
    // region Shelf Creation
    /**
     *
     * @param objectGraph The App Store dependency graph
     * @param shelfToken The shelf shelfToken for this current shelf creation request
     * @param shelfData The media api shelfContents array for this shelf
     * @param groupingParseContext The parse context used to generate the grouping page on the initial page load,
     * this will be missing when this controller renders a secondary or incomplete shelf fetch.
     */
    _createShelf(objectGraph, shelfToken, shelfData, groupingParseContext) {
        var _a;
        if (!appPromotionCommon.appEventsAreEnabled(objectGraph)) {
            return null;
        }
        if (!shelfToken.isValidRecommendationsShelf) {
            return null;
        }
        const metricsOptions = {
            pageInformation: shelfToken.metricsPageInformation,
            locationTracker: shelfToken.metricsLocationTracker,
            recoMetricsData: shelfToken.metricsPageInformation.recoMetricsData,
        };
        // First personalize the data, as this may cause things to be re-ordered
        let sortedShelfContents = shelfData.shelfContents;
        // Only try to use the personalized data the first render, second renders the shelfContents has already been personalized
        if (serverData.isDefinedNonNullNonEmpty(shelfToken.personalizedDataResult) && shelfToken.isFirstRender) {
            sortedShelfContents = shelfToken.personalizedDataResult.personalizedData;
        }
        // Now find which items are hydrated, and add the rest to the token
        const hydratedShelfContents = [];
        for (const data of sortedShelfContents) {
            if (serverData.isNull(data.attributes) || groupingShelfControllerCommon.shouldDefer(shelfToken)) {
                shelfToken.isDeferring = true;
                shelfToken.remainingItems.push(data);
                continue;
            }
            hydratedShelfContents.push(data);
        }
        // Now create our shelf from the hydrated items
        const displayableAppEvents = appPromotionCommon.appPromotionsFromData(objectGraph, hydratedShelfContents, null, false, false, metricsOptions, false, true, shelfToken.isArcadePage, false);
        refresh.addNextPreferredContentRefreshDate(displayableAppEvents.nextAppEventPromotionStartDate, groupingParseContext === null || groupingParseContext === void 0 ? void 0 : groupingParseContext.refreshController);
        const appPromotions = displayableAppEvents.appPromotions;
        const shelfType = "appPromotion";
        const shelf = new models.Shelf(shelfType);
        shelf.isHorizontal = true;
        shelf.title = (_a = shelfData.shelfTitle) !== null && _a !== void 0 ? _a : shelfToken.title;
        shelf.items = appPromotions;
        const willHydrateShelfLater = serverData.isNullOrEmpty(shelf.items) && shelfToken.isFirstRender;
        if (willHydrateShelfLater && placeholders.placeholdersEnabled(objectGraph)) {
            placeholders.insertPlaceholdersIntoGenericPageShelf(objectGraph, shelf, shelfToken, shelfToken.featuredContentId);
        }
        shelf.url = groupingShelfControllerCommon.createShelfTokenUrlIfNecessaryForShelf(objectGraph, shelf, shelfToken);
        if (serverData.isNullOrEmpty(shelf.items) && serverData.isNullOrEmpty(shelf.url)) {
            return shelfToken.isFirstRender ? null : GroupingAppEventShelfController.makeHiddenShelf(shelfToken);
        }
        return shelf;
    }
    // region Helpers
    /**
     * Personalizes the input list of app event data items.
     * @param objectGraph
     * @param dataItems The array of app event data items
     */
    personalizedDataResultFromDataItems(objectGraph, dataItems) {
        // Collect the app IDs we are interested in
        const appIds = new Set();
        for (const data of dataItems) {
            const appId = serverData.asString(data, "meta.personalizationData.appId");
            if ((appId === null || appId === void 0 ? void 0 : appId.length) > 0) {
                appIds.add(appId);
            }
        }
        // Now personalize the data
        const personalizationDataContainer = onDevicePersonalization.personalizationDataContainerForAppIds(objectGraph, appIds);
        return onDevicePersonalization.personalizeDataItems(objectGraph, "groupingAppEvent", dataItems, false, personalizationDataContainer, null, null, null, true);
    }
    static makeHiddenShelf(shelfToken) {
        const hiddenShelf = new models.Shelf(shelfToken.shelfStyle);
        hiddenShelf.isHidden = true;
        return hiddenShelf;
    }
}
//# sourceMappingURL=grouping-app-event-shelf-controller.js.map