import { isSome } from "@jet/environment/types/optional";
import * as models from "../../api/models";
import * as serverData from "../../foundation/json-parsing/server-data";
import * as mediaAttributes from "../../foundation/media/attributes";
import * as mediaPlatformAttributes from "../../foundation/media/platform-attributes";
import * as color from "../../foundation/util/color-util";
import * as contentDeviceFamily from "../content/device-family";
import * as client from "../../foundation/wrappers/client";
import * as contentArtwork from "../content/artwork/artwork";
import * as contentAttributes from "../content/attributes";
import * as content from "../content/content";
import * as filtering from "../filtering";
import * as lockups from "../lockups/lockups";
import * as metricsHelpersClicks from "../metrics/helpers/clicks";
import { externalPurchasesLearnMoreAction, externalPurchasesPlacementIsEnabled, hasExternalPurchasesForData, } from "../offers/external-purchases";
import * as productPageUtil from "../product-page/product-page-util";
import { createExpandActionForAnnotation } from "./shelves/annotations/annotations";
import * as compatibilityAnnotation from "./shelves/annotations/compatibility-annotation";
import { appPlatformTitle } from "../../gameservicesui/src/common/media-preview-platform";
import { hasRemoteDownloadIdentifiers, supportsVisionPlatformForVisionCompanion } from "../offers/offers";
/**
 * Create a product page banner.
 *
 * @param data The raw data response for a product page JSON fetch.
 * @param bannerContext A collection of any other variables used when creating this banner.
 * @returns A banner.
 */
export function create(objectGraph, data, bannerContext) {
    let message = null;
    let focusedMessage = null;
    let action = null;
    let fullProductAction = null;
    let leadingArtwork = null;
    let leadingArtworkTintColor = null;
    let includeBackgroundBorder = false;
    const bannerKind = null;
    // 32-bit only app (disables buy button)
    // `requires32bit` is used only for macOS apps, which is why we have two similar flags here
    const is32bitOnly = contentAttributes.contentAttributeAsBooleanOrFalse(objectGraph, data, "is32bitOnly");
    const requires32bit = contentAttributes.contentAttributeAsBooleanOrFalse(objectGraph, data, "requires32bit");
    if (is32bitOnly || requires32bit) {
        if (objectGraph.client.isMac) {
            message = objectGraph.loc.string("ProductPage.Banner.UpdateRequired.macOS");
        }
        else if (objectGraph.client.isVision) {
            message = objectGraph.loc.string("ProductPage.Banner.UpdateRequired.Vision");
        }
        else {
            message = objectGraph.loc.string("ProductPage.Banner.UpdateRequired.iOS");
        }
        bannerContext.offerButtonShouldBeDisabled = true;
    }
    // Is SAD watch-only app
    if (message === null && filtering.shouldFilter(objectGraph, data, 1024 /* filtering.Filter.SADWatchApps */)) {
        message = objectGraph.loc.string("OFFER_WATCH_ONLY_BANNER");
        bannerContext.offerButtonShouldBeDisabled = true;
    }
    // Required capabilities mismatch
    if (message === null && !lockups.deviceHasCapabilitiesFromData(objectGraph, data)) {
        message = objectGraph.loc.string("NOT_COMPATIBLE_BANNER");
        if (preprocessor.GAMES_TARGET) {
            message = objectGraph.loc.string("GameDetails.Page.Banner.NotCompatible.Message");
        }
        else if (objectGraph.client.isTV) {
            // We don't support product page scrolling for this particular banner on TV
            message = objectGraph.loc.string("NOT_COMPATIBLE_BANNER_NO_LINK");
        }
        else if (objectGraph.client.isVision) {
            // For visionOS, we show a sheet rather than scrolling
            const annotation = compatibilityAnnotation.createAnnotation(objectGraph, data, false, false, false, null);
            if (isSome(annotation)) {
                action = createExpandActionForAnnotation(objectGraph, annotation);
                if (isSome(action)) {
                    action.title = objectGraph.loc.string("NOT_COMPATIBLE_BANNER_LINK_TITLE");
                    message = objectGraph.loc
                        .string("NOT_COMPATIBLE_BANNER_TEMPLATE")
                        .replace("{linkTitle}", action.title);
                }
            }
            bannerContext.offerButtonShouldBeDisabled = true;
        }
        else if (objectGraph.client.isiOS || objectGraph.client.isMac) {
            // For iOS / macOS, add an action that allows users to scroll to the Compatibility item
            if (productPageUtil.isShelfBased(objectGraph)) {
                const scrollAction = new models.ShelfBasedPageScrollAction("information");
                scrollAction.title = objectGraph.loc.string("NOT_COMPATIBLE_BANNER_LINK_TITLE");
                scrollAction.indexId = "compatibilityAnnotation";
                // Here we use the `fullProductAction` action rather than just `action`,
                // as our `ProductPageScrollAction` will only be valid once the full product page has loaded
                fullProductAction = scrollAction;
            }
            else {
                const informationSection = new models.ProductPageSection("shelf", "information");
                const scrollAction = new models.ProductPageScrollAction(informationSection);
                scrollAction.title = objectGraph.loc.string("NOT_COMPATIBLE_BANNER_LINK_TITLE");
                scrollAction.indexId = "compatibilityAnnotation";
                // Here we use the `fullProductAction` action rather than just `action`,
                // as our `ProductPageScrollAction` will only be valid once the full product page has loaded
                fullProductAction = scrollAction;
            }
            message = objectGraph.loc
                .string("NOT_COMPATIBLE_BANNER_TEMPLATE")
                .replace("{linkTitle}", fullProductAction.title);
            bannerContext.offerButtonShouldBeDisabled = true;
        }
    }
    // Filtered system & legacy apps
    if (message === null &&
        filtering.shouldFilter(objectGraph, data, 4 /* filtering.Filter.UnsupportedSystemDeletableApps */ | 32 /* filtering.Filter.LegacyApps */)) {
        message = objectGraph.loc.string("UNSUPPORTED_CAPABILITIES");
        bannerContext.offerButtonShouldBeDisabled = true;
    }
    // App is supported on this OS version
    if (filtering.shouldFilter(objectGraph, data, 512 /* filtering.Filter.MinimumOSRequirement */)) {
        const minOSVersion = content.minimumOSVersionFromData(objectGraph, data, objectGraph.appleSilicon.isSupportEnabled);
        switch (objectGraph.client.deviceType) {
            case "mac":
                message = objectGraph.loc.string("UNSUPPORTED_MACOS_VERSION").replace("{osVersion}", minOSVersion);
                break;
            case "phone":
            case "pad":
                message = objectGraph.loc.string("UNSUPPORTED_IOS_VERSION").replace("{osVersion}", minOSVersion);
                break;
            case "tv":
                message = objectGraph.loc.string("UNSUPPORTED_TVOS_VERSION").replace("{osVersion}", minOSVersion);
                break;
            case "watch":
                const minWatchOSVersion = contentAttributes.contentAttributeAsString(objectGraph, data, "minimumWatchOSVersion");
                message = objectGraph.loc
                    .string("UNSUPPORTED_WATCHOS_VERSION")
                    .replace("{osVersion}", minWatchOSVersion);
                break;
            case "vision":
                message = objectGraph.loc.string("UNSUPPORTED_VISIONOS_VERSION").replace("{osVersion}", minOSVersion);
                break;
            default:
                message = objectGraph.loc.string("UNSUPPORTED_CAPABILITIES");
                break;
        }
        // If the device is a phone but the app is watch-only, use the unsupported watch message.
        if (objectGraph.client.isPhone &&
            contentAttributes.contentAttributeAsBooleanOrFalse(objectGraph, data, "isStandaloneForWatchOS")) {
            const minWatchOSVersion = contentAttributes.contentAttributeAsString(objectGraph, data, "minimumWatchOSVersion");
            message = objectGraph.loc.string("UNSUPPORTED_WATCHOS_VERSION").replace("{osVersion}", minWatchOSVersion);
        }
    }
    // App is supported on companion's OS version
    if (objectGraph.client.isWatch &&
        filtering.shouldFilter(objectGraph, data, 2048 /* filtering.Filter.MinimumCompanionOSRequirement */)) {
        const minOSVersion = mediaPlatformAttributes.platformAttributeAsString(data, contentAttributes.bestAttributePlatformFromData(objectGraph, data), "minimumOSVersion");
        message = objectGraph.loc.string("UNSUPPORTED_IOS_VERSION").replace("{osVersion}", minOSVersion);
    }
    // If the current device is not supported
    if (filtering.shouldFilter(objectGraph, data, 128 /* filtering.Filter.UnsupportedPlatform */)) {
        bannerContext.offerButtonShouldBeDisabled = true;
        message = objectGraph.loc.string("NOT_COMPATIBLE_BANNER");
        if (preprocessor.GAMES_TARGET) {
            const supportedPlatforms = content.supportedAppPlatformsFromData(objectGraph, data);
            if (supportedPlatforms.length === 1) {
                const supportedPlatform = supportedPlatforms[0];
                const platformTitle = appPlatformTitle(objectGraph, supportedPlatform);
                message = objectGraph.localizer.string("GameDetails.Page.Banner.OnlyAvailable.Message", {
                    platform: platformTitle,
                });
                const systemImageName = content.systemImageNameForAppPlatform(supportedPlatform);
                leadingArtwork = contentArtwork.createArtworkForResource(objectGraph, `systemimage://${systemImageName}`);
            }
            else {
                message = objectGraph.loc.string("GameDetails.Page.Banner.NotCompatible.Message");
            }
        }
        else if (objectGraph.client.isTV) {
            // We don't support product page scrolling for this particular banner on TV
            message = objectGraph.loc.string("NOT_COMPATIBLE_BANNER_NO_LINK");
        }
        else if (objectGraph.client.isVision) {
            // For visionOS, we show a sheet rather than scrolling
            const annotation = compatibilityAnnotation.createAnnotation(objectGraph, data, false, false, false, null);
            if (isSome(annotation)) {
                action = createExpandActionForAnnotation(objectGraph, annotation);
                if (isSome(action)) {
                    action.title = objectGraph.loc.string("NOT_COMPATIBLE_BANNER_LINK_TITLE");
                    message = objectGraph.loc
                        .string("NOT_COMPATIBLE_BANNER_TEMPLATE")
                        .replace("{linkTitle}", action.title);
                }
            }
            bannerContext.offerButtonShouldBeDisabled = true;
        }
        else if (objectGraph.client.isiOS || objectGraph.client.isMac) {
            if (productPageUtil.isShelfBased(objectGraph)) {
                const scrollAction = new models.ShelfBasedPageScrollAction("information");
                scrollAction.title = objectGraph.loc.string("NOT_COMPATIBLE_BANNER_LINK_TITLE");
                scrollAction.indexId = "compatibilityAnnotation";
                // Here we use the `fullProductAction` action rather than just `action`,
                // as our `ProductPageScrollAction` will only be valid once the full product page has loaded
                fullProductAction = scrollAction;
                message = objectGraph.loc
                    .string("NOT_COMPATIBLE_BANNER_TEMPLATE")
                    .replace("{linkTitle}", scrollAction.title);
            }
            else {
                // For iOS / macOS, add an action that allows users to scroll to the Compatibility item
                const informationSection = new models.ProductPageSection("shelf", "information");
                const scrollAction = new models.ProductPageScrollAction(informationSection);
                scrollAction.title = objectGraph.loc.string("NOT_COMPATIBLE_BANNER_LINK_TITLE");
                scrollAction.indexId = "compatibilityAnnotation";
                // Here we use the `fullProductAction` action rather than just `action`,
                // as our `ProductPageScrollAction` will only be valid once the full product page has loaded
                fullProductAction = scrollAction;
                message = objectGraph.loc
                    .string("NOT_COMPATIBLE_BANNER_TEMPLATE")
                    .replace("{linkTitle}", scrollAction.title);
            }
        }
    }
    // Perform Rosetta filtering for macOS.
    if (filtering.shouldFilter(objectGraph, data, 8192 /* filtering.Filter.MacOSRosetta */)) {
        if (productPageUtil.isShelfBased(objectGraph)) {
            const scrollAction = new models.ShelfBasedPageScrollAction("information");
            scrollAction.title = objectGraph.loc.string("NOT_COMPATIBLE_BANNER_LINK_TITLE");
            scrollAction.indexId = "compatibilityAnnotation";
            // Here we use the `fullProductAction` action rather than just `action`,
            // as our `ProductPageScrollAction` will only be valid once the full product page has loaded
            fullProductAction = scrollAction;
        }
        else {
            const informationSection = new models.ProductPageSection("shelf", "information");
            const scrollAction = new models.ProductPageScrollAction(informationSection);
            scrollAction.title = objectGraph.loc.string("NOT_COMPATIBLE_BANNER_LINK_TITLE");
            scrollAction.indexId = "compatibilityAnnotation";
            // Here we use the `fullProductAction` action rather than just `action`,
            // as our `ProductPageScrollAction` will only be valid once the full product page has loaded
            fullProductAction = scrollAction;
        }
        message = objectGraph.loc
            .string("NOT_COMPATIBLE_BANNER_TEMPLATE")
            .replace("{linkTitle}", fullProductAction.title);
    }
    // App is not supported by the current companion, eg. dynamic duo app on a Tinker watch
    const isPreorder = mediaAttributes.attributeAsBooleanOrFalse(data, "isPreorder");
    if (content.isUnsupportedByCurrentCompanion(objectGraph, data)) {
        if (isPreorder) {
            if (objectGraph.host.isWatch) {
                message = objectGraph.loc.string("UNSUPPORTED_COMPANION_CONFIGURATION_PREORDER");
            }
            else {
                message = objectGraph.loc.string("ProductPage.WatchOS.PreOrderRequiresiPhone");
            }
        }
        else {
            message = objectGraph.loc.string("UNSUPPORTED_COMPANION_CONFIGURATION", "Requires iPhone");
        }
        bannerContext.offerButtonShouldBeDisabled = true;
    }
    // App is not supported on paired watch OS version
    const minimumWatchOSVersionString = contentAttributes.contentAttributeAsString(objectGraph, data, "minimumWatchOSVersion");
    if (message === null &&
        bannerContext.clientIdentifierOverride === client.watchIdentifier &&
        content.isActivePairedWatchOSBelowVersion(objectGraph, minimumWatchOSVersionString)) {
        message = objectGraph.loc
            .string("ProductPage.Banner.PairedWatchOSVersionBelowMinimum")
            .replace("{osVersion}", minimumWatchOSVersionString);
    }
    /// App requires a visionOS device
    const isVisionOnlyApp = contentDeviceFamily.dataOnlyHasDeviceFamily(objectGraph, data, "realityDevice");
    if (isVisionOnlyApp &&
        !objectGraph.client.isVision &&
        !objectGraph.client.isWeb &&
        !preprocessor.GAMES_TARGET &&
        !objectGraph.client.isCompanionVisionApp) {
        const learnMoreTitle = objectGraph.loc.string("BANNER_VISION_ONLY_APP_LEARN_MORE_LINK");
        action = visionOnlyAppLearnMoreAction(objectGraph, learnMoreTitle, bannerContext.metricsPageInformation, bannerContext.metricsLocationTracker);
        message = visionOnlyAppMessage(objectGraph, learnMoreTitle, action);
        fullProductAction = null;
        leadingArtwork = contentArtwork.createArtworkForResource(objectGraph, "systemimage://visionpro");
        leadingArtworkTintColor = color.named("secondaryText");
        includeBackgroundBorder = true;
    }
    if (supportsVisionPlatformForVisionCompanion(objectGraph, data) && !hasRemoteDownloadIdentifiers(objectGraph)) {
        // This case is where we support the download to a visionOS device, but we don't have anything to download to.
        bannerContext.offerButtonShouldBeDisabled = true;
        message = objectGraph.loc.string("ProductPage.Banner.Companion.VisionDeviceRequired");
    }
    else if (objectGraph.client.isCompanionVisionApp &&
        !supportsVisionPlatformForVisionCompanion(objectGraph, data)) {
        // This case is the app doesn't support remote downloads, show this banner.
        bannerContext.offerButtonShouldBeDisabled = true;
        message = objectGraph.loc.string("ProductPage.Banner.Companion.RemoteDownloadUnavailable");
    }
    // External purchases
    // If we have no banner, or the offer button is not disabled, give priority to the external purchases banner
    const hasExternalPurchases = hasExternalPurchasesForData(objectGraph, data);
    const externalPurchasesEnabled = externalPurchasesPlacementIsEnabled(objectGraph, "product-page-banner");
    if ((message === null || !bannerContext.offerButtonShouldBeDisabled) &&
        hasExternalPurchases &&
        externalPurchasesEnabled) {
        const learnMoreTitle = objectGraph.loc.string("ProductPage.ExternalPurchasesBanner.LearnMore");
        action = externalPurchasesLearnMoreAction(objectGraph, learnMoreTitle, bannerContext.metricsPageInformation, bannerContext.metricsLocationTracker);
        message = externalPurchasesMessage(objectGraph, learnMoreTitle, action);
        fullProductAction = null;
        if (objectGraph.bag.externalPurchasesIncludeProductPageBannerIcon) {
            if (objectGraph.bag.externalPurchasesProductPageBannerIconVariant === "secondaryInfoCircle") {
                leadingArtwork = contentArtwork.createArtworkForResource(objectGraph, "systemimage://info.circle");
                leadingArtworkTintColor = color.named("secondaryText");
            }
            else {
                leadingArtwork = contentArtwork.createArtworkForResource(objectGraph, "systemimage://exclamationmark.triangle");
                if (objectGraph.client.isVision) {
                    leadingArtworkTintColor = color.named("secondaryText");
                }
                else {
                    leadingArtworkTintColor = color.named("systemRed");
                }
            }
        }
        else {
            leadingArtwork = null;
            leadingArtworkTintColor = null;
        }
        if (objectGraph.client.isTV) {
            if (isSome(objectGraph.bag.externalPurchasesProductPageBannerTextVariant)) {
                const key = `ProductPage.ExternalPurchasesBanner.Focused.Variant${objectGraph.bag.externalPurchasesProductPageBannerTextVariant}`;
                focusedMessage = objectGraph.loc.string(key);
            }
            else {
                focusedMessage = objectGraph.loc.string("ProductPage.ExternalPurchasesBanner.Focused");
            }
        }
        includeBackgroundBorder = true;
    }
    if ((message === null || message === void 0 ? void 0 : message.length) > 0) {
        return new models.Banner(message, focusedMessage, action, fullProductAction, leadingArtwork, leadingArtworkTintColor, includeBackgroundBorder, bannerKind);
    }
    else if (!bannerContext.offerButtonShouldBeDisabled) {
        // If no banner or disabled button for above reasons, show an AppState based Banner if needed
        const appCapabilities = content.appBinaryTraitsFromData(objectGraph, data);
        if (serverData.isDefinedNonNullNonEmpty(appCapabilities)) {
            return createExternalBrowserCompatibilityBanner(objectGraph, appCapabilities);
        }
    }
    return null;
}
function createExternalBrowserBanner(appAction, appCapabilities, message) {
    return new models.Banner(message, undefined, undefined, undefined, undefined, undefined, undefined, undefined, {
        type: "canPerformAppAction",
        appAction: appAction,
        appCapabilities: appCapabilities,
    });
}
function createExternalBrowserCompatibilityBanner(objectGraph, appCapabilities) {
    const message = objectGraph.loc.string("ProductPage.Banner.ExternalBrowser.Message");
    let unknownMessage = message;
    let buyMessage = message;
    let downloadMessage = message;
    let updateMessage = message;
    let openMessage = message;
    // Debug builds append current app state to banner text for testing.
    if (["debug"].includes(objectGraph.client.buildType)) {
        unknownMessage += "\n(Internal: unknown)";
        buyMessage += "\n(Internal: buyOrGet)";
        downloadMessage += "\n(Internal: redownload)";
        updateMessage += "\n(Internal: update)";
        openMessage += "\n(Internal: open)";
    }
    return new models.AppStateBanner(
    /* unknownBanner */ createExternalBrowserBanner("install", appCapabilities, unknownMessage), 
    /* buyBanner */ createExternalBrowserBanner("install", appCapabilities, buyMessage), 
    /* downloadBanner */ createExternalBrowserBanner("install", appCapabilities, downloadMessage), 
    /* updateBanner */ createExternalBrowserBanner("update", appCapabilities, updateMessage), 
    /* openBanner */ createExternalBrowserBanner("launch", appCapabilities, openMessage));
}
/**
 * Creates the banner message to display for external purchases.
 *
 * @param objectGraph Current object graph
 * @param learnMoreTitle The title for a "Learn More" link
 * @param learnMoreAction The action associated with the "Learn More" link, if any
 * @returns The built message, which may or ma
 */
function externalPurchasesMessage(objectGraph, learnMoreTitle, learnMoreAction) {
    if (learnMoreTitle &&
        learnMoreAction &&
        !objectGraph.client.isTV &&
        !objectGraph.client.isWatch &&
        !objectGraph.client.isWeb) {
        if (objectGraph.client.isMac || objectGraph.client.isVision) {
            if (isSome(objectGraph.bag.externalPurchasesProductPageBannerTextVariant)) {
                const key = `ProductPage.ExternalPurchasesBanner.WithLink_WithoutNewline.Variant${objectGraph.bag.externalPurchasesProductPageBannerTextVariant}`;
                return objectGraph.loc.string(key).replace("{learnMoreLink}", learnMoreTitle);
            }
            else {
                return objectGraph.loc
                    .string("ProductPage.ExternalPurchasesBanner.WithLink_WithoutNewline")
                    .replace("{learnMoreLink}", learnMoreTitle);
            }
        }
        else {
            if (isSome(objectGraph.bag.externalPurchasesProductPageBannerTextVariant)) {
                const key = `ProductPage.ExternalPurchasesBanner.WithLink.Variant${objectGraph.bag.externalPurchasesProductPageBannerTextVariant}`;
                return objectGraph.loc.string(key).replace("{learnMoreLink}", learnMoreTitle);
            }
            else {
                return objectGraph.loc
                    .string("ProductPage.ExternalPurchasesBanner.WithLink")
                    .replace("{learnMoreLink}", learnMoreTitle);
            }
        }
    }
    else {
        if (isSome(objectGraph.bag.externalPurchasesProductPageBannerTextVariant)) {
            const key = `ProductPage.ExternalPurchasesBanner.NoLink.Variant${objectGraph.bag.externalPurchasesProductPageBannerTextVariant}`;
            return objectGraph.loc.string(key);
        }
        else {
            return objectGraph.loc.string("ProductPage.ExternalPurchasesBanner.NoLink");
        }
    }
}
/**
 * The message to use when viewing a visionOS only app on other platforms.
 * @param objectGraph Current object graph
 * @param learnMoreTitle Title for the learn more action
 * @param learnMoreAction An optional learn more action
 * @returns A message string
 */
function visionOnlyAppMessage(objectGraph, learnMoreTitle, learnMoreAction) {
    if (learnMoreTitle && learnMoreAction) {
        return objectGraph.loc.string("BANNER_VISION_ONLY_APP_WITH_LINK").replace("{learnMoreLink}", learnMoreTitle);
    }
    else {
        return objectGraph.loc.string("BANNER_VISION_ONLY_APP_NO_LINK");
    }
}
/**
 * Creates a learn more action, for when viewing a visionOS only app on other platforms.
 * @param objectGraph Current object graph
 * @param title The title to assign to the action
 * @param metricsPageInformation Metrics page info
 * @param metricsLocationTracker Metrics location tracker
 * @returns A built action
 */
export function visionOnlyAppLearnMoreAction(objectGraph, title, metricsPageInformation, metricsLocationTracker) {
    const editorialItemId = objectGraph.bag.visionOnlyAppLearnMoreEditorialItemId;
    if (serverData.isNullOrEmpty(editorialItemId)) {
        return null;
    }
    const action = new models.FlowAction("article");
    action.title = title;
    action.pageUrl = `https://apps.apple.com/story/id${editorialItemId}`;
    metricsHelpersClicks.addClickEventToAction(objectGraph, action, {
        id: "LearnMore",
        targetType: "link",
        actionType: "navigate",
        pageInformation: metricsPageInformation,
        locationTracker: metricsLocationTracker,
    });
    return action;
}
//# sourceMappingURL=banner.js.map