import * as validation from "@jet/environment/json/validation";
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 mediaNetwork from "../../../foundation/media/network";
import * as mediaRelationship from "../../../foundation/media/relationships";
import { ResponseMetadata } from "../../../foundation/network/network";
import { Parameters, Path, Protocol } from "../../../foundation/network/url-constants";
import * as urls from "../../../foundation/network/urls";
import * as contentAttributes from "../../content/attributes";
import * as content from "../../content/content";
import * as flowPreview from "../../content/flow-preview";
import * as filtering from "../../filtering";
import * as lockups from "../../lockups/lockups";
import * as metricsHelpersClicks from "../../metrics/helpers/clicks";
import * as metricsHelpersImpressions from "../../metrics/helpers/impressions";
import { GroupingShelfController } from "./grouping-shelf-controller";
import * as groupingShelfControllerCommon from "./grouping-shelf-controller-common";
import { makeGameCenterHeader } from "../../arcade/arcade-common";
import { injectCrossfireFlowForGameCenter } from "./grouping-game-center-popular-with-your-friends-shelf-controller";
export class GroupingGameCenterContinuePlayingShelfController extends GroupingShelfController {
    // region Constructors
    constructor() {
        super("GroupingGameCenterContinuePlayingShelfController");
        this.batchGroupKey = "gameCenterContinuePlaying";
        this.supportedFeaturedContentIds = new Set([500 /* groupingTypes.FeaturedContentID.AppStore_ContinuePlayingMarker */]);
    }
    // endregion
    // region GroupingShelfController
    _supports(objectGraph, mediaApiData, featuredContentId, nativeGroupingShelfId) {
        return (super._supports(objectGraph, mediaApiData, featuredContentId, nativeGroupingShelfId) &&
            this.supportsVideoCardShelf(objectGraph, objectGraph.host.platform));
    }
    // endregion
    // region Shelf Builder
    shelfRoute(objectGraph) {
        return [
            ...super.shelfRoute(objectGraph),
            {
                protocol: Protocol.internal,
                path: `/${Path.grouping}/${Path.shelf}/{token}`,
                query: [Parameters.isGameCenterContinuePlayingShelf],
            },
        ];
    }
    // 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) {
        const startTime = Date.now();
        const maxNumberOfGames = this.maximumNumberOfRecentGamesToRequest();
        const recentlyPlayedGamesPromise = objectGraph.gameCenter.fetchRecentlyPlayedGamesWithinSeconds(this.gameCategoryFilter(shelfToken.gamesFilter), maxNumberOfGames, objectGraph.bag.recentlyPlayedGamesWindowInSeconds);
        return await recentlyPlayedGamesPromise.then(async (recentlyPlayedIds) => {
            const endTime = Date.now();
            objectGraph.console.log("grouping-gamecenter-builder: requestForContinuePlaying NATIVE took " +
                (endTime - startTime).toString(10) +
                " milliseconds.");
            let shelfDataPromise;
            if (recentlyPlayedIds.length === 0) {
                // One of the few exceptions where TS minifiers cannot derive data container type
                // without some help, in this case using explicit type for the value passed to promise.
                const emptyShelfData = { shelfContents: [] };
                return await Promise.resolve(emptyShelfData);
            }
            else {
                const request = new mediaDataFetching.Request(objectGraph)
                    .withIdsOfType(recentlyPlayedIds.slice(0, this.maximumNumberOfRecentGamesToShow()), "apps")
                    .includingAgeRestrictions();
                groupingShelfControllerCommon.prepareGroupingShelfRequest(objectGraph, request);
                shelfDataPromise = mediaNetwork
                    .fetchData(objectGraph, request, {})
                    .then((dataContainer) => {
                    const shelfData = {
                        shelfContents: dataContainer.data,
                        responseTimingValues: dataContainer[ResponseMetadata.timingValues],
                    };
                    return shelfData;
                });
            }
            return await shelfDataPromise;
        });
    }
    /**
     * 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;
    }
    incompleteShelfFetchStrategy(objectGraph) {
        return models.IncompleteShelfFetchStrategy.OnPageLoad;
    }
    // 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) {
        if (shelfToken.isFirstRender) {
            return this.pendingContinuePlayingForGrouping(objectGraph, shelfToken);
        }
        else {
            return this.continuePlayingShelfForGrouping(objectGraph, shelfData.shelfContents, shelfToken);
        }
    }
    pendingContinuePlayingForGrouping(objectGraph, shelfToken) {
        const shelf = this.continuePlayingShelfForGrouping(objectGraph, [], shelfToken);
        if (!shelf) {
            return null;
        }
        const groupingShelfUrl = urls.URL.from(groupingShelfControllerCommon.groupingShelfUrl(shelfToken));
        shelf.url = groupingShelfUrl.param(Parameters.isGameCenterContinuePlayingShelf, "true").build();
        shelf.batchGroup = this.batchGroupKey;
        return shelf;
    }
    continuePlayingShelfForGrouping(objectGraph, shelfContents, shelfToken) {
        return validation.context("continuePlayingShelfForGrouping", () => {
            const shelf = this.videoCardContinuePlayingShelf(objectGraph, shelfContents, shelfToken);
            shelf.mergeWhenFetched = false; // Always replace
            shelf.batchGroup = this.batchGroupKey;
            shelf.isHidden = shelf.items.length === 0;
            shelf.header = makeGameCenterHeader(objectGraph, objectGraph.loc.string("GameCenter.ContinuePlayingShelf.Title"), shelfToken.subtitle);
            return shelf;
        });
    }
    // endregion
    // region Video Card Shelf
    supportsVideoCardShelf(objectGraph, platform) {
        switch (platform) {
            case "iOS":
            case "tvOS":
            case "macOS":
                return true;
            default:
                return false;
        }
    }
    videoCardContinuePlayingShelf(objectGraph, dataArray, shelfToken) {
        return validation.context("videoCardContinuePlayingShelf", () => {
            const shelf = new models.Shelf("videoCard");
            shelf.isHorizontal = true;
            shelf.batchGroup = this.batchGroupKey;
            const items = [];
            for (const data of dataArray) {
                // Filter out unwanted content
                if (filtering.shouldFilter(objectGraph, data)) {
                    continue;
                }
                const item = this.editorialSplashVideoCardForContinuePlaying(objectGraph, data, shelfToken);
                if (item) {
                    items.push(item);
                }
            }
            shelf.items = items;
            return shelf;
        });
    }
    /**
     * Create a `VideoCard` configured for CP Shelf.
     * Specifically, it uses:
     * - TV Top Shelf Static Image Still
     * - Arcade Product Page Uber Video
     *
     * @param objectGraph
     * @param data
     * @param shelfToken
     */
    editorialSplashVideoCardForContinuePlaying(objectGraph, data, shelfToken) {
        return validation.context("editorialSplashVideoCardForContinuePlaying", () => {
            var _a;
            const lockupMetricsOptions = {
                pageInformation: shelfToken.metricsPageInformation,
                locationTracker: shelfToken.metricsLocationTracker,
                targetType: "lockup",
            };
            const shouldHideArcadeHeader = objectGraph.featureFlags.isEnabled("hide_arcade_header_on_arcade_tab") &&
                serverData.asBooleanOrFalse(shelfToken.isArcadePage);
            const isArcadeLockup = content.isArcadeSupported(objectGraph, data);
            const lockupOptions = {
                metricsOptions: lockupMetricsOptions,
                artworkUseCase: 1 /* content.ArtworkUseCase.LockupIconSmall */,
                offerEnvironment: "dark",
                offerStyle: "white",
                canDisplayArcadeOfferButton: true,
                shouldHideArcadeHeader: shouldHideArcadeHeader,
                isSubtitleHidden: isArcadeLockup && !shouldHideArcadeHeader,
            };
            const video = this.editorialSplashVideoWithTopShelfStill(objectGraph, data);
            if (!video || !video.preview) {
                return null;
            }
            const lockup = lockups.lockupFromData(objectGraph, data, lockupOptions);
            if (!lockup) {
                return null;
            }
            lockup.clickAction = injectCrossfireFlowForGameCenter(objectGraph, lockup.clickAction);
            const clickAction = this.clickActionForVideoCard(objectGraph, data, objectGraph.host.platform, lockupMetricsOptions, shelfToken.clientIdentifierOverride);
            if (!clickAction) {
                return null;
            }
            const videoCard = new models.VideoCard();
            videoCard.video = video;
            videoCard.lockup = lockup;
            videoCard.overlayStyle = "dark";
            videoCard.clickAction = clickAction;
            // Set flow preview actions
            const metricsClickOptions = metricsHelpersClicks.clickOptionsForLockup(objectGraph, data, lockupMetricsOptions);
            videoCard.flowPreviewActionsConfiguration = flowPreview.flowPreviewActionsConfigurationForProductFromData(objectGraph, data, true, shelfToken.clientIdentifierOverride, videoCard.clickAction, lockupMetricsOptions, metricsClickOptions);
            // Configure impressions borrowing lockup values for now.
            const impressionOptions = metricsHelpersImpressions.impressionOptions(objectGraph, data, lockup.title, lockupMetricsOptions);
            metricsHelpersImpressions.addImpressionFields(objectGraph, videoCard, impressionOptions);
            (_a = videoCard.impressionMetrics) === null || _a === void 0 ? true : delete _a.fields["impressionIndex"];
            return videoCard;
        });
    }
    /**
     * Return a video to use for continue playing with:
     * - Product Uber
     * - TV Top Shelf Static Still
     */
    editorialSplashVideoWithTopShelfStill(objectGraph, data) {
        return validation.context("editorialSplashVideoWithTopShelfStill", () => {
            // TV Top Shelf Still (If Any):
            let previewOverride = null;
            const artworkData = contentAttributes.contentAttributeAsDictionary(objectGraph, data, "editorialArtwork.topShelf");
            if (serverData.isDefinedNonNull(artworkData)) {
                previewOverride = content.artworkFromApiArtwork(objectGraph, artworkData, {
                    withJoeColorPlaceholder: true,
                    useCase: 23 /* content.ArtworkUseCase.VideoCardStill */,
                    cropCode: "sr",
                });
            }
            return content.editorialSplashVideoFromData(objectGraph, data, previewOverride);
        });
    }
    // endregion
    // region Helpers
    /**
     * Returns the click action to use for given platform for video card
     */
    clickActionForVideoCard(objectGraph, data, platform, metricsOptions, clientIdentifierOverride) {
        const lockupClickMetricsOptions = metricsHelpersClicks.clickOptionsForLockup(objectGraph, data, metricsOptions);
        let productPageAction = lockups.actionFromData(objectGraph, data, lockupClickMetricsOptions, clientIdentifierOverride);
        productPageAction = injectCrossfireFlowForGameCenter(objectGraph, productPageAction);
        // Wrap in Open for tv only.
        if (platform === "tvOS") {
            const openAppAction = new models.OpenAppAction(data.id, "app");
            const openAppClickOptions = {
                actionType: "open",
                id: data.id,
                contextualAdamId: data.id,
                anonymizationOptions: metricsOptions.anonymizationOptions,
                pageInformation: metricsOptions.pageInformation,
                locationTracker: metricsOptions.locationTracker,
            };
            metricsHelpersClicks.addClickEventToAction(objectGraph, openAppAction, openAppClickOptions);
            const stateAction = new models.OfferStateAction(data.id, productPageAction);
            stateAction.openAction = openAppAction;
            // If the app is downloading and the user clicks this item, take them to the product page instead of cancelling the download.
            stateAction.cancelAction = productPageAction;
            return stateAction;
        }
        else {
            return productPageAction;
        }
    }
    /**
     * The maximum number of games we should ask GameCenterServer for. Note that some of the games it fetches will
     * not be Arcade nor platform-compatible games. For this reason, you should ask for more than you need.
     * As this call is performant enough with a time limit, we just request the maximum amount.
     *
     * The maximum that GameCenterServer will accept is 200.
     */
    maximumNumberOfRecentGamesToRequest() {
        return 200;
    }
    /**
     * The maximum number of games to display on the shelf.
     *
     * The maximum that Media API will accept is 100.
     */
    maximumNumberOfRecentGamesToShow() {
        return 10;
    }
    /**
     * Convert GameCategoryFilter to GamesFilter. Ideally these would be the same, but seed 1 has already left the station.
     * @param gamesFilter
     */
    gameCategoryFilter(gamesFilter) {
        if (gamesFilter === "nonArcade") {
            return "nonarcade";
        }
        return gamesFilter;
    }
    // endregion
    // region Metrics
    shelfMetricsOptionsFromBaseMetricsOptions(objectGraph, shelfToken, baseMetricsOptions) {
        return {
            ...baseMetricsOptions,
            badges: {
                gameCenter: true,
            },
            idType: "its_contentId",
            title: objectGraph.loc.string("GameCenter.ContinuePlayingShelf.Title"),
        };
    }
}
//# sourceMappingURL=grouping-game-center-continue-playing-shelf-controller.js.map