/**
 * Common for top-charts.
 * Incrementally migrate `top-charts-controller` builder logic here.
 */
import { isSome, isNothing } from "@jet/environment/types/optional";
import * as categories from "../common/categories";
import { isDefinedNonNullNonEmpty } from "../foundation/json-parsing/server-data";
import { attributeAsString } from "../foundation/media/attributes";
import { fetchData } from "../foundation/media/network";
import { Parameters } from "../foundation/network/url-constants";
import { URL } from "../foundation/network/urls";
import * as client from "../foundation/wrappers/client";
import { mediaApiChartRequestForGenre } from "./builders/url-mapping";
// region API - URLs
/**
 * Given a chart type, lookup the most appropriate chart to show next to it using
 * fallback mapping logic, e.g. `top-paid` for `top-free` and visa versa.
 *
 * MAINTAINERS NOTE: This is typically driven by Editorial's programming but this can be used as a fallback.
 *
 * @param objectGraph The App Store object graph.
 * @param chartType The type of chart to lookup a sibling for, e.g. `top-free`.
 * @returns The sibling of the provided chart type, e.g. `top-paid`.
 */
export function lookupFallbackSiblingChart(objectGraph, chartType) {
    // Vision currently doesn't support sibling charts - don't attempt to find one.
    if (isNothing(chartType) || objectGraph.client.isVision) {
        return undefined;
    }
    switch (chartType) {
        case "top-free" /* TopChartType.TopFree */:
            return "top-paid" /* TopChartType.TopPaid */;
        case "top-paid" /* TopChartType.TopPaid */:
            return "top-free" /* TopChartType.TopFree */;
        /*
         **  MAINTAINERS NOTE **
         We don't want to show "Top Apps" / "Paid Apps" for extensions, trending, or emerging,
         so don't map   these together until we can confirm the desired UX we want for this.

        case TopChartType.TopFreeSafariExtensions:
            return TopChartType.TopPaidSafariExtensions;
        case TopChartType.TopPaidSafariExtensions:
            return TopChartType.TopFreeSafariExtensions;
        case TopChartType.TopFreeTrending:
            return TopChartType.TopPaidTrending;
        case TopChartType.TopPaidTrending:
            return TopChartType.TopFreeTrending;
        case TopChartType.TopFreeEmerging:
            return TopChartType.TopPaidEmerging;
        case TopChartType.TopPaidEmerging:
            return TopChartType.TopFreeEmerging;
        */
        default:
            return undefined;
    }
}
/**
 * Creates a charts parameter value for an invidual chart shelf's see all flow action URL, which may show multiple charts.
 *
 *  ** MAINTAINERS NOTE **
 *  This function guarantees the selected chart is always included in charts.
 *  This helps make the user experience more resilient to either unexpected editorial programming or client JS programmer error.
 *  For example, if provided chart set is missing the selected chart or is missing any siblings, we lookup hardcoded fallback
 *  mappings, e.g. `top-paid` for `top-free`.
 *
 * @param objectGraph The App Store object graph.
 * @param selectedChartType The selected chart, e.g. `top-free`.
 * @param chartSet  The collection fo charts to be shown as sibligs, e.g. `top-free` and `top-paid` in a segmented control
 * @returns Value for charts URL query paramater.
 */
function makeChartsParameterValue(objectGraph, selectedChartType, chartSet) {
    var _a;
    const hasMultipleCharts = (_a = (chartSet === null || chartSet === void 0 ? void 0 : chartSet.editorialCharts.length) > 1) !== null && _a !== void 0 ? _a : false;
    const charts = chartSet === null || chartSet === void 0 ? void 0 : chartSet.editorialCharts.map((chart) => chart.type.toString()).join(",");
    // use editorially programmed chart set if defined with multiple charts, including the selection.
    if (isSome(charts) && charts.includes(selectedChartType) && hasMultipleCharts) {
        return charts;
    }
    // otherwise, lookup hardcoded fallback sibling if available, e.g. `top-paid` for `top-free`.
    const siblingChartType = lookupFallbackSiblingChart(objectGraph, selectedChartType);
    if (siblingChartType === undefined) {
        return selectedChartType; // no sibling found, show just the single selected chart
    }
    return [selectedChartType, siblingChartType].join(","); // show harcoded pair of charts
}
/**
 * Construct the URL for a single chart shelf "See All", that might be part of an editorial chart set.
 * @param objectGraph The App Store object graph.
 * @param chartData The media API data for the chart shelf, e.g. `top-paid`.
 * @param chartSet The set of charts shown when tapping "See All", e.g. `top-free` and `top-paid`.
 */
export function makeSeeAllUrlFromMediaApiData(objectGraph, chartData, chartSet) {
    const baseUrl = attributeAsString(chartData, "chartHref");
    const chartSeeAllUrl = new URL(baseUrl);
    /**
     * The selected chart to show, e.g. `top-free`.
     */
    const selectedChart = attributeAsString(chartData, "chart");
    if (isDefinedNonNullNonEmpty(selectedChart)) {
        chartSeeAllUrl.param(Parameters.chart, selectedChart);
    }
    /**
     * The collection of charts to show, e.g. `top-free` and `top-paid`.
     * This is needed since a chart sets are vended down as a single fcKind item with children that is divided into multiple shelves.
     * Tapping "See All" on a chart shelf, should show a top charts page with all `charts` provided and `chart` selected.
     */
    const charts = makeChartsParameterValue(objectGraph, selectedChart, chartSet);
    if (isDefinedNonNullNonEmpty(charts)) {
        chartSeeAllUrl.param(Parameters.charts, charts);
    }
    return chartSeeAllUrl.toString();
}
/**
 * Returns whether or not given chart page URL charts parameter is for safari extensions.
 * Charts for safari extensions must be handled as a special case since they don't have an associated specific genre.
 *
 * @param url The URL to check if it is Safari Extension charts.
 */
function isSafariExtensionCharts(charts) {
    return (isDefinedNonNullNonEmpty(charts) &&
        (charts.indexOf("top-free-safari-extensions" /* TopChartType.TopFreeSafariExtensions */) !== -1 ||
            charts.indexOf("top-paid-safari-extensions" /* TopChartType.TopPaidSafariExtensions */) !== -1));
}
// endregion API
// region MAPI Requests
/**
 * Fetch the top-level structural data for top charts.
 *
 * @param objectGraph The App Store object graph.
 * @param genreId The genre to fetch charts for, e.g. Apps or Games.
 * @param charts The specific charts in this genre.
 */
export async function fetchTopChartsData(objectGraph, genreId, charts, ages = null) {
    // Request
    const topChartsRequest = mediaApiChartRequestForGenre(objectGraph, genreId, charts, ages);
    // Pagination + Sparse limits
    topChartsRequest.withLimit(200);
    if (objectGraph.client.isMac || objectGraph.client.isWeb) {
        topChartsRequest.withSparseLimit(25);
    }
    topChartsRequest.enablingFeature("newChartsElements");
    return await fetchData(objectGraph, topChartsRequest);
}
/**
 * Fetch the categories data promise accompanying given `chartUrl`.
 *
 * @param objectGraph Object graph
 * @param charts The charts to fetch categories data for, e.g. `top-free,top-paid`
 * @param genreId The genre for chart to fetch categories data for, e.g. Apps or Games
 */
export async function fetchCategoriesDataForPlatform(objectGraph, charts, genreId) {
    let categoriesRequestPromise;
    /**
     * No categories filter on:
     * - All tvOS charts
     * - All Messages AppStore charts
     * - Safari Extension Charts (Genre-less Genre)
     */
    if (objectGraph.client.isTV ||
        objectGraph.host.clientIdentifier === client.messagesIdentifier ||
        isSafariExtensionCharts(charts)) {
        categoriesRequestPromise = Promise.resolve({});
    }
    else {
        const categoriesRequest = categories.createRequest(objectGraph, genreId);
        categoriesRequestPromise = fetchData(objectGraph, categoriesRequest).catch(() => undefined);
    }
    return await categoriesRequestPromise;
}
// endregion
// region Page Title
/**
 * Return the top charts page title to use for a collection of top chart segments.
 *
 * @param objectGraph Object graph
 * @param segments The segments to derive page title for
 */
export function topChartsPageTitleForSegments(objectGraph, segments) {
    const everySegmentIsTrending = segments.every((seg) => isTrendingChartType(seg.chart));
    if (everySegmentIsTrending) {
        return objectGraph.loc.string("PAGE_TITLE_TRENDING_CHARTS");
    }
    const everySegmentIsEmerging = segments.every((seg) => isEmergingChartType(seg.chart));
    if (everySegmentIsEmerging) {
        return objectGraph.loc.string("PAGE_TITLE_EMERGING_CHARTS");
    }
    return objectGraph.loc.string("PAGE_TITLE_TOP_CHARTS");
}
// endregion
// region Top Charts Type
/// Whether or not given chart type is trending chart type
function isTrendingChartType(chart) {
    switch (chart) {
        case "top-trending-free" /* TopChartType.TopFreeTrending */:
        case "top-trending-paid" /* TopChartType.TopPaidTrending */:
            return true;
        default:
            return false;
    }
}
/// Whether or not given chart type is emerging chart type
function isEmergingChartType(chart) {
    switch (chart) {
        case "top-emerging-free" /* TopChartType.TopFreeEmerging */:
        case "top-emerging-paid" /* TopChartType.TopPaidEmerging */:
            return true;
        default:
            return false;
    }
}
// endregion
//# sourceMappingURL=top-charts-common.js.map