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 mediaDataStructure from "../../../foundation/media/data-structure";
import * as mediaRelationship from "../../../foundation/media/relationships";
import { Parameters, Path, Protocol, ShelfRefreshType } from "../../../foundation/network/url-constants";
import { URL } from "../../../foundation/network/urls";
import { applySearchAdMissedOpportunityToShelvesIfNeeded, isAdPlacementEnabled } from "../../ads/ad-common";
import * as content from "../../content/content";
import * as metricsHelpersLocation from "../../metrics/helpers/location";
import * as metricsHelpersPage from "../../metrics/helpers/page";
import { insertPlaceholdersIntoProductPageShelfIfRequired } from "../../placeholders/placeholders";
import * as productPageCommon from "../product-page-common";
import { ProductPageOnDemandShelfType } from "../product-page-common";
import { ProductPageShelfMetrics } from "../product-page-shelf-metrics";
import * as adIncidents from "../../../common/ads/ad-incident-recorder";
import { adStitcherForOnDeviceProductPageYMALAdvertData } from "../../ads/on-device-ad-stitch";
import * as adStitch from "../../ads/ad-stitcher";
import { makeSeeAllPageURL } from "../intent-controller-routing";
import { makeSeeAllPageIntent } from "../../../api/intents/see-all-page-intent";
import { getPlatform } from "../../preview-platform";
import { getLocale } from "../../locale";
/**
 * Create a shelf of similar items for the product page.
 *
 * @param productData The raw data response for a product page JSON fetch.
 * @param shelfMetrics The product page shelf metrics.
 * @returns A similar items shelf.
 */
export function createInitialShelf(objectGraph, productData, shelfMetrics) {
    return validation.context("similarItemsShelf", () => {
        var _a;
        if (serverData.isNullOrEmpty(productData)) {
            return null;
        }
        if (objectGraph.client.isCompanionVisionApp) {
            return null;
        }
        const relationship = mediaRelationship.relationship(productData, "customers-also-bought-apps");
        if (serverData.isNullOrEmpty(relationship)) {
            return null;
        }
        const supportsArcade = content.isArcadeSupported(objectGraph, productData);
        const title = supportsArcade
            ? objectGraph.loc.string("Arcade.ProductPage.MoreFromAppleArcade")
            : objectGraph.loc.string("ProductPage.Section.SimilarItems.Title");
        const metricsTargetType = "similarItems";
        const metricsIdType = "relationship";
        metricsHelpersLocation.pushContentLocation(objectGraph, {
            pageInformation: shelfMetrics.metricsPageInformation,
            locationTracker: shelfMetrics.locationTracker,
            targetType: metricsTargetType,
            id: ProductPageShelfMetrics.similarItemsShelfId,
            idType: metricsIdType,
        }, title);
        let contentType;
        let shouldInferSeeAllFromFetchedItems;
        switch (objectGraph.client.deviceType) {
            case "tv":
                contentType = "mediumLockup";
                shouldInferSeeAllFromFetchedItems = false;
                break;
            case "mac":
                contentType = "mediumLockup";
                shouldInferSeeAllFromFetchedItems = true;
                break;
            default:
                contentType = "smallLockup";
                shouldInferSeeAllFromFetchedItems = true;
                break;
        }
        const shelf = new models.Shelf(contentType);
        shelf.title = title;
        const recoMetricsData = mediaDataStructure.metricsFromMediaApiObject(relationship);
        const hasShelfBackground = !objectGraph.client.isTV && !objectGraph.client.isiOS;
        const offerStyle = hasShelfBackground ? "white" : null;
        const shelfItems = productPageCommon.lockupsFromDataContainer(objectGraph, relationship, shelfMetrics, content.artworkUseCaseFromShelfStyle(objectGraph, contentType), contentType, offerStyle, null, recoMetricsData);
        if (!shelfItems) {
            return null;
        }
        shelf.items = shelfItems.items;
        const isAdEnabled = isAdPlacementEnabled(objectGraph, "productPageYMAL");
        const destinationPageInformation = metricsHelpersPage.fakeMetricsPageInformation(objectGraph, "SimilarItems", productData.id, "");
        // Add all the ids on the shelf to attach to the refreshUrl as a fallback in case the shelf can't be refreshed with new content.
        // Create a `refreshUrl` for this shelf so it can be refreshed by native during downloading.
        const refreshShelfToken = new productPageCommon.ProductPageShelfToken(productData.id, relationship.data, shelf.title, shouldInferSeeAllFromFetchedItems, undefined, contentType, null, null, null, null, null, ProductPageOnDemandShelfType.SimilarItems);
        if (objectGraph.client.isWeb) {
            const action = new models.FlowAction("page");
            action.title = objectGraph.loc.string("ACTION_SEE_ALL");
            const destination = makeSeeAllPageIntent({
                ...getLocale(objectGraph),
                ...getPlatform(objectGraph),
                "id": productData.id,
                "see-all": "customers-also-bought-apps",
            });
            action.destination = destination;
            action.pageUrl = makeSeeAllPageURL(objectGraph, destination);
            shelf.seeAllAction = action;
        }
        else {
            const shelfRefreshUrl = refreshUrl(objectGraph, productData.id, refreshShelfToken, shelfMetrics, destinationPageInformation);
            shelf.refreshUrl = shelfRefreshUrl;
        }
        shelf.isHorizontal = true;
        if (relationship.data.length < 2 || objectGraph.client.isTV) {
            shelf.rowsPerColumn = 1;
        }
        else if (supportsArcade || !objectGraph.client.isiOS) {
            // Arcade and other platforms (except TV) show 2 apps per column.
            shelf.rowsPerColumn = 2;
        }
        else {
            // iOS regular product pages show 3 apps per column.
            shelf.rowsPerColumn = 3;
        }
        if (hasShelfBackground) {
            shelf.background = {
                type: "color",
                color: productPageCommon.grayShelfBackgroundColor,
            };
        }
        if (objectGraph.client.isiOS && objectGraph.bag.isOnDemandShelfFetchingEnabled) {
            shelf.fetchStrategy = models.IncompleteShelfFetchStrategy.OnShelfWillAppear;
        }
        if (serverData.isDefinedNonNullNonEmpty(shelfItems.remainingItems) || isAdEnabled) {
            // Add impressions and pop the location here so we're at the original state for the shelf token / url
            metricsHelpersLocation.popLocation(shelfMetrics.locationTracker);
            shelfMetrics.addImpressionsFieldsToSimilarItemsShelf(objectGraph, shelf, metricsTargetType, metricsIdType);
            metricsHelpersLocation.nextPosition(shelfMetrics.locationTracker);
            const shelfToken = new productPageCommon.ProductPageShelfToken(productData.id, (_a = shelfItems.remainingItems) !== null && _a !== void 0 ? _a : [], shelf.title, shouldInferSeeAllFromFetchedItems, undefined, contentType, offerStyle, null, shelf.refreshUrl, recoMetricsData, supportsArcade, ProductPageOnDemandShelfType.SimilarItems);
            insertPlaceholdersIntoProductPageShelfIfRequired(objectGraph, shelf, shelfToken);
            shelf.url = productPageCommon.shelfContentUrl(objectGraph, shelfToken, shelfMetrics, destinationPageInformation);
            if (isAdEnabled) {
                const url = new URL(shelf.url);
                url.param(Parameters.isShelfWithAd, "true");
                url.param(Parameters.shelfWithAdPlacementType, "productPageYMAL");
                url.param(Parameters.id, productData.id);
                shelf.url = url.build();
            }
        }
        else {
            metricsHelpersLocation.popLocation(shelfMetrics.locationTracker);
            shelfMetrics.addImpressionsFieldsToSimilarItemsShelf(objectGraph, shelf, metricsTargetType, metricsIdType);
            metricsHelpersLocation.nextPosition(shelfMetrics.locationTracker);
        }
        return shelf;
    });
}
/**
 * Create a shelf of similar items for the secondary look up.
 *
 * @param dataItems The raw data items from the secondary fetch.
 * @param shelfToken The shelf token for this shelf.
 * @returns A similar items shelf.
 */
export function createSecondaryShelf(objectGraph, dataItems, shelfToken, adResponse) {
    return validation.context("similarItemsSecondaryShelf", () => {
        var _a, _b;
        if (serverData.isNullOrEmpty(dataItems)) {
            return null;
        }
        if (objectGraph.client.isCompanionVisionApp) {
            return null;
        }
        const shelfMetrics = new ProductPageShelfMetrics(shelfToken.sourcePageInformation, shelfToken.sourceLocationTracker, shelfToken.sourceSequenceId);
        const metricsTargetType = "similarItems";
        const metricsIdType = "relationship";
        const metricsOptions = {
            pageInformation: shelfMetrics.metricsPageInformation,
            locationTracker: shelfMetrics.locationTracker,
            targetType: metricsTargetType,
            id: ProductPageShelfMetrics.similarItemsShelfId,
            idType: metricsIdType,
            excludeAttribution: true,
            recoMetricsData: shelfToken.recoMetricsData,
        };
        metricsHelpersLocation.pushContentLocation(objectGraph, metricsOptions, shelfToken.title);
        const shelf = new models.Shelf(shelfToken.contentType);
        let adIncidentRecorder;
        if (isAdPlacementEnabled(objectGraph, "productPageYMAL") ||
            isAdPlacementEnabled(objectGraph, "productPageYMALDuringDownload")) {
            adIncidentRecorder = adIncidents.newRecorder(objectGraph, shelfToken.sourcePageInformation.iAdInfo);
            adIncidents.recordAdResponseEventsIfNeeded(objectGraph, adIncidentRecorder, adResponse);
            const adStitcher = adStitcherForOnDeviceProductPageYMALAdvertData(objectGraph, adResponse);
            // Update metrics data for a new ad request.
            (_a = shelfMetrics.metricsPageInformation.iAdInfo) === null || _a === void 0 ? void 0 : _a.updateForAdResponse(objectGraph, adResponse);
            /**
             * *** Ad Stitching ***
             * Get all the tasks for the current shelf, and iterate over the tasks, inserting them in the specified position.
             */
            const adTasks = adStitch.consumeTasksForShelfIdentifier(adStitcher, (_b = metricsHelpersLocation.currentLocation(shelfMetrics.locationTracker)) === null || _b === void 0 ? void 0 : _b.id);
            adTasks.forEach((task) => {
                // Remove any organic dupes of the ad we're about to insert.
                dataItems = dataItems.filter((data) => data.id !== task.data.id);
                dataItems.splice(task.positionInfo.slot, 0, task.data);
            });
            shelf.adIncidents = adIncidents.recordedIncidents(objectGraph, adIncidentRecorder);
        }
        const shelfItems = productPageCommon.lockupsFromData(objectGraph, dataItems, shelfMetrics, content.artworkUseCaseFromShelfStyle(objectGraph, shelfToken.contentType), shelfToken.contentType, shelfToken.offerStyle, null, shelfToken.recoMetricsData);
        if (serverData.isNullOrEmpty(shelfItems)) {
            return null;
        }
        shelf.title = shelfToken.title;
        shelf.items = shelfItems.items;
        shelf.isHorizontal = true;
        const hasShelfBackground = !objectGraph.client.isTV && !objectGraph.client.isiOS;
        if (hasShelfBackground) {
            shelf.background = {
                type: "color",
                color: productPageCommon.grayShelfBackgroundColor,
            };
        }
        // Add all the ids on the shelf to attach to the refreshUrl as a fallback in case the shelf can't be refreshed with new content.
        // Create a `refreshUrl` for this shelf so it can be refreshed by native during downloading.
        const refreshShelfToken = new productPageCommon.ProductPageShelfToken(shelfToken.productId, dataItems, shelfToken.title, shelfToken.shouldInferSeeAllFromFetchesItems, undefined, shelfToken.contentType, null, null, null, null, null, ProductPageOnDemandShelfType.SimilarItems);
        const shelfRefreshUrl = refreshUrl(objectGraph, shelfToken.productId, refreshShelfToken, shelfMetrics, shelfToken.destinationPageInformation);
        shelf.refreshUrl = shelfRefreshUrl;
        if (dataItems.length < 2 || objectGraph.client.isTV) {
            shelf.rowsPerColumn = 1;
        }
        else if (shelfToken.supportsArcade || !objectGraph.client.isiOS) {
            // Arcade and other platforms (except TV) show 2 apps per column.
            shelf.rowsPerColumn = 2;
        }
        else {
            // iOS regular product pages show 3 apps per column.
            shelf.rowsPerColumn = 3;
        }
        shelfMetrics.addImpressionsFieldsToSimilarItemsShelf(objectGraph, shelf, metricsTargetType, metricsIdType);
        applySearchAdMissedOpportunityToShelvesIfNeeded(objectGraph, [shelf], "productPageYMAL", metricsOptions.id, metricsOptions.pageInformation);
        metricsHelpersLocation.popLocation(shelfMetrics.locationTracker);
        metricsHelpersLocation.nextPosition(shelfMetrics.locationTracker);
        return shelf;
    });
}
/**
 * Returns a refresh URL for the similar items shelf.
 * @param objectGraph - The object graph.
 * @param id - The ID of the product this shelf appears on.
 * @param token - The constructed ProductPageShelfToken.
 * @param shelfMetrics - Metrics for the shelf.
 * @param destinationPageInformation - Information for the destination page.
 * @returns A string containing a URL.
 */
function refreshUrl(objectGraph, id, token, shelfMetrics, destinationPageInformation) {
    const urlString = `${Protocol.internal}:/${Path.product}/${Path.shelf}/` +
        productPageCommon.encodedShelfToken(token, shelfMetrics, destinationPageInformation);
    const url = new URL(urlString);
    url.param(Parameters.shelfRefreshType, ShelfRefreshType.productPageSimilarItems);
    url.param(Parameters.id, id);
    return url.build();
}
//# sourceMappingURL=similar-items-shelf.js.map