import * as validation from "@jet/environment/json/validation";
import { isNothing, 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 contentArtwork from "../content/artwork/artwork";
import * as content from "../content/content";
import * as metricsHelpersImpressions from "../metrics/helpers/impressions";
import * as metricsHelpersLocation from "../metrics/helpers/location";
import * as privacyHeaderShelf from "./privacy-header-shelf";
/**
 * Builder for the privacy types shelf. This shelf is currently used
 * on both the product page, and the privacy detail page.
 */
export function create(objectGraph, data, shelfMetrics) {
    return validation.context("create", () => {
        if (serverData.isNullOrEmpty(data) || objectGraph.client.isWatch) {
            return null;
        }
        const privacyData = mediaAttributes.attributeAsDictionary(data, "privacy");
        if (isNothing(privacyData) || serverData.isNullOrEmpty(privacyData)) {
            return null;
        }
        const shelf = new models.Shelf("privacyType");
        const title = objectGraph.loc.string("PRODUCT_PRIVACY_TITLE");
        metricsHelpersLocation.pushContentLocation(objectGraph, {
            pageInformation: shelfMetrics.metricsPageInformation,
            locationTracker: shelfMetrics.locationTracker,
            targetType: "privacyCard",
            id: `${shelfMetrics.getSequenceId()}`,
            idType: "sequential",
        }, title);
        const privacyTypes = privacyTypesFromData(objectGraph, privacyData, data, "productPage", true, shelfMetrics.metricsPageInformation, shelfMetrics.locationTracker);
        if (privacyTypes === null || privacyTypes.length === 0) {
            return null;
        }
        shelf.items = privacyTypes;
        if (privacyTypes.length <= 2) {
            shelf.presentationHints = { isLowDensity: true };
        }
        // We don't actually want a shelf title, but we populate it temporarily here
        // so that impressions have the appropriate title without causing too much churn.
        shelf.title = title;
        shelfMetrics.addImpressionsToShelf(objectGraph, shelf, "appPrivacy");
        metricsHelpersLocation.popLocation(shelfMetrics.locationTracker);
        metricsHelpersLocation.nextPosition(shelfMetrics.locationTracker);
        shelf.title = null;
        return shelf;
    });
}
/**
 * Creates a list of privacy types from the given data.
 * @param privacyData The privacy data blob
 * @param dataContainer The response data
 * @param style The style that the privacy types should be created with
 * @param includeCategories Whether the privacy categories should be included or not.
 */
export function privacyTypesFromData(objectGraph, privacyData, dataContainer, style, includeCategories, pageInformation, locationTracker) {
    const types = serverData.asArrayOrEmpty(privacyData, "privacyTypes");
    const privacyTypes = [];
    for (const type of types) {
        const typeData = serverData.asJSONData(type);
        if (serverData.isDefinedNonNullNonEmpty(typeData)) {
            const privacyType = privacyTypeFromData(objectGraph, typeData, dataContainer, style, includeCategories, pageInformation, locationTracker);
            if (serverData.isDefinedNonNull(privacyType)) {
                privacyTypes.push(privacyType);
            }
        }
    }
    if (privacyTypes.length === 0) {
        const noDetailsPrivacyType = noDetailsProvidedPrivacyTypeFromDataContainer(objectGraph, dataContainer, style, pageInformation, locationTracker);
        privacyTypes.push(noDetailsPrivacyType);
    }
    for (const privacyType of privacyTypes) {
        const options = {
            id: null,
            kind: null,
            softwareType: null,
            title: privacyType.title,
            pageInformation: pageInformation,
            locationTracker: locationTracker,
            targetType: "privacyCard",
        };
        metricsHelpersImpressions.addImpressionFields(objectGraph, privacyType, options);
        metricsHelpersLocation.nextPosition(locationTracker);
    }
    return privacyTypes;
}
/**
 * Creates a privacy type from the given data.
 * @param data The privacy types data blob
 * @param dataContainer The response data
 * @param style The style that the privacy types should have.
 * @param includeCategories Whether the privacy categories should be included or not.
 */
function privacyTypeFromData(objectGraph, data, dataContainer, style, includeCategories, pageInformation, locationTracker) {
    const identifier = serverData.asString(data, "identifier");
    const title = serverData.asString(data, "privacyType");
    const detail = serverData.asString(data, "description");
    if (isNothing(identifier) ||
        serverData.isNullOrEmpty(identifier) ||
        isNothing(title) ||
        serverData.isNullOrEmpty(title) ||
        isNothing(detail) ||
        serverData.isNullOrEmpty(detail)) {
        return null;
    }
    const artworkResourceUrl = artworkResourceUrlForPrivacyTypeIdentifier(objectGraph, identifier);
    const artwork = artworkFromData(objectGraph, data, artworkResourceUrl);
    const categories = includeCategories ? privacyCategoriesFromData(objectGraph, data, style) : [];
    const purposes = privacyPurposesFromData(objectGraph, data, style);
    const clickAction = privacyTypeClickActionFromDataContainer(objectGraph, dataContainer, identifier, style, pageInformation, locationTracker);
    return new models.PrivacyType(identifier, title, detail, artwork, style, purposes, categories, clickAction);
}
/**
 * Creates  a suitable click action for a privacy type.
 * @param dataContainer The response data
 * @param identifier The identifier for the privacy type
 * @param style The style that the privacy types should have.
 */
function privacyTypeClickActionFromDataContainer(objectGraph, dataContainer, identifier, style, pageInformation, locationTracker) {
    let clickAction = null;
    if (style === "productPage" || style === "intermediateDetailPage") {
        const destinationStyle = isIntermediateDetailPageEnabled(objectGraph) && style === "productPage"
            ? "intermediateDetailPage"
            : "detailPage";
        clickAction = privacyHeaderShelf.privacyDetailActionFromData(objectGraph, dataContainer, destinationStyle, pageInformation, locationTracker, identifier);
    }
    return clickAction;
}
/**
 * Creates a privacy type object to represent the case where the developer has not yet provided any privacy details.
 *
 * @param dataContainer The response data
 * @param style The style that the privacy types should have.
 */
function noDetailsProvidedPrivacyTypeFromDataContainer(objectGraph, dataContainer, style, pageInformation, locationTracker) {
    const identifier = "DATA_NOT_PROVIDED";
    const title = objectGraph.loc.string("PRODUCT_PRIVACY_NO_DETAILS_PROVIDED_TITLE");
    const detail = objectGraph.loc.string("PRODUCT_PRIVACY_NO_DETAILS_PROVIDED_BODY");
    const artwork = contentArtwork.createArtworkForResource(objectGraph, "systemimage://exclamationmark.triangle");
    const clickAction = privacyTypeClickActionFromDataContainer(objectGraph, dataContainer, identifier, style, pageInformation, locationTracker);
    return new models.PrivacyType(identifier, title, detail, artwork, style, [], [], clickAction);
}
/**
 * Creates a list of privacy categories from the given data.
 * @param data The privacy data blob
 * @param privacyTypeStyle The style that the parent privacy type style will have.
 */
function privacyCategoriesFromData(objectGraph, data, privacyTypeStyle) {
    const categories = serverData.asArrayOrEmpty(data, "dataCategories");
    const privacyCategories = [];
    for (const category of categories) {
        const categoryData = serverData.asJSONData(category);
        if (serverData.isDefinedNonNullNonEmpty(categoryData)) {
            const style = privacyTypeStyle === "productPage" ? "productPage" : "detailPage";
            const privacyCategory = privacyCategoryFromData(objectGraph, categoryData, style);
            if (serverData.isDefinedNonNull(privacyCategory)) {
                privacyCategories.push(privacyCategory);
            }
        }
    }
    return privacyCategories;
}
/**
 * Creates a privacy category from the given data.
 * @param data The privacy data blob
 * @param style The style that the privacy category should have.
 */
function privacyCategoryFromData(objectGraph, data, style) {
    const identifier = serverData.asString(data, "identifier");
    const title = serverData.asString(data, "dataCategory");
    if (isNothing(identifier) ||
        serverData.isNullOrEmpty(identifier) ||
        isNothing(title) ||
        serverData.isNullOrEmpty(title)) {
        return null;
    }
    const artworkResourceUrl = artworkResourceUrlForPrivacyCategoryIdentifier(objectGraph, identifier);
    const artwork = artworkFromData(objectGraph, data, artworkResourceUrl);
    if (serverData.isNull(artwork)) {
        return null;
    }
    let dataTypes = [];
    if (style === "detailPage") {
        dataTypes = serverData.asArrayOrEmpty(data, "dataTypes");
    }
    const privacyCategory = new models.PrivacyCategory(identifier, title, artwork, style, dataTypes);
    if (identifier === "USAGE_DATA") {
        privacyCategory.prefersSmallArtwork = true;
    }
    return privacyCategory;
}
/**
 * Creates a list of privacy purposes from the given data.
 * @param data The privacy data blob
 * @param privacyTypeStyle The style that the parent privacy type style will have.
 */
function privacyPurposesFromData(objectGraph, data, privacyTypeStyle) {
    const purposes = serverData.asArrayOrEmpty(data, "purposes");
    const privacyPurposes = [];
    for (const purpose of purposes) {
        const purposeData = serverData.asJSONData(purpose);
        if (serverData.isDefinedNonNullNonEmpty(purposeData)) {
            const privacyPurpose = privacyPurposeFromData(objectGraph, purposeData, privacyTypeStyle);
            if (serverData.isDefinedNonNull(privacyPurpose)) {
                privacyPurposes.push(privacyPurpose);
            }
        }
    }
    return privacyPurposes;
}
/**
 * Creates a privacy purpose from the given data.
 * @param data The privacy data blob
 * @param privacyTypeStyle The style that the parent privacy type style will have.
 */
function privacyPurposeFromData(objectGraph, data, privacyTypeStyle) {
    const identifier = serverData.asString(data, "identifier");
    const title = serverData.asString(data, "purpose");
    const categories = privacyCategoriesFromData(objectGraph, data, privacyTypeStyle);
    if (isNothing(identifier) ||
        serverData.isNullOrEmpty(identifier) ||
        isNothing(title) ||
        serverData.isNullOrEmpty(title) ||
        categories.length === 0) {
        return null;
    }
    return new models.PrivacyPurpose(identifier, title, categories);
}
/**
 * Creates a suitable artwork object for a privacy object, from the given data blob or artwork resource url
 * @param data The privacy object data blob
 * @param artworkResourceUrl An optional artwork resource url
 */
function artworkFromData(objectGraph, data, artworkResourceUrl) {
    let artwork = null;
    if (isSome(artworkResourceUrl) && (artworkResourceUrl === null || artworkResourceUrl === void 0 ? void 0 : artworkResourceUrl.length) > 0) {
        artwork = contentArtwork.createArtworkForResource(objectGraph, artworkResourceUrl);
    }
    if (serverData.isNull(artwork)) {
        const artworkData = serverData.asDictionary(data, "artwork");
        if (serverData.isDefinedNonNull(artworkData)) {
            artwork = content.artworkFromApiArtwork(objectGraph, artworkData, {
                useCase: 0 /* content.ArtworkUseCase.Default */,
                allowingTransparency: true,
            });
        }
    }
    return artwork;
}
/**
 * Maps a privacy type identifier to a known (SF symbol) artwork resource.
 * @param privacyTypeIdentifier the given privacy type identifier.
 */
function artworkResourceUrlForPrivacyTypeIdentifier(objectGraph, privacyTypeIdentifier) {
    switch (privacyTypeIdentifier) {
        case "DATA_NOT_LINKED_TO_YOU":
            return "resource://person.circle.slash";
        case "DATA_USED_TO_TRACK_YOU":
            return "systemimage://person.fill.viewfinder";
        case "DATA_NOT_COLLECTED":
            return "systemimage://checkmark.circle";
        case "DATA_LINKED_TO_YOU":
            return "systemimage://person.circle";
        default:
            return null;
    }
}
/**
 * Maps a privacy category identifier to a known (SF symbol) artwork resource.
 * @param privacyCategoryIdentifier the given privacy category identifier.
 */
function artworkResourceUrlForPrivacyCategoryIdentifier(objectGraph, privacyCategoryIdentifier) {
    switch (privacyCategoryIdentifier) {
        case "FINANCIAL_INFO":
            return "systemimage://creditcard.fill";
        case "CONTACT_INFO":
            return "systemimage://info.circle.fill";
        case "OTHER":
            return "systemimage://ellipsis.circle.fill";
        case "SENSITIVE_INFO":
            return "systemimage://eye.fill";
        case "USAGE_DATA":
            return "systemimage://chart.bar.fill";
        case "CONTACTS":
            return "systemimage://person.circle";
        case "PURCHASES":
            return "systemimage://bag.fill";
        case "LOCATION":
            return "systemimage://location.fill";
        case "HEALTH_AND_FITNESS":
            return "systemimage://heart.circle.fill";
        case "IDENTIFIERS":
            return "resource://person.crop.rectangle.line.fill";
        case "USER_CONTENT":
            return "systemimage://photo.fill.on.rectangle.fill";
        case "BROWSING_HISTORY":
            return "systemimage://clock.fill";
        case "DIAGNOSTICS":
            return "systemimage://gearshape.fill";
        case "SEARCH_HISTORY":
            return "systemimage://magnifyingglass.circle.fill";
        case "BODY":
            return "systemimage://figure";
        case "SURROUNDING":
            return "systemimage://arkit";
        default:
            return null;
    }
}
/**
 * Determines whether the intermediate detail privacy page is enabled.
 */
export function isIntermediateDetailPageEnabled(objectGraph) {
    // Only watchOS has an intermediate detail page
    if (objectGraph.client.deviceType !== "watch") {
        return false;
    }
    return true;
}
//# sourceMappingURL=privacy-types-shelf.js.map