import { isSome } from "@jet/environment";
import { isNothing } from "@jet/environment/types/optional";
import { AppStoreMetricsData, } from "../../api/models/metrics/metrics";
import * as serverData from "../../foundation/json-parsing/server-data";
import * as client from "../../foundation/wrappers/client";
import { EventLinter } from "./event-linter";
import { optOutOfLegacyMetricsIdFieldsProvider } from "./helpers/legacy-metrics-identifier-fields-opt-out";
export function createMetricsClickData(objectGraph, targetId, targetType, eventFields, additionalIncludingFields, isDefaultBrowser) {
    const fields = {};
    Object.assign(fields, eventFields);
    fields["eventType"] = "click";
    fields["targetType"] = targetType;
    fields["targetId"] = targetId;
    const include = ["impressionsSnapshot", "pageFields"];
    if (!preprocessor.GAMES_TARGET) {
        include.push("contentRestrictionReasons");
    }
    if (additionalIncludingFields) {
        include.push(...additionalIncludingFields);
    }
    addWebClientEventFields(objectGraph, fields);
    addAltAb2DataToEventFields(objectGraph, fields);
    return optOutOfLegacyMetricsIdFieldsProvider(objectGraph, new AppStoreMetricsData(fields, include, [], topicFromEventFields(objectGraph, fields), shouldFlushFromEventFields(objectGraph, fields, null, isDefaultBrowser)));
}
export function createMetricsBackClickData(objectGraph, eventFields) {
    const fields = {};
    Object.assign(fields, eventFields);
    fields["actionType"] = "back";
    const clickData = createMetricsClickData(objectGraph, "back", "button", fields);
    return clickData;
}
export function createMetricsPageData(objectGraph, isReferralEligible, isCrossfireReferralCandidate, timingMetrics, eventFields, isDefaultBrowser) {
    const fields = {};
    Object.assign(fields, eventFields);
    fields["eventType"] = "page";
    if (timingMetrics) {
        fields["clientCorrelationKey"] = timingMetrics.clientCorrelationKey;
        fields["requestStartTime"] = timingMetrics.requestStartTime;
        fields["responseStartTime"] = timingMetrics.responseStartTime;
        fields["responseEndTime"] = timingMetrics.responseEndTime;
    }
    const include = ["pageFields", "pageReferrer"];
    if (!preprocessor.GAMES_TARGET) {
        include.push("userContentRestriction");
    }
    if (isReferralEligible) {
        include.push("crossfireReferral");
    }
    else if (isCrossfireReferralCandidate) {
        include.push("crossfireReferralCandidate"); // Only possible when not crossfire eligible.
    }
    addAltAb2DataToEventFields(objectGraph, fields);
    addWebClientEventFields(objectGraph, fields);
    return optOutOfLegacyMetricsIdFieldsProvider(objectGraph, new AppStoreMetricsData(fields, include, [], topicFromEventFields(objectGraph, fields), shouldFlushFromEventFields(objectGraph, fields, null, isDefaultBrowser)));
}
export function createMetricsSearchData(objectGraph, term, target, actionType, actionUrl, eventFields, additionalIncludingFields) {
    const fields = {};
    Object.assign(fields, eventFields);
    fields["term"] = term;
    fields["targetType"] = target;
    fields["actionType"] = actionType;
    if (actionUrl) {
        fields["actionUrl"] = actionUrl; // actionUrl is defined for `hints` but not for searches fired from elsewhere.
    }
    fields["eventType"] = "search";
    const include = ["pageReferrer"];
    if (additionalIncludingFields) {
        include.push(...additionalIncludingFields);
    }
    addWebClientEventFields(objectGraph, fields);
    addAltAb2DataToEventFields(objectGraph, fields);
    return optOutOfLegacyMetricsIdFieldsProvider(objectGraph, new AppStoreMetricsData(fields, include, [], topicFromEventFields(objectGraph, fields), shouldFlushFromEventFields(objectGraph, fields)));
}
export function createMetricsPageRenderFields(objectGraph, timingMetrics, eventFields) {
    const fields = {};
    Object.assign(fields, eventFields);
    fields["eventType"] = "pageRender";
    if (timingMetrics) {
        if (!fields["pageUrl"]) {
            fields["pageUrl"] = timingMetrics.pageURL;
        }
        fields["clientCorrelationKey"] = timingMetrics.clientCorrelationKey;
        fields["platformRequestStartTime"] = timingMetrics.requestStartTime;
        fields["platformResponseStartTime"] = timingMetrics.responseStartTime;
        fields["platformResponseEndTime"] = timingMetrics.responseEndTime;
        fields["platformResponseWasCached"] = timingMetrics.responseWasCached;
        fields["platformJsonParseStartTime"] = timingMetrics.parseStartTime;
        fields["platformJsonParseEndTime"] = timingMetrics.parseEndTime;
    }
    addWebClientEventFields(objectGraph, fields);
    addAltAb2DataToEventFields(objectGraph, fields);
    return fields;
}
/**
 * Create a metrics data for regular impressions.
 * @param objectGraph The dependency graph for the App Store.
 * @param eventFields Base fields to build off on.
 * @param shouldIncludeAdFieldsForPad Whether or not metrics data should include iPad related fields for adverts.
 * @param includeAdRotationFields Whether or not metrics data should include advert related fields.
 * @param hasImpressionsAppendix Whether condensed format search results should track appendix data.
 */
export function createMetricsImpressionsData(objectGraph, eventFields, shouldIncludeAdFieldsForPad, includeAdRotationFields, hasImpressionsAppendix) {
    const fields = {};
    Object.assign(fields, eventFields);
    fields["eventType"] = "impressions";
    fields["impressionQueue"] = "data-metrics";
    fields["eventVersion"] = 4;
    const include = ["impressions", "pageFields", "pageReferrer"];
    if (!preprocessor.GAMES_TARGET) {
        include.push("contentRestrictionReasons");
    }
    if (shouldIncludeAdFieldsForPad) {
        include.push("advertDeviceWindow");
    }
    if (includeAdRotationFields) {
        include.push("advertRotation");
    }
    if (hasImpressionsAppendix) {
        include.push("impressionsAppendix");
    }
    addWebClientEventFields(objectGraph, fields);
    addAltAb2DataToEventFields(objectGraph, fields);
    return optOutOfLegacyMetricsIdFieldsProvider(objectGraph, new AppStoreMetricsData(fields, include, ["eventVersion"], topicFromEventFields(objectGraph, fields), shouldFlushFromEventFields(objectGraph, fields)));
}
/**
 * Create a metrics data for fast impressions, a special type for SearchAds on Search Page.
 * Included fields assume fields are for search page w/ Ads.
 * @param baseFields Base fields to build off on.
 */
export function createMetricsFastImpressionsData(objectGraph, baseFields, pageInformation) {
    var _a, _b;
    const shouldIncludeAdFieldsForPad = serverData.isDefinedNonNull(pageInformation.iAdInfo) &&
        objectGraph.client.isPad &&
        (isNothing(pageInformation.iAdInfo.missedOpportunityReason) ||
            pageInformation.iAdInfo.missedOpportunityReason.length === 0);
    const shouldIncludeAdRotationFields = (_b = (_a = pageInformation.iAdInfo) === null || _a === void 0 ? void 0 : _a.shouldIncludeAdRotationFields) !== null && _b !== void 0 ? _b : false;
    const exclude = [];
    const fields = createMetricsImpressionsData(objectGraph, baseFields, shouldIncludeAdFieldsForPad, shouldIncludeAdRotationFields, false).fields;
    fields["impressionQueue"] = "data-metrics-impressions-low-latency";
    if (pageInformation !== null && serverData.isDefinedNonNull(pageInformation.iAdInfo)) {
        const eventVersion = pageInformation.iAdInfo.fastImpressionsEventVersion;
        fields["eventVersion"] = eventVersion;
        exclude.push("eventVersion");
        // Make some manual adjustments to events for v5.
        if (eventVersion === 5) {
            // Indicates the viewable area where elements can be impressed excludes the tab bar
            fields["viewableArea"] = "excludingTabBar";
            // Remove the `iAdPlacementId` for v5. It's added for compatibility with v4 impressions.
            delete fields["iAdPlacementId"];
        }
    }
    const include = ["fastImpressions", "pageFields", "pageReferrer"];
    if (shouldIncludeAdFieldsForPad) {
        include.push("advertDeviceWindow");
    }
    if (shouldIncludeAdRotationFields) {
        include.push("advertRotation");
    }
    return optOutOfLegacyMetricsIdFieldsProvider(objectGraph, new AppStoreMetricsData(fields, include, exclude, topicFromEventFields(objectGraph, fields), shouldFlushFromEventFields(objectGraph, fields, pageInformation)));
}
export function createMetricsMediaData(objectGraph, eventFields) {
    const fields = {};
    Object.assign(fields, eventFields);
    fields["eventType"] = "media";
    addWebClientEventFields(objectGraph, fields);
    addAltAb2DataToEventFields(objectGraph, fields);
    return optOutOfLegacyMetricsIdFieldsProvider(objectGraph, new AppStoreMetricsData(fields, [], [], topicFromEventFields(objectGraph, fields), shouldFlushFromEventFields(objectGraph, fields)));
}
export function createMetricsMediaClickData(objectGraph, targetId, targetType, eventFields) {
    const fields = {};
    Object.assign(fields, eventFields);
    fields["eventType"] = "click";
    fields["targetType"] = targetType;
    fields["targetId"] = targetId;
    const include = ["pageFields"];
    addWebClientEventFields(objectGraph, fields);
    addAltAb2DataToEventFields(objectGraph, fields);
    return optOutOfLegacyMetricsIdFieldsProvider(objectGraph, new AppStoreMetricsData(fields, include, [], topicFromEventFields(objectGraph, fields), shouldFlushFromEventFields(objectGraph, fields)));
}
function shouldFlushFromEventFields(objectGraph, eventFields, pageInformation = null, isDefaultBrowser) {
    var _a, _b;
    const eventType = eventFields["eventType"];
    let shouldFlush = false;
    if (!serverData.isDefinedNonNullNonEmpty(eventType)) {
        return shouldFlush;
    }
    const isDefaultBrowserContext = isDefaultBrowser !== null && isDefaultBrowser !== void 0 ? isDefaultBrowser : false;
    switch (eventType) {
        case "click":
            shouldFlush =
                serverData.asBooleanOrFalse(eventFields, EventLinter.hasIAdData) ||
                    isDefaultBrowserContext;
            break;
        case "exit":
            shouldFlush = true;
            break;
        case "impressions":
            shouldFlush = serverData.asBooleanOrFalse(eventFields, EventLinter.hasIAdData);
            // Not my best work here.
            // For most ad placements on a page, it's fine to check the `hasIAdData` as an indicator for whether we should flush after a given event.
            // The challenge for the product page placements is that they're fetched asynchronously, and we don't create an entirely new impressions
            // event when that happens (we just update fields within the event via the `pageChange` mechanism). To ensure that fast impression events on
            // the product page are actually fast, we have to force the events to flush if they meet the below conditions that effectively guarantee
            // we will be impressing something on the low latency queue.
            if (eventFields["impressionQueue"] === "data-metrics-impressions-low-latency" &&
                (((_a = pageInformation === null || pageInformation === void 0 ? void 0 : pageInformation.iAdInfo) === null || _a === void 0 ? void 0 : _a.placementType) === "productPageYMAL" ||
                    ((_b = pageInformation === null || pageInformation === void 0 ? void 0 : pageInformation.iAdInfo) === null || _b === void 0 ? void 0 : _b.placementType) === "productPageYMALDuringDownload")) {
                shouldFlush = true;
            }
            break;
        case "page":
            // rdar://98487650 (CL seed: Product Page observed lower % of events coming in <2 mins ( page change + page events ))
            // In order to resolve issues with flushing timeliness in the PPE: rdar://93127678 ([Metrics] Dismissing store sheet does not fire clickstream events)
            // we allow page events with ad data in them to cause a flush on product pages in the PPE.
            // We also pre-emptively flush for page events where it's the default browser flow in order to "prewarm" the metrics pipeline, ensuring flushes can occur
            // if and when the user taps "Open" on an installed app.
            const isProductPageExtension = objectGraph.host.clientIdentifier === client.productPageExtensionIdentifier;
            shouldFlush =
                isProductPageExtension &&
                    (serverData.asBooleanOrFalse(eventFields, EventLinter.hasIAdData) ||
                        isDefaultBrowserContext);
            break;
        default:
            break;
    }
    const isSubscribePageExtensionEnterExitEventsEnabled = objectGraph.host.isiOS;
    if (objectGraph.host.clientIdentifier === client.subscribePageExtensionIdentifier &&
        !isSubscribePageExtensionEnterExitEventsEnabled) {
        // <rdar://problem/55865604> Metrics: missing metrics events for arcade upsell from springboard app open on unsubscribed user
        // Until a native fix is in to address enter/exit events in SPE (subscribePageExtensionEnterExitEvents), we
        // need to force events in the SubscribePageExtension to trigger a flush.
        shouldFlush = true;
    }
    return shouldFlush;
}
function topicFromEventFields(objectGraph, eventFields) {
    const topic = eventFields["topic"] || objectGraph.bag.metricsTopic;
    return topic;
}
function addAltAb2DataToEventFields(objectGraph, eventFields) {
    if (objectGraph.bag.isMetricsAb2DataFallbackEnabled && isSome(objectGraph.experimentCache)) {
        eventFields["alt_ab2_data"] = JSON.stringify(objectGraph.experimentCache.createAb2Data());
    }
}
/**
 * Attach expected metrics fields specific to the "web" client, if necessary
 */
function addWebClientEventFields(objectGraph, eventFields) {
    var _a;
    if (!objectGraph.client.isWeb) {
        return;
    }
    // The `platformContext` field is expected to reflect the "platform" that the user is browsing
    // at the time of the event
    eventFields["platformContext"] = (_a = objectGraph.activeIntent) === null || _a === void 0 ? void 0 : _a.previewPlatform;
}
//# sourceMappingURL=builder.js.map