import * as validation from "@jet/environment/json/validation";
import * as models from "../../../api/models";
import * as actions from "../../../api/models/actions";
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 { ResponseMetadata } from "../../../foundation/network/network";
import { Parameters, Path, Protocol } from "../../../foundation/network/url-constants";
import * as urls from "../../../foundation/network/urls";
import * as color from "../../../foundation/util/color-util";
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 { GroupingShelfController } from "./grouping-shelf-controller";
import * as groupingShelfControllerCommon from "./grouping-shelf-controller-common";
import { injectCrossfireFlowForGameCenter } from "./grouping-game-center-popular-with-your-friends-shelf-controller";
export class GroupingGameCenterReengagementShelfController extends GroupingShelfController {
    // region Constructors
    constructor() {
        super("GroupingGameCenterReengagementShelfController");
        this.batchGroupKey = "gameCenter";
        this.supportedFeaturedContentIds = new Set([494 /* groupingTypes.FeaturedContentID.AppStore_GameCenterReengagement */]);
    }
    // endregion
    // region Shelf Builder
    shelfRoute(objectGraph) {
        return [
            ...super.shelfRoute(objectGraph),
            {
                protocol: Protocol.internal,
                path: `/${Path.grouping}/${Path.shelf}/{token}`,
                query: [Parameters.isGameCenterReengagementShelf],
            },
        ];
    }
    // 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: [],
            achievementData: null,
            achievementSummaryData: null,
        };
    }
    /**
     * 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 objectGraph.gameCenter.fetchRengagementDataForLocalPlayer().then(async (reengagementData) => {
            const adamID = serverData.asString(reengagementData, "adamId");
            const achievement = serverData.asJSONData(reengagementData["achievement"]);
            const achievementSummary = serverData.asJSONData(reengagementData["achievementSummary"]);
            if (serverData.isNullOrEmpty(adamID)) {
                // 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: [],
                    responseTimingValues: null,
                    achievementData: null,
                    achievementSummaryData: null,
                };
                return await Promise.resolve(emptyShelfData);
            }
            const request = new mediaDataFetching.Request(objectGraph)
                .withIdOfType(adamID, "apps")
                .includingAgeRestrictions();
            groupingShelfControllerCommon.prepareGroupingShelfRequest(objectGraph, request);
            return await mediaNetwork
                .fetchData(objectGraph, request, {})
                .then((dataContainer) => {
                return {
                    shelfContents: dataContainer.data,
                    responseTimingValues: dataContainer[ResponseMetadata.timingValues],
                    achievementData: achievement,
                    achievementSummaryData: achievementSummary,
                };
            });
        });
    }
    /**
     * 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) {
        if (shelfToken.isFirstRender) {
            return this.pendingGameCenterReengagementShelf(objectGraph, shelfData, shelfToken, groupingParseContext === null || groupingParseContext === void 0 ? void 0 : groupingParseContext.isArcadePage);
        }
        else {
            return this.gameCenterReengagementShelf(objectGraph, shelfData, shelfToken, groupingParseContext === null || groupingParseContext === void 0 ? void 0 : groupingParseContext.isArcadePage);
        }
    }
    pendingGameCenterReengagementShelf(objectGraph, shelfData, shelfToken, isArcadePage) {
        const shelf = this.gameCenterReengagementShelf(objectGraph, shelfData, shelfToken, isArcadePage);
        if (!shelf) {
            return null;
        }
        const groupingShelfUrl = urls.URL.from(groupingShelfControllerCommon.groupingShelfUrl(shelfToken));
        shelf.url = groupingShelfUrl.param(Parameters.isGameCenterReengagementShelf, "true").build();
        shelf.batchGroup = this.batchGroupKey;
        return shelf;
    }
    gameCenterReengagementShelf(objectGraph, shelfData, shelfToken, isArcadePage = false) {
        return validation.context("gameCenterReengagementShelf", () => {
            if (!serverData.isDefinedNonNullNonEmpty(shelfData.shelfContents)) {
                return null;
            }
            const shelf = new models.Shelf("gameCenterReengagement");
            shelf.isHorizontal = false;
            shelf.mergeWhenFetched = false; // Always replace
            shelf.batchGroup = this.batchGroupKey;
            const heroMetricsOptions = {
                id: shelfToken.id,
                kind: null,
                softwareType: isArcadePage ? "Arcade" : null,
                targetType: "achievements",
                title: "Achievements Hero",
                pageInformation: shelfToken.metricsPageInformation,
                locationTracker: shelfToken.metricsLocationTracker,
                idType: "its_contentId",
                fcKind: shelfToken.featuredContentId,
                badges: {
                    gameCenter: true,
                },
            };
            // Hero Background / Artwork
            const artwork = content.productEditorialVideoFromData(objectGraph, shelfData.shelfContents[0], 21 /* content.ArtworkUseCase.Uber */);
            let backgroundColor = color.named("componentBackground");
            let preview = null;
            if (serverData.isDefinedNonNullNonEmpty(artwork)) {
                preview = artwork.preview;
                backgroundColor = preview.backgroundColor;
            }
            // Build lockup used by reegnagement shelf
            const lockupListOptions = {
                lockupOptions: {
                    metricsOptions: {
                        pageInformation: shelfToken.metricsPageInformation,
                        locationTracker: shelfToken.metricsLocationTracker,
                    },
                    offerStyle: "white",
                    artworkUseCase: content.artworkUseCaseFromShelfStyle(objectGraph, "smallLockup"),
                    isSubtitleHidden: true,
                },
            };
            metricsHelpersLocation.pushContentLocation(objectGraph, heroMetricsOptions, heroMetricsOptions.title);
            const heroLockup = lockups.lockupsFromData(objectGraph, shelfData.shelfContents, lockupListOptions)[0];
            heroLockup.clickAction = injectCrossfireFlowForGameCenter(objectGraph, heroLockup.clickAction);
            metricsHelpersLocation.popLocation(shelfToken.metricsLocationTracker);
            // Click action used by hero view (achievement card)
            let heroAction = null;
            if (serverData.isDefinedNonNullNonEmpty(heroLockup)) {
                heroAction = new actions.GameCenterAchievementsAction(heroLockup.bundleId);
                heroAction.title = "Achievements Hero"; // `addClickEventToAction` uses `title` for `name` field currently.
                metricsHelpersClicks.addClickEventToAction(objectGraph, heroAction, heroMetricsOptions);
            }
            const shelfBadge = objectGraph.loc.string("GameCenter.Reengagement.Badge.GameCenter");
            const achievement = this.achievementFromData(objectGraph, shelfData.achievementData);
            const achievementCounts = this.achievementCountsFromData(objectGraph, shelfData.achievementSummaryData);
            const shelfMetadata = this.shelfMetadataForAchievement(objectGraph, achievement, achievementCounts);
            const heroItem = new models.GameCenterReengagement("gamecenter.fill", shelfBadge, shelfMetadata.title, shelfMetadata.subtitle, achievement, heroLockup, backgroundColor, preview, heroAction);
            shelf.items = [heroItem];
            /**
             * For reengagement, the shelf is a container fully fulled by `heroItem`.
             * Match what breakouts do by impressing `heroItem` directly instead of the `shelf`.
             */
            metricsHelpersImpressions.addImpressionFields(objectGraph, heroItem, heroMetricsOptions);
            return shelf;
        });
    }
    // region Helpers
    achievementStatusFromData(objectGraph, data) {
        const statusType = serverData.asString(data, "type");
        const status = new models.GameCenterAchievementStatus(statusType);
        status.percent = serverData.asNumber(data, "percent");
        status.date = serverData.asString(data, "date");
        status.artwork = new models.Artwork(serverData.asString(data, "artwork.template"), serverData.asNumber(data, "artwork.width"), serverData.asNumber(data, "artwork.height"), []);
        return status;
    }
    achievementFromData(objectGraph, data) {
        const id = serverData.asString(data, "id");
        const title = serverData.asString(data, "title");
        const subtitle = serverData.asString(data, "subtitle");
        const status = this.achievementStatusFromData(objectGraph, serverData.asDictionary(data, "status"));
        return new models.GameCenterAchievement(id, title, subtitle, status);
    }
    achievementCountsFromData(objectGraph, data) {
        const completedAchievements = serverData.asNumber(data, "completedAchievements");
        const totalAchievements = serverData.asNumber(data, "totalAchievements");
        return { completed: completedAchievements, total: totalAchievements };
    }
    shelfMetadataForAchievement(objectGraph, achievement, achievementCounts) {
        if (!serverData.isDefinedNonNull(achievement)) {
            return { title: "", subtitle: null };
        }
        if (achievementCounts.completed === 0) {
            return {
                title: objectGraph.loc.string("GameCenter.Reengagement.Achievement.First.Title"),
                subtitle: objectGraph.loc.string("GameCenter.Reengagement.Achievement.First.Subtitle"),
            };
        }
        switch (achievement.status.type) {
            case "locked":
            case "hidden":
            case "inprogress":
                return {
                    title: objectGraph.loc.string("GameCenter.Reengagement.Achievement.KeepPlaying.Title"),
                    subtitle: objectGraph.loc.string("GameCenter.Reengagement.Achievement.KeepPlaying.Subtitle"),
                };
            case "completed":
                const achievementsTotalCount = objectGraph.loc.stringWithCount("GameCenter.AchievementSummary.TotalToCompleteCount", achievementCounts.total);
                const achievementsCompletedCount = objectGraph.loc.stringWithCount("GameCenter.AchievementSummary.NumberCompletedCount", achievementCounts.completed);
                const subtitle = objectGraph.loc
                    .string("GameCenter.AchievementSummary.CompletedCount.Subtitle")
                    .replace("@@completedCount@@", achievementsCompletedCount)
                    .replace("@@totalCount@@", achievementsTotalCount);
                return {
                    title: objectGraph.loc.string("GameCenter.Reengagement.Achievement.CompletedCount.Title"),
                    subtitle: subtitle,
                };
            default:
                return { title: "", subtitle: null };
        }
    }
}
//# sourceMappingURL=grouping-game-center-reengagement-shelf-controller.js.map