import * as validation from "@jet/environment/json/validation";
import { isNothing } 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 mediaRelationships from "../../foundation/media/relationships";
import { Path, Protocol } from "../../foundation/network/url-constants";
import * as urls from "../../foundation/network/urls";
import * as constants from "../../foundation/util/constants";
import * as contentAttributes from "../content/attributes";
import * as metricsHelpersClicks from "../metrics/helpers/clicks";
import * as linksShelf from "../product-page/shelves/links-shelf";
import * as privacyTypesShelf from "./privacy-types-shelf";
import { makeRoutableArticlePageCanonicalUrl } from "../today/routable-article-page-url-utils";
import { makeRoutableArticlePageIntent } from "../../api/intents/routable-article-page-intent";
import { getPlatform } from "../preview-platform";
import { getLocale } from "../locale";
/**
 * Builder for the privacy header shelf. This shelf is currently used
 * on both the product page, and the privacy detail page.
 */
export function create(objectGraph, data, pageInformation, locationTracker) {
    return validation.context("privacyShelf", () => {
        if (serverData.isNullOrEmpty(data)) {
            return null;
        }
        const shelf = new models.Shelf("privacyHeader");
        shelf.title = objectGraph.loc.string("PRODUCT_PRIVACY_TITLE");
        const privacyHeader = privacyHeaderFromData(objectGraph, data, false, false, pageInformation, locationTracker);
        shelf.items = [privacyHeader];
        if (objectGraph.client.deviceType !== "watch" && objectGraph.client.deviceType !== "tv") {
            shelf.seeAllAction = privacyDetailActionFromData(objectGraph, data, "detailPage", pageInformation, locationTracker, null);
        }
        return shelf;
    });
}
/**
 * Creates a privacy header object.
 * @param data The data blob
 * @param isDetailHeader Whether this header is intended to be displayed on the detail page
 * @param isDetailData Whether the included data is for the detail page
 */
export function privacyHeaderFromData(objectGraph, data, isDetailHeader, isDetailData, pageInformation, locationTracker) {
    return validation.context("createPrivacyHeaderFromData", () => {
        const bodyText = bodyTextFromData(objectGraph, data, isDetailHeader, isDetailData, pageInformation, locationTracker);
        let seeDetailsAction;
        let privacyPolicyAction;
        const privacyDefinitionsText = privacyDefinitionsTextFromData(objectGraph, data, isDetailHeader, pageInformation, locationTracker);
        let privacyDefinitionsAction;
        let learnMoreText;
        let learnMoreAction;
        if (objectGraph.client.isTV || objectGraph.client.isWatch) {
            if (!isDetailHeader) {
                const destinationPrivacyTypeStyle = privacyTypesShelf.isIntermediateDetailPageEnabled(objectGraph)
                    ? "intermediateDetailPage"
                    : "detailPage";
                seeDetailsAction = privacyDetailActionFromData(objectGraph, data, destinationPrivacyTypeStyle, pageInformation, locationTracker, null);
            }
            privacyPolicyAction = privacyPolicyActionFromData(objectGraph, data, pageInformation, locationTracker);
        }
        if (isDetailHeader) {
            if (objectGraph.client.isWatch || objectGraph.client.isTV) {
                privacyDefinitionsAction = createPrivacyDefinitionsAction(objectGraph, pageInformation, locationTracker);
            }
            learnMoreText = learnMoreTextFromData(objectGraph, data, isDetailHeader, pageInformation, locationTracker);
            if (serverData.isDefinedNonNullNonEmpty(learnMoreText)) {
                learnMoreAction = createLearnMoreAction(objectGraph, pageInformation, locationTracker);
            }
        }
        const supplementaryItems = [];
        if (serverData.isDefinedNonNull(privacyDefinitionsText)) {
            const supplementaryItem = new models.PrivacyHeaderSupplementaryItem(privacyDefinitionsText, privacyDefinitionsAction);
            supplementaryItems.push(supplementaryItem);
        }
        if (serverData.isDefinedNonNull(learnMoreText)) {
            const supplementaryItem = new models.PrivacyHeaderSupplementaryItem(learnMoreText, learnMoreAction);
            supplementaryItems.push(supplementaryItem);
        }
        let privacyTypes = [];
        if ((objectGraph.client.isWatch || objectGraph.client.isTV) && !isDetailHeader) {
            privacyTypes = privacyTypesFromData(objectGraph, data, isDetailData, "productPage", pageInformation, locationTracker);
        }
        const bodyActions = [];
        if (objectGraph.client.isTV) {
            if (serverData.isDefinedNonNull(seeDetailsAction)) {
                bodyActions.push(seeDetailsAction);
            }
            if (serverData.isDefinedNonNull(privacyPolicyAction)) {
                bodyActions.push(privacyPolicyAction);
            }
        }
        if (objectGraph.client.isWatch) {
            if (serverData.isDefinedNonNull(privacyPolicyAction)) {
                bodyActions.push(privacyPolicyAction);
            }
        }
        return new models.PrivacyHeader(bodyText, isDetailHeader, privacyTypes, bodyActions, supplementaryItems, seeDetailsAction);
    });
}
/**
 * Creates the main body text for the header.
 * @param data The data blob
 * @param isDetailHeader Whether this header is intended to be displayed on the detail page
 * @param isDetailData Whether the included data is for the detail page
 */
function bodyTextFromData(objectGraph, data, isDetailHeader, isDetailData, pageInformation, locationTracker) {
    let text;
    let textType = "text/x-apple-as3-nqml";
    const developer = mediaRelationships.relationshipData(objectGraph, data, "developer");
    const isAppleOwnedDeveloperId = serverData.isDefinedNonNullNonEmpty(developer) && constants.appleOwnedDeveloperIds.indexOf(developer.id) > -1;
    if (isDetailHeader && !isAppleOwnedDeveloperId) {
        text = objectGraph.loc.string("PRODUCT_PRIVACY_DETAIL_HEADER_TEMPLATE");
    }
    else {
        text = objectGraph.loc.string("PRODUCT_PRIVACY_HEADER_TEMPLATE");
    }
    const privacyTypes = privacyTypesFromData(objectGraph, data, isDetailData, "detailPage", pageInformation, locationTracker);
    const privacyDataNotProvided = (privacyTypes.length === 1 && privacyTypes[0].identifier === "DATA_NOT_PROVIDED") || privacyTypes.length === 0;
    if (privacyDataNotProvided) {
        text = objectGraph.loc.string("PRODUCT_PRIVACY_HEADER_NO_DETAILS_TEMPLATE");
    }
    // Developer name
    const developerName = mediaAttributes.attributeAsString(data, "artistName");
    if (serverData.isDefinedNonNull(developerName)) {
        text = text.replace("{developerName}", "<b>" + developerName + "</b>");
    }
    else {
        // This shouldn't happen, but just in case, fallback to the text with no developer name placeholder
        if (privacyDataNotProvided) {
            text = objectGraph.loc.string("PRODUCT_PRIVACY_FALLBACK_HEADER_NO_DETAILS_TEMPLATE");
        }
        else {
            if (isDetailHeader) {
                text = objectGraph.loc.string("PRODUCT_PRIVACY_FALLBACK_DETAIL_HEADER_TEMPLATE");
            }
            else {
                text = objectGraph.loc.string("PRODUCT_PRIVACY_FALLBACK_HEADER_TEMPLATE");
            }
        }
        textType = "text/plain";
    }
    // Privacy policy link
    const privacyPolicyLinkText = objectGraph.loc.string("PRODUCT_PRIVACY_SUMMARY_PRIVACY_POLICY_LINK");
    text = text.replace("{privacyPolicyLink}", privacyPolicyLinkText);
    const privacyPolicyAction = privacyPolicyActionFromData(objectGraph, data, pageInformation, locationTracker);
    const linkedSubstrings = {};
    if (serverData.isDefinedNonNull(privacyPolicyAction)) {
        linkedSubstrings[privacyPolicyLinkText] = privacyPolicyAction;
    }
    // Manage choices
    if (isDetailHeader) {
        if (objectGraph.client.isiOS ||
            objectGraph.client.isMac ||
            objectGraph.client.isVision ||
            objectGraph.client.isWeb) {
            const managePrivacyChoicesAction = managePrivacyChoicesActionFromData(objectGraph, data, pageInformation, locationTracker);
            if (serverData.isDefinedNonNull(managePrivacyChoicesAction)) {
                const managePrivacyChoicesLink = objectGraph.loc.string("PRODUCT_PRIVACY_MANAGE_CHOICES_LINK");
                text += "<br><br>";
                text += objectGraph.loc
                    .string("PRODUCT_PRIVACY_MANAGE_CHOICES_TEMPLATE")
                    .replace("{manageChoicesLink}", managePrivacyChoicesLink);
                managePrivacyChoicesAction.title = managePrivacyChoicesLink;
                linkedSubstrings[managePrivacyChoicesLink] = managePrivacyChoicesAction;
            }
        }
        else {
            text += "<br><br>";
            text += objectGraph.loc.string("PRODUCT_PRIVACY_MANAGE_CHOICES_NO_LINK");
        }
    }
    const styledText = new models.StyledText(text, textType);
    return new models.LinkableText(styledText, linkedSubstrings);
}
/**
 * Creates the action for linking to the developer's privacy policy.
 */
function privacyPolicyActionFromData(objectGraph, data, pageInformation, locationTracker) {
    let privacyPolicyLinkAction;
    if (objectGraph.client.isTV) {
        const hasPrivacyPolicy = contentAttributes.contentAttributeAsBooleanOrFalse(objectGraph, data, "hasPrivacyPolicyText");
        if (!hasPrivacyPolicy) {
            return null;
        }
        const url = linksShelf.privacyPolicyUrlFromData(objectGraph, data);
        if (serverData.isNull(url)) {
            return null;
        }
        const action = new models.FlowAction("unknown");
        action.pageUrl = url;
        privacyPolicyLinkAction = action;
    }
    else {
        const privacyPolicyUrl = contentAttributes.contentAttributeAsString(objectGraph, data, "privacyPolicyUrl");
        if (isNothing(privacyPolicyUrl) || serverData.isNullOrEmpty(privacyPolicyUrl)) {
            return null;
        }
        privacyPolicyLinkAction = new models.ExternalUrlAction(privacyPolicyUrl, false);
    }
    privacyPolicyLinkAction.title = objectGraph.loc.string("PRODUCT_PRIVACY_SUMMARY_PRIVACY_POLICY_BUTTON_TITLE");
    metricsHelpersClicks.addClickEventToAction(objectGraph, privacyPolicyLinkAction, {
        targetType: "link",
        id: "privacyPolicy",
        pageInformation: pageInformation,
        locationTracker: locationTracker,
    });
    return privacyPolicyLinkAction;
}
/**
 * Creates the action for linking to the developer's manage privacy choices URL.
 */
function managePrivacyChoicesActionFromData(objectGraph, data, pageInformation, locationTracker) {
    const privacyDetailsData = mediaAttributes.attributeAsDictionary(data, "privacyDetails");
    const managePrivacyChoicesUrl = serverData.asString(privacyDetailsData, "managePrivacyChoicesUrl");
    if (isNothing(managePrivacyChoicesUrl) || serverData.isNullOrEmpty(managePrivacyChoicesUrl)) {
        return null;
    }
    const managePrivacyChoicesAction = new models.ExternalUrlAction(managePrivacyChoicesUrl, false);
    metricsHelpersClicks.addClickEventToAction(objectGraph, managePrivacyChoicesAction, {
        targetType: "link",
        id: "managePrivacyChoices",
        pageInformation: pageInformation,
        locationTracker: locationTracker,
    });
    return managePrivacyChoicesAction;
}
/**
 * Creates the text for linking to the learn more page.
 * @param data The data blob
 * @param isDetailHeader Whether this header is intended to be displayed on the detail page
 */
function learnMoreTextFromData(objectGraph, data, isDetailHeader, pageInformation, locationTracker) {
    if (!isDetailHeader || objectGraph.client.isTV) {
        return null;
    }
    const learnMoreLink = objectGraph.loc.string("PRODUCT_PRIVACY_LEARN_MORE_LINK");
    const learnMoreAction = createLearnMoreAction(objectGraph, pageInformation, locationTracker);
    let text;
    const linkedSubstrings = {};
    if (serverData.isNull(learnMoreAction) || objectGraph.client.isWatch) {
        text = objectGraph.loc.string("PRODUCT_PRIVACY_LEARN_MORE_NO_LINK");
    }
    else {
        text = objectGraph.loc.string("PRODUCT_PRIVACY_LEARN_MORE_TEMPLATE").replace("{learnMoreLink}", learnMoreLink);
        learnMoreAction.title = learnMoreLink;
        linkedSubstrings[learnMoreLink] = learnMoreAction;
    }
    const styledText = new models.StyledText(text, "text/plain");
    return new models.LinkableText(styledText, linkedSubstrings);
}
/**
 * Creates the action for linking to the learn more URL.
 */
export function createLearnMoreAction(objectGraph, pageInformation, locationTracker) {
    const editorialItemId = objectGraph.bag.appPrivacyLearnMoreEditorialItemId;
    if (isNothing(editorialItemId) || editorialItemId.length === 0) {
        return null;
    }
    const learnMoreAction = new models.FlowAction("article");
    learnMoreAction.title = objectGraph.loc.string("PRODUCT_PRIVACY_LEARN_MORE_LINK");
    learnMoreAction.pageUrl = `https://apps.apple.com/story/id${editorialItemId}`;
    metricsHelpersClicks.addClickEventToAction(objectGraph, learnMoreAction, {
        targetType: "button",
        id: "privacyLearnMore",
        pageInformation: pageInformation,
        locationTracker: locationTracker,
    });
    if (objectGraph.client.isVision) {
        learnMoreAction.presentation = "sheetPresent";
    }
    if (objectGraph.client.isWeb) {
        const destination = makeRoutableArticlePageIntent({
            ...getLocale(objectGraph),
            ...getPlatform(objectGraph),
            id: editorialItemId,
        });
        const pageUrlString = makeRoutableArticlePageCanonicalUrl(objectGraph, destination);
        learnMoreAction.pageUrl = pageUrlString;
        learnMoreAction.destination = destination;
    }
    return learnMoreAction;
}
/**
 * Creates the text for linking to the privacy definitions EI.
 * @param data The data blob
 * @param isDetailHeader Whether this header is intended to be displayed on the detail page
 */
function privacyDefinitionsTextFromData(objectGraph, data, isDetailHeader, pageInformation, locationTracker) {
    if (!isDetailHeader) {
        return null;
    }
    const privacyDefinitionsLink = objectGraph.loc.string("PRODUCT_PRIVACY_DEFINITIONS_LINK");
    const text = objectGraph.loc
        .string("PRODUCT_PRIVACY_DEFINITIONS_LINK_TEMPLATE")
        .replace("{privacyDefinitionsLink}", privacyDefinitionsLink);
    const privacyDefinitionsAction = createPrivacyDefinitionsAction(objectGraph, pageInformation, locationTracker);
    if (serverData.isNull(privacyDefinitionsAction)) {
        return null;
    }
    privacyDefinitionsAction.title = privacyDefinitionsLink;
    const linkedSubstrings = {};
    linkedSubstrings[privacyDefinitionsLink] = privacyDefinitionsAction;
    const styledText = new models.StyledText(text, "text/plain");
    return new models.LinkableText(styledText, linkedSubstrings);
}
/**
 * Creates the action for linking to the privacy definitions page.
 */
export function createPrivacyDefinitionsAction(objectGraph, pageInformation, locationTracker) {
    const editorialItemId = objectGraph.bag.appPrivacyDefinitionsEditorialItemId;
    if (isNothing(editorialItemId) || editorialItemId.length === 0) {
        return null;
    }
    const privacyDefinitionsAction = new models.FlowAction("article");
    privacyDefinitionsAction.title = objectGraph.loc.string("PRODUCT_PRIVACY_DEFINITIONS_LINK");
    privacyDefinitionsAction.pageUrl = `https://apps.apple.com/story/id${editorialItemId}`;
    if (objectGraph.client.isWeb) {
        const destination = makeRoutableArticlePageIntent({
            ...getLocale(objectGraph),
            ...getPlatform(objectGraph),
            id: editorialItemId,
        });
        const pageUrlString = makeRoutableArticlePageCanonicalUrl(objectGraph, destination);
        privacyDefinitionsAction.pageUrl = pageUrlString;
        privacyDefinitionsAction.destination = destination;
    }
    metricsHelpersClicks.addClickEventToAction(objectGraph, privacyDefinitionsAction, {
        targetType: "button",
        id: "privacyDefinitions",
        pageInformation: pageInformation,
        locationTracker: locationTracker,
    });
    return privacyDefinitionsAction;
}
/**
 * Creates a list of privacy types, suitable for associating with the header.
 * In practice, this means that the categories will only be included when necessary,
 * to keep the data size as small as possible.
 */
export function privacyTypesFromData(objectGraph, data, isDetailData, destinationPrivacyTypeStyle, pageInformation, locationTracker) {
    var _a;
    let privacyTypes = [];
    const privacyDataKey = isDetailData ? "privacyDetails" : "privacy";
    const privacyData = mediaAttributes.attributeAsDictionary(data, privacyDataKey);
    if (serverData.isDefinedNonNullNonEmpty(privacyData)) {
        const includeCategories = objectGraph.client.deviceType !== "watch" || destinationPrivacyTypeStyle === "intermediateDetailPage";
        privacyTypes =
            (_a = privacyTypesShelf.privacyTypesFromData(objectGraph, privacyData, data, destinationPrivacyTypeStyle, includeCategories, pageInformation, locationTracker)) !== null && _a !== void 0 ? _a : [];
        // If we only have a single privacy type, with no categories, force it to display in `productPage` style
        // even on the intermediate detail page, as it has a nicer appearance for this case.
        if (privacyTypes.length === 1 && privacyTypes[0].categories.length === 0) {
            privacyTypes[0].style = "productPage";
        }
    }
    return privacyTypes;
}
/**
 * Creates an incomplete privacy detail page, sidepacking the privacy header shelf.
 * On watchOS, when creating the `intermediateDetailPage`, we also sidepack the privacy types themselves,
 * resulting in a complete (intermediate) detail page.
 */
export function privacyDetailSidepackPageFromData(objectGraph, data, destinationPrivacyTypeStyle, pageInformation, locationTracker) {
    const shelves = [];
    // Always sidepack the header, unless this will be the detail page for the watch,
    // which does not display the header
    if (objectGraph.client.deviceType !== "watch" || destinationPrivacyTypeStyle !== "detailPage") {
        const headerShelf = new models.Shelf("privacyHeader");
        const privacyHeader = privacyHeaderFromData(objectGraph, data, true, false, pageInformation, locationTracker);
        headerShelf.items = [privacyHeader];
        headerShelf.presentationHints = { isFirstShelf: true };
        shelves.push(headerShelf);
    }
    if (
    // On the watch, we want to sidepack the privacy types if coming from the product page
    // as we already have all the information we need, and we can avoid having an incomplete page
    (objectGraph.client.isWatch && destinationPrivacyTypeStyle === "intermediateDetailPage") ||
        // The "detailPage" on the "web" client is presented as a modal, so we want to sidepack all
        // of the data so it can display is immediately
        (objectGraph.client.isWeb && destinationPrivacyTypeStyle === "detailPage")) {
        const privacyTypes = privacyTypesFromData(objectGraph, data, objectGraph.client.isWeb, destinationPrivacyTypeStyle, pageInformation, locationTracker);
        const shelf = new models.Shelf("privacyType");
        if (privacyTypes.length > 0) {
            shelf.items = privacyTypes;
            shelves.push(shelf);
        }
    }
    const page = new models.GenericPage(shelves);
    if (objectGraph.client.deviceType !== "watch" || destinationPrivacyTypeStyle === "detailPage") {
        page.isIncomplete = true;
    }
    page.title = objectGraph.loc.string("PRODUCT_PRIVACY_TITLE");
    if (objectGraph.client.isMac) {
        page.presentationOptions = ["prefersLargeTitle"];
    }
    return page;
}
/**
 * Creates the action for linking to the privacy detail page.
 */
export function privacyDetailActionFromData(objectGraph, data, destinationPrivacyTypeStyle, pageInformation, locationTracker, scrollFocusPrivacyTypeId) {
    if (serverData.isNull(data.id)) {
        return null;
    }
    const seeDetailsAction = new models.FlowAction("privacyDetail");
    seeDetailsAction.title = objectGraph.loc.string("ACTION_SEE_DETAILS");
    seeDetailsAction.pageData = privacyDetailSidepackPageFromData(objectGraph, data, destinationPrivacyTypeStyle, pageInformation, locationTracker);
    const productType = data.type === "app-bundles" ? Path.productBundle : Path.product;
    let query;
    if (serverData.isDefinedNonNullNonEmpty(scrollFocusPrivacyTypeId)) {
        query = { privacyTypeId: scrollFocusPrivacyTypeId };
    }
    const pageUrl = urls.URL.fromComponents(Protocol.internal, null, `/${Path.privacyDetail}/${productType}/${data.id}`, query);
    seeDetailsAction.pageUrl = pageUrl.build();
    const seeDetailsClickOptions = {
        targetType: "button",
        id: "seeDetails",
        pageInformation: pageInformation,
        locationTracker: locationTracker,
    };
    if (serverData.isDefinedNonNull(scrollFocusPrivacyTypeId)) {
        seeDetailsClickOptions.targetType = "privacyCard";
        seeDetailsClickOptions.id = scrollFocusPrivacyTypeId;
    }
    metricsHelpersClicks.addClickEventToAction(objectGraph, seeDetailsAction, seeDetailsClickOptions);
    return seeDetailsAction;
}
//# sourceMappingURL=privacy-header-shelf.js.map