import { buildEditorialShelf } from "..";
import * as models from "../../../../api/models";
import * as serverData from "../../../../foundation/json-parsing/server-data";
import { Parameters, Path, Protocol } from "../../../../foundation/network/url-constants";
import * as urls from "../../../../foundation/network/urls";
import * as mediaUrlMapping from "../../../builders/url-mapping";
import * as metricsHelpersClicks from "../../../metrics/helpers/clicks";
import * as metricsHelpersLocation from "../../../metrics/helpers/location";
import { createLocationTrackerCopy, setCurrentPosition } from "../../../metrics/helpers/location";
import * as placeholders from "../../../placeholders/placeholders";
import { createBaseShelfToken } from "../../editorial-page-shelf-token";
import { collectionDisplayStyleOverride, CollectionShelfDisplayStyle, CollectionShelfFilterOverride, EditorialShelfType, } from "../../editorial-page-types";
import { isNothing, isSome } from "@jet/environment";
import * as gamesComponentBuilder from "../../../../gameservicesui/src/editorial-page/editorial-component-builder";
import { makeEditorialShelfCollectionPageIntent } from "../../../../api/intents/editorial/editorial-shelf-collection-page-intent";
import { makeEditorialShelfCollectionPageURL } from "../../editorial-shelf-collection-page-utils";
import { getLocale } from "../../../locale";
import { getPlatform } from "../../../preview-platform";
import { collectionShelfDisplayStyleFromShelfData } from "../../editorial-data-util";
// region Shelf Tokens
/**
 * Whether we should defer building the rest of a shelf given a shelf token
 * @param token
 */
export function shouldDefer(token) {
    return token && token.isDeferring && token.isFirstRender;
}
// endregion
// region Shelf Urls
/**
 * Configure `url` on a standard editorial page shelf if it needs to fetch more content.
 * @param objectGraph
 * @param shelf The shelf we'll be adding the url to
 * @param shelfToken Token to encode in URL for subsequent fetch.
 */
export function createShelfTokenUrlIfNecessary(objectGraph, shelf, shelfToken) {
    if (serverData.isNullOrEmpty(shelfToken)) {
        return null;
    }
    if (objectGraph.client.isWeb) {
        return null;
    }
    const shouldAddFirstRenderUrl = shelfToken.remainingItems.length || shelfToken.recommendationsHref || shelfToken.onDeviceRecommendationsUseCase;
    if (shouldAddFirstRenderUrl && shelfToken.isFirstRender) {
        return editorialPageShelfUrl(shelfToken);
    }
    else {
        return null;
    }
}
/**
 * Updates a shelf URL based on the provided token.
 * @param objectGraph Current object graph
 * @param shelf Shelf to add url to.
 * @param token Token to encode in the url.
 */
function updateShelfTokenUrlWithNewShelfToken(objectGraph, shelf, shelfToken) {
    const originalShelfUrl = urls.URL.from(shelf.url);
    const updatedUrl = urls.URL.from(createShelfTokenUrlIfNecessary(objectGraph, shelf, shelfToken));
    // Add missing query params to the updated URL from the original.
    for (const key of Object.keys(originalShelfUrl.query)) {
        if (serverData.isNull(updatedUrl.query[key])) {
            updatedUrl.query[key] = originalShelfUrl.query[key];
        }
    }
    // Finally, update the shelf's URL.
    shelf.url = updatedUrl.build();
}
/**
 * Stores the impression metrics for a placeholder shelf in the shelf token.
 * @param objectGraph Current object graph
 * @param shelf The shelf
 * @param shelfToken The shelf token
 */
export function storePlaceholderShelfImpressionMetrics(objectGraph, shelf, shelfToken) {
    if (isNothing(shelf.url) || isNothing(shelf.impressionMetrics) || !shelfToken.showingPlaceholders) {
        return;
    }
    const originalShelfUrlString = shelf.url;
    try {
        // Extract the token from the URL.
        // Note: Although we have access to the shelfToken here, we do not know that
        //       the url was constructed from token in its current state. To be safe,
        //       if not efficient, we reverse engineer the URL to get the token.
        const originalShelfUrl = urls.URL.from(originalShelfUrlString);
        const encodedToken = originalShelfUrl.query[Parameters.token];
        const shelfTokenFromUrl = JSON.parse(decodeURIComponent(encodedToken));
        // Modify the token to include the impressions metrics.
        shelfTokenFromUrl.originalPlaceholderShelfImpressionMetrics = shelf.impressionMetrics;
        updateShelfTokenUrlWithNewShelfToken(objectGraph, shelf, shelfTokenFromUrl);
    }
    catch {
        shelf.url = originalShelfUrlString;
    }
}
/**
 * // Merge the original impression metrics with the newly created impression metrics.
 * @param objectGraph Current object graph
 * @param shelf The hydrated shelf
 * @param shelfToken The shelf token
 */
export function mergeShelfImpressionMetricsWithPlaceholders(objectGraph, shelf, shelfToken) {
    if (serverData.isNullOrEmpty(shelfToken.originalPlaceholderShelfImpressionMetrics)) {
        return;
    }
    // If the `shelf.impressionMetrics` is null, we just defer to the original metrics.
    if (serverData.isNull(shelf.impressionMetrics)) {
        shelf.impressionMetrics = shelfToken.originalPlaceholderShelfImpressionMetrics;
    }
    else {
        for (const key in shelfToken.originalPlaceholderShelfImpressionMetrics.fields) {
            if (Object.prototype.hasOwnProperty.call(shelfToken.originalPlaceholderShelfImpressionMetrics.fields, key)) {
                shelf.impressionMetrics.fields[key] = shelfToken.originalPlaceholderShelfImpressionMetrics.fields[key];
            }
        }
    }
}
/**
 * Configure `url` on a standard editorial page shelf if it needs to fetch more content.
 * @param objectGraph
 * @param shelf The shelf we'll be adding the url to
 * @param shelfToken Token to encode in URL for subsequent fetch.
 */
export function createShelfSeeAllActionIfNecessary(objectGraph, shelf, shelfToken) {
    if (serverData.isNullOrEmpty(shelfToken) || serverData.isNullOrEmpty(shelf)) {
        return null;
    }
    if (shouldShowSeeAll(shelfToken)) {
        const action = new models.FlowAction("page");
        // The web client makes a separate request for See All pages, so we don't sidepack for web.
        if (!placeholders.isPlaceholderShelf(shelf) && !objectGraph.client.isWeb) {
            const contentShelfId = `shelf_${shelfToken.id}`;
            action.pageData = createSeeAllPage(objectGraph, shelfToken, shelf.contentType, contentShelfId, isSome(shelfToken.recommendationsHref));
        }
        const additionalPageUrlQueryParams = {};
        if (shelfToken.type === EditorialShelfType.Recommendations) {
            additionalPageUrlQueryParams[Parameters.editorialPageId] = shelfToken.pageId;
        }
        if (objectGraph.client.isWeb) {
            const destinationIntent = makeEditorialShelfCollectionPageIntent({
                ...getLocale(objectGraph),
                ...getPlatform(objectGraph),
                id: shelfToken.id,
            });
            action.destination = destinationIntent;
            action.pageUrl = makeEditorialShelfCollectionPageURL(objectGraph, destinationIntent);
        }
        else {
            action.pageUrl = mediaUrlMapping.hrefToRoutableUrl(objectGraph, shelfToken.data.href, additionalPageUrlQueryParams);
        }
        action.title = objectGraph.loc.string("ACTION_SEE_ALL");
        action.referrerUrl = shelfToken.metricsPageInformation.pageUrl;
        // This can be called after we've gone through and added items to a shelf, meaning the locationPosition
        // would have been incremented to the number of shelf items, the see all should always have a position of
        // 0 so we reset it here and use that, without mucking with the active location tracker.
        const resetLocationTracker = createLocationTrackerCopy(shelfToken.metricsLocationTracker);
        setCurrentPosition(resetLocationTracker, 0);
        metricsHelpersClicks.addClickEventToSeeAllAction(objectGraph, action, shelfToken.seeAllUrl, {
            pageInformation: shelfToken.metricsPageInformation,
            locationTracker: resetLocationTracker,
        });
        return action;
    }
    else {
        return null;
    }
}
/**
 * Determine whether lockup shelves should show "See All" on given platforms.
 *
 * @param shelfToken Token to encode in URL for subsequent fetch.
 * @return Whether or not a lockup shelf with given properties should have a "See All" action.
 */
export function shouldShowSeeAll(shelfToken) {
    if (shelfToken.isSeeAll) {
        return false;
    }
    switch (shelfToken.collectionDisplayStyle) {
        case CollectionShelfDisplayStyle.BreakoutLarge:
        case CollectionShelfDisplayStyle.Poster:
            return false;
        default:
            break;
    }
    // On all other platforms, we always to attach "See All", except AppStore_ComingSoon,
    // which should not because the see all page won't drop lockups whose pre-order has
    // been released (which the AppStore_ComingSoon swoosh will).
    //
    // The Games app is able to show the see all irrespective of the preorder flag.
    return (!shelfToken.filterOverrides.includes(CollectionShelfFilterOverride.ShowOnlyPreorder) ||
        preprocessor.GAMES_TARGET);
}
/**
 * Returns the URL schema for editorial page shelves that may need to fetch additional content.
 * Editorial-Page-Related builders can extend on this scheme if needed, e.g. query param on Continue Playing shelves.
 * @param shelfToken Token to encode in URL for subsequent fetch.
 * @param parseContext
 */
export function editorialPageShelfUrl(shelfToken) {
    const shelfUrl = new urls.URL()
        .set("protocol", Protocol.internal)
        .append("pathname", Path.editorialPage)
        .append("pathname", Path.shelf)
        .param(Parameters.token, encodeURIComponent(JSON.stringify(shelfToken)));
    return shelfUrl.build();
}
/**
 * Creates a page that can be used for side-packing see all pages into a room.
 *
 * @param objectGraph
 * @param {EditorialPageShelfToken} shelfToken The shelf token used to build the original shelf
 * @param {ShelfContentType} preferredShelfContentType The content type to use for the page
 * @param {string} parentShelfId The ID of the parent shelf that the contains the sidepack items
 * @returns {GenericPage} A GenericPage which will use the parentShelfItems from the see all to render the initial room
 */
export function createSeeAllPage(objectGraph, shelfToken, preferredShelfContentType, parentShelfId, isComplete) {
    // Create a new shelf token with a new location tracker in order to get accurate metrics for the items in the shelf.
    const newLocationTracker = metricsHelpersLocation.newLocationTracker();
    const collectionDisplayStyle = collectionShelfDisplayStyleFromShelfData(objectGraph, shelfToken.data);
    const newToken = createBaseShelfToken(objectGraph, shelfToken.pageId, shelfToken.data, shelfToken.isArcadePage, shelfToken.shelfIndex, shelfToken.metricsPageInformation, newLocationTracker, true, collectionDisplayStyleOverride(collectionDisplayStyle));
    const contentShelf = buildEditorialShelf(objectGraph, undefined, newToken);
    if (contentShelf === null) {
        return null;
    }
    contentShelf.title = null;
    contentShelf.eyebrow = null;
    contentShelf.isHorizontal = false;
    contentShelf.id = parentShelfId;
    let pageHeader;
    if (preprocessor.GAMES_TARGET) {
        pageHeader = gamesComponentBuilder.makeGamesPageHeader(shelfToken, shelfToken.title, contentShelf.items, shelfToken.subtitle);
    }
    else {
        pageHeader = new models.PageHeader(null, shelfToken.title, null);
    }
    const headerShelf = new models.Shelf("pageHeader");
    headerShelf.id = "shelf_page_header";
    headerShelf.items = [pageHeader];
    const shelves = [headerShelf, contentShelf];
    const page = new models.GenericPage(shelves);
    page.isIncomplete = !(isComplete !== null && isComplete !== void 0 ? isComplete : false);
    if (isNothing(page.pageMetrics.pageFields)) {
        page.pageMetrics.pageFields = {};
    }
    return page;
}
// endregion
//# sourceMappingURL=editorial-page-collection-shelf-common.js.map