import { attributeAsString } from "@apple-media-services/media-api";
import { isNothing, isSome } from "@jet/environment";
import * as models from "../../../api/models";
import * as serverData from "../../../foundation/json-parsing/server-data";
import * as mediaDataStructure from "../../../foundation/media/data-structure";
import * as mediaRelationship from "../../../foundation/media/relationships";
import { seeAllArcadeGamesPageFlowAction } from "../../arcade/arcade-common";
import { pageRouter } from "../../builders/routing";
import { hrefToRoutableUrl } from "../../builders/url-mapping";
import { categoryArtworkData } from "../../categories";
import * as artworkBuilder from "../../content/artwork/artwork";
import * as content from "../../content/content";
import * as lockups from "../../lockups/lockups";
import * as metricsHelpersClicks from "../../metrics/helpers/clicks";
import * as metricsHelpersImpressions from "../../metrics/helpers/impressions";
import * as metricsHelpersLocation from "../../metrics/helpers/location";
import { areAppTagsEnabled } from "../../util/app-tags-util";
import * as lottery from "../../util/lottery";
import { GroupingShelfController } from "./grouping-shelf-controller";
import * as groupingShelfControllerCommon from "./grouping-shelf-controller-common";
export class GroupingRibbonBarShelfController extends GroupingShelfController {
    // region Constructors
    constructor() {
        super("GroupingRibbonBarShelfController");
        this.supportedFeaturedContentIds = new Set([556 /* groupingTypes.FeaturedContentID.AppStore_RibbonBarMarker */]);
    }
    // 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) {
        return await GroupingShelfController.secondaryGroupingShelfDataForShelfUrl(objectGraph, shelfUrl, shelfToken, parameters);
    }
    /**
     * 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) {
        return baseShelfToken;
    }
    // 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;
        const items = [];
        const shelf = new models.Shelf("ribbonBar");
        shelf.isHorizontal = true;
        const isSAGUpliftEnabledForCurrentUser = lottery.isFeatureEnabledForCurrentUser(objectGraph, objectGraph.bag.arcadeCategoryBarSAGUpliftDisplayRate);
        // Display See All Games facet when:
        // - This is an Arcade page AND
        // - This is the first render of the shelf AND
        // - Bag is enabled for current user
        if (shelfToken.isArcadePage && shelfToken.isFirstRender && isSAGUpliftEnabledForCurrentUser) {
            const seeAllGamesRibbonItem = GroupingRibbonBarShelfController.createSeeAllGamesRibbonItem(objectGraph, shelfToken.metricsPageInformation, shelfToken.metricsLocationTracker);
            items.push(seeAllGamesRibbonItem);
            metricsHelpersLocation.nextPosition(shelfToken.metricsLocationTracker);
        }
        // If we have any hydrated items stored in the token, it means we found an unhydrated priorized item. In this
        // case, we combine the initial hydrated items with the secondary hydrated items, and build the entire set
        // of ribbon items from this list. As we are manipulating the order, we also need to replace the original
        // shelf rather than merge.
        let combinedShelfContents = (_a = shelfData.shelfContents) !== null && _a !== void 0 ? _a : [];
        if (isSome(shelfToken.initialHydratedItems) && shelfToken.initialHydratedItems.length > 0) {
            combinedShelfContents = shelfToken.initialHydratedItems.concat(combinedShelfContents);
        }
        // Tracks the initial set of hydrated items from the initial shelf load. This will be stored in the shelf
        // token only if we find a prioritized item that is deferred.
        const initialHydratedItems = [];
        let isPrioritizedItemDeferred = false;
        for (const ribbonData of combinedShelfContents) {
            if (serverData.isNull(ribbonData.attributes) || groupingShelfControllerCommon.shouldDefer(shelfToken)) {
                shelfToken.isDeferring = true;
                shelfToken.remainingItems.push(ribbonData);
                if (GroupingRibbonBarShelfController.shouldPriorizeItemWithData(objectGraph, ribbonData)) {
                    isPrioritizedItemDeferred = true;
                }
                continue;
            }
            let isTextOnly = false;
            if (isSome(shelfToken.featuredContentData)) {
                const displayStyle = attributeAsString(shelfToken.featuredContentData, "displayStyle");
                isTextOnly = displayStyle === "textOnly";
            }
            const ribbonModel = GroupingRibbonBarShelfController.createRibbonItem(objectGraph, ribbonData, shelfToken.metricsPageInformation, shelfToken.metricsLocationTracker, isTextOnly, shelfToken, groupingParseContext);
            if (isSome(ribbonModel)) {
                if (GroupingRibbonBarShelfController.shouldPriorizeItemWithData(objectGraph, ribbonData)) {
                    items.unshift(ribbonModel);
                }
                else {
                    items.push(ribbonModel);
                }
                initialHydratedItems.push(ribbonData);
            }
            metricsHelpersLocation.nextPosition(shelfToken.metricsLocationTracker);
        }
        if (objectGraph.client.isiOS ||
            objectGraph.featureFlags.isEnabled("shelves_2_0_arcade") ||
            objectGraph.featureFlags.isEnabled("shelves_2_0_generic")) {
            shelf.items = items;
            if (isPrioritizedItemDeferred && initialHydratedItems.length > 0) {
                shelfToken.initialHydratedItems = initialHydratedItems;
            }
        }
        else {
            // Only set `shelf.items` if there are any `items` present
            // so that hydrated items reload when they are fetched.
            if (items.length > 0) {
                const ribbonBar = new models.RibbonBar(items);
                shelf.items = [ribbonBar];
            }
        }
        shelf.url = groupingShelfControllerCommon.createShelfTokenUrlIfNecessaryForShelf(objectGraph, shelf, shelfToken);
        return shelf;
    }
    // region Static Helpers
    static createRibbonItem(objectGraph, itemData, metricsPageInformation, metricsLocationTracker, isTextOnly, shelfToken, groupingParseContext) {
        var _a, _b, _c;
        const metricsOptions = {
            targetType: "facet",
            pageInformation: metricsPageInformation,
            locationTracker: metricsLocationTracker,
            recoMetricsData: mediaDataStructure.metricsFromMediaApiObject(itemData),
        };
        let metadata;
        if (itemData.type === "tags") {
            if (!areAppTagsEnabled(objectGraph, "grouping")) {
                return null;
            }
            metadata = groupingShelfControllerCommon.metadataForTag(objectGraph, itemData, shelfToken, metricsOptions);
        }
        else {
            metadata = groupingShelfControllerCommon.metadataForFCData(objectGraph, itemData, shelfToken, false, null, metricsOptions, groupingParseContext);
        }
        const metricsClickOptions = metricsHelpersClicks.clickOptionsForLockup(objectGraph, itemData, metricsOptions);
        metricsClickOptions.targetType = metricsOptions.targetType;
        const actionFromData = lockups.actionFromData(objectGraph, itemData, metricsClickOptions, shelfToken === null || shelfToken === void 0 ? void 0 : shelfToken.clientIdentifierOverride);
        const action = (_a = metadata === null || metadata === void 0 ? void 0 : metadata.action) !== null && _a !== void 0 ? _a : actionFromData;
        const editorialNotesName = (_b = content.editorialNotesFromData(objectGraph, itemData, "name")) !== null && _b !== void 0 ? _b : attributeAsString(itemData, "name");
        const title = (_c = metadata === null || metadata === void 0 ? void 0 : metadata.title) !== null && _c !== void 0 ? _c : editorialNotesName;
        const ribbonModel = new models.RibbonBarItem(title, action);
        // Setup Artwork
        const artworkDict = categoryArtworkData(objectGraph, itemData);
        let artwork;
        if (isTextOnly) {
            artwork = null;
        }
        else {
            if (isSome(artworkDict)) {
                artwork = content.artworkFromApiArtwork(objectGraph, artworkDict, {
                    useCase: 29 /* content.ArtworkUseCase.RibbonBarFacet */,
                });
            }
            else {
                let resource;
                if (shelfToken.isArcadePage) {
                    resource = "resource://arcade-ribbon-bar-fallback-icon";
                }
                else {
                    resource = "resource://appstore-ribbon-bar-fallback-icon";
                }
                artwork = artworkBuilder.createArtworkForResource(objectGraph, resource, 36, 36);
            }
        }
        ribbonModel.artwork = artwork;
        ribbonModel.accessibilityLabel = title;
        // Configure impressions
        const impressionOptions = metricsHelpersImpressions.impressionOptions(objectGraph, itemData, title, metricsOptions);
        metricsHelpersImpressions.addImpressionFields(objectGraph, ribbonModel, impressionOptions);
        if (!ribbonModel.isValid()) {
            return null;
        }
        return ribbonModel;
    }
    /// Creates and returns Arcade See All Games ribbon item.
    static createSeeAllGamesRibbonItem(objectGraph, metricsPageInformation, metricsLocationTracker) {
        const title = objectGraph.loc.string("Arcade.CategoryBar.AllGames.Title");
        const action = seeAllArcadeGamesPageFlowAction(objectGraph, "releaseDate", metricsPageInformation, metricsLocationTracker, title, "AllGames", "none", "facet");
        const ribbonModel = new models.RibbonBarItem(title, action);
        // Setup Artwork
        // To update this artwork, run `cat artwork.png | base64` and prefix with `data:image/png;base64,`.
        const resource = "data:image/png;base64, ";
        const artwork = artworkBuilder.createArtworkForResource(objectGraph, resource, 36, 36);
        ribbonModel.artwork = artwork;
        ribbonModel.accessibilityLabel = title;
        // Configure impressions
        const metricsOptions = {
            targetType: "facet",
            pageInformation: metricsPageInformation,
            locationTracker: metricsLocationTracker,
            recoMetricsData: null,
        };
        const impressionOptions = metricsHelpersImpressions.impressionOptionsForArcadeSeeAllGamesRibbonItem(metricsOptions);
        metricsHelpersImpressions.addImpressionFields(objectGraph, ribbonModel, impressionOptions);
        return ribbonModel;
    }
    static createTagsRibbonShelf(objectGraph, data) {
        const tagsData = mediaRelationship.relationshipViewsCollection(data, "categorizations");
        const ribbonBarShelf = new models.Shelf("ribbonFlow");
        const ribbonItems = [];
        for (const tagData of tagsData) {
            const name = attributeAsString(tagData, "name");
            let pageUrl = null;
            switch (tagData.type) {
                case "genres":
                    pageUrl = attributeAsString(tagData, "url");
                    break;
                case "tags":
                    const href = serverData.asString(tagData, "href");
                    pageUrl = hrefToRoutableUrl(objectGraph, href);
                    break;
                default:
                    break;
            }
            if (isNothing(pageUrl)) {
                continue;
            }
            const flowPage = objectGraph.required(pageRouter).fetchFlowPage(pageUrl);
            const flowAction = new models.FlowAction(flowPage);
            flowAction.pageUrl = pageUrl;
            if (isSome(name)) {
                const ribbonItem = new models.RibbonBarItem(name, flowAction);
                ribbonItems.push(ribbonItem);
            }
        }
        ribbonBarShelf.items = ribbonItems;
        ribbonBarShelf.isHorizontal = true;
        return ribbonBarShelf;
    }
    /**
     * Determines if an item should be given priority and moved to the front of the list.
     * @param objectGraph Current object graph
     * @param data The data for the item
     * @returns True if the item should be moved to the front of the list.
     */
    static shouldPriorizeItemWithData(objectGraph, data) {
        var _a, _b;
        const displayDeviceDrivenContent = (_b = (_a = objectGraph.userDefaults) === null || _a === void 0 ? void 0 : _a.bool("displayDeviceDrivenContent")) !== null && _b !== void 0 ? _b : false;
        return (displayDeviceDrivenContent &&
            objectGraph.bag.ribbonBarVisionEditorialItemIds.includes(data.id) &&
            objectGraph.bag.enableDeviceDrivenDiscoveryContent);
    }
}
//# sourceMappingURL=grouping-ribbon-bar-shelf-controller.js.map