import * as validation from "@jet/environment/json/validation";
import * as models from "../../api/models";
import * as base from "../../api/models/base";
import * as serverData from "../../foundation/json-parsing/server-data";
import * as mediaAttributes from "../../foundation/media/attributes";
import * as mediaRelationship from "../../foundation/media/relationships";
import * as http from "../../foundation/network/http";
import * as urls from "../../foundation/network/urls";
import * as externalDeepLink from "../linking/external-deep-link";
import * as lockups from "../lockups/lockups";
import * as metricsUtil from "../metrics/helpers/util";
import * as offers from "../offers/offers";
import * as reviews from "../product-page/reviews";
import * as sharing from "../sharing";
import * as contentArtwork from "./artwork/artwork";
import * as content from "./content";
import * as contentDeviceFamily from "./device-family";
import { isSome } from "@jet/environment";
import { Request } from "../../foundation/media/data-fetching";
import { buildURLFromRequest } from "../../foundation/media/url-builder";
/**
 * Create and return the flow preview actions configuration for a product.
 * @param objectGraph
 * @param data  The response data to read from.
 * @param includeOfferAction  Whether to include an offer action, where possible
 * @param clientIdentifierOverride  The suggested client identifier for the given product
 * @param clickAction  The flow action for viewing the product
 * @param metricsOptions The metrics options to use for reporting metrics actions.
 * @param metricsClickOptions  TThe metrics click options for the product
 * @param externalDeepLinkUrl
 * @returns A configuration object for flow preview actions that can be taken on the product
 */
export function flowPreviewActionsConfigurationForProductFromData(objectGraph, data, includeOfferAction, clientIdentifierOverride, clickAction, metricsOptions, metricsClickOptions, externalDeepLinkUrl, lockupSubtitle, lockupTitle) {
    return validation.context("flowPreviewActionsConfigurationForProductFromData", () => {
        // Flow preview is only supported on iOS
        if (objectGraph.client.deviceType !== "phone" && objectGraph.client.deviceType !== "pad") {
            return null;
        }
        const productData = productDataFromData(objectGraph, data);
        if (!serverData.isDefinedNonNullNonEmpty(productData)) {
            return null;
        }
        const actions = [];
        // Offer
        let offerActionIndex = null;
        let offerDisplayProperties = null;
        const isPreorder = mediaAttributes.attributeAsBooleanOrFalse(productData, "isPreorder");
        if (includeOfferAction) {
            const isArcade = content.isArcadeSupported(objectGraph, productData);
            const offerType = lockups.offerTypeForMediaType(objectGraph, productData.type, isArcade);
            const offerAction = offerActionFromData(objectGraph, productData, isPreorder, isArcade, offerType, clientIdentifierOverride, metricsClickOptions);
            offerDisplayProperties = offers.displayPropertiesFromOfferAction(objectGraph, offerAction, offerType, productData, isPreorder, false, null, null, null, null, "flowPreview");
            const wrappedOfferAction = wrappedOfferActionFromData(objectGraph, productData, offerAction, isPreorder, clientIdentifierOverride, metricsClickOptions, metricsOptions, externalDeepLinkUrl);
            if (serverData.isDefinedNonNull(wrappedOfferAction) &&
                serverData.isDefinedNonNull(offerDisplayProperties)) {
                offerActionIndex = actions.length;
                wrappedOfferAction.artwork = contentArtwork.createArtworkForResource(objectGraph, "systemimage://arrow.down.circle");
                actions.push(wrappedOfferAction);
            }
        }
        // Share
        const shareAction = shareActionFromData(objectGraph, productData, metricsOptions);
        if (serverData.isDefinedNonNull(shareAction)) {
            actions.push(shareAction);
        }
        // Reviews
        const shouldSuppressReviews = reviews.shouldSuppressReviews(objectGraph, productData);
        const shouldShowRatingsAndReviews = !isPreorder && !shouldSuppressReviews;
        if (shouldShowRatingsAndReviews) {
            // See ratings & reviews
            if (serverData.isDefinedNonNull(clickAction) &&
                clickAction instanceof models.FlowAction &&
                (clickAction.pageData instanceof models.ProductPage ||
                    clickAction.pageData instanceof models.ShelfBasedProductPage)) {
                const seeRatingsAndReviewsAction = seeRatingsAndReviewsActionFromData(objectGraph, productData, clickAction);
                if (serverData.isDefinedNonNull(seeRatingsAndReviewsAction)) {
                    actions.push(seeRatingsAndReviewsAction);
                }
            }
            // Write a review
            const isTvOnlyApp = contentDeviceFamily.dataOnlyHasDeviceFamily(objectGraph, data, "tvos");
            if (!isTvOnlyApp) {
                const writeReviewAction = writeReviewActionFromData(objectGraph, productData, lockupSubtitle, lockupTitle);
                if (serverData.isDefinedNonNull(writeReviewAction)) {
                    actions.push(writeReviewAction);
                }
            }
        }
        return new models.FlowPreviewActionsConfiguration(actions, offerDisplayProperties, offerActionIndex);
    });
}
/**
 * Create and return the flow preview configuration for a review object
 * @param data  The response data to read from.
 * @param deviceId  The UUID for the user's device.
 * @param adamId    The adam id of the product associated with the review
 * @returns A configuration object for flow preview actions that can be taken on the review
 */
export function flowPreviewActionsConfigurationForReviewFromData(objectGraph, data, deviceId, adamId, reviewText) {
    var _a;
    if (serverData.isNullOrEmpty(data) ||
        (objectGraph.client.deviceType !== "phone" &&
            objectGraph.client.deviceType !== "pad" &&
            objectGraph.client.deviceType !== "mac")) {
        return null;
    }
    const actions = [
        voteActionFromData(objectGraph, data, deviceId, true),
        voteActionFromData(objectGraph, data, deviceId, false),
    ];
    // Workaround for missing report concern url in bag
    if (((_a = objectGraph.bag.reportConcernUrl) === null || _a === void 0 ? void 0 : _a.length) > 0) {
        actions.push(reportConcernActionFromData(objectGraph, data, deviceId));
    }
    if ((reviewText === null || reviewText === void 0 ? void 0 : reviewText.length) > 0) {
        actions.push(copyReviewAction(objectGraph, reviewText));
    }
    return new models.FlowPreviewActionsConfiguration(actions);
}
/**
 * Create and return the flow preview configuration for a review summary object
 * @param data The response data to read from.
 * @param adamId The adam ID of the app
 * @param appName The name of the app
 * @param reviewSummaryId The ID of the review summary
 * @param reviewSummaryText The text of the review summary
 * @param deviceId The UUID for the customer's device.
 * @returns A configuration object for flow preview actions that can be taken on the review summary
 */
export function flowPreviewActionsConfigurationForReviewSummaryFromData(objectGraph, data, adamId, appName, reviewSummaryId, reviewSummaryText, deviceId) {
    if (!objectGraph.client.isiOS) {
        return null;
    }
    const actions = [];
    const reportConcernAction = reviewSummaryReportConcernActionFromData(objectGraph, data, reviewSummaryId, deviceId);
    if (isSome(reportConcernAction)) {
        actions.push(reportConcernAction);
    }
    const learnMoreAction = reviews.reviewSummaryLearnMoreAction(objectGraph);
    if (isSome(learnMoreAction)) {
        actions.push(learnMoreAction);
    }
    const fileRadarAction = fileReviewSummaryRadarAction(objectGraph, adamId, appName, reviewSummaryId, reviewSummaryText);
    if (isSome(fileRadarAction)) {
        actions.push(fileRadarAction);
    }
    return new models.FlowPreviewActionsConfiguration(actions);
}
/**
 * Creates a report a concern action for a given review
 * @param data  The response data to read from.
 * @param deviceId  The UUID for the user's device.
 * @returns A report concern action
 */
export function reviewSummaryReportConcernActionFromData(objectGraph, data, reviewSummaryId, deviceId) {
    return validation.context("reviewSummaryReportConcernActionFromApiRow", () => {
        const isEnabled = serverData.asBoolean(data, "enabled");
        if (!isEnabled) {
            return null;
        }
        const sendAction = createReviewSummaryReportConcernHtmlTemplateAction(objectGraph, reviewSummaryId);
        const concerns = serverData.asArrayOrEmpty(data, "concerns");
        const reviewSummaryConcerns = concerns.map((concernData) => {
            let name;
            let uppercaseName;
            const concernKind = serverData.asString(concernData, "kind");
            switch (concernKind) {
                case "OFFENSIVE":
                case "OFFENSIVE_OR_HARMFUL":
                    name = objectGraph.loc.string("ProductPage.ReviewSummary.ReportAConcern.Offensive.Name");
                    uppercaseName = objectGraph.loc.string("ProductPage.ReviewSummary.ReportAConcern.Offensive.UppercaseName");
                    break;
                case "MISREPRESENTING_THE_APP":
                case "MISREPRESENT":
                    name = objectGraph.loc.string("ProductPage.ReviewSummary.ReportAConcern.Misrepresent.Name");
                    uppercaseName = objectGraph.loc.string("ProductPage.ReviewSummary.ReportAConcern.Misrepresent.UppercaseName");
                    break;
                case "SOMETHING_ELSE":
                    name = objectGraph.loc.string("ProductPage.ReviewSummary.ReportAConcern.SomethingElse.Name");
                    uppercaseName = objectGraph.loc.string("ProductPage.ReviewSummary.ReportAConcern.SomethingElse.UppercaseName");
                    break;
                default:
                    break;
            }
            return new base.ReportConcernReason(concernKind, name, uppercaseName);
        });
        if (reviewSummaryConcerns.length === 0) {
            return null;
        }
        const title = objectGraph.loc.string("ACTION_REVIEW_REPORT");
        const explanation = objectGraph.loc.string("ProductPage.ReviewSummary.ReportAConcern.Explanation");
        const action = new models.ReviewSummaryReportConcernAction(reviewSummaryConcerns, title, explanation, sendAction);
        action.artwork = contentArtwork.createArtworkForResource(objectGraph, "systemimage://exclamationmark.circle");
        return action;
    });
}
function createReviewSummaryReportConcernHtmlTemplateAction(objectGraph, reviewSummaryId) {
    const request = new Request(objectGraph);
    request.includeAppBinaryTraitsAttribute = false;
    request.resourceType = "concerns";
    const url = buildURLFromRequest(objectGraph, request);
    const sendAction = new models.HttpTemplateAction(url.toString());
    sendAction.method = "POST";
    sendAction.disableCache = true;
    sendAction.needsMediaToken = true;
    sendAction.headers = { "Content-Type": "application/json" };
    sendAction.bodyDictionary = {
        report: { contentId: reviewSummaryId, contentKind: "review-summaries", concerns: null },
    };
    const successToast = new models.AlertAction("toast");
    successToast.title = objectGraph.loc.string("TOAST_CONCERN_REPORTED_TITLE");
    successToast.message = objectGraph.loc.string("TOAST_CONCERN_REPORTED_DESCRIPTION");
    successToast.artwork = contentArtwork.createArtworkForResource(objectGraph, "systemimage://exclamationmark.circle");
    sendAction.successAction = successToast;
    const failureAlert = new models.AlertAction("default");
    failureAlert.title = objectGraph.loc.string("Alert.GenericError.Title");
    failureAlert.message = objectGraph.loc.string("Alert.GenericError.Message");
    failureAlert.isCancelable = true;
    sendAction.failureAction = failureAlert;
    return sendAction;
}
/**
 * Walks through the given data to extract the data blob for a product
 * @param data  The response data to read from.
 * @returns Response data for a product
 */
function productDataFromData(objectGraph, data) {
    return validation.context(`productDataFromData: ${data.type}`, () => {
        switch (data.type) {
            case "apps":
            case "app-bundles": {
                return data;
            }
            case "editorial-items": {
                const cardContents = mediaRelationship.relationshipCollection(data, "card-contents");
                if (serverData.isDefinedNonNullNonEmpty(cardContents) && cardContents.length === 1) {
                    const cardContentsData = cardContents[0];
                    return productDataFromData(objectGraph, cardContentsData);
                }
                break;
            }
            case "editorial-elements": {
                const contents = mediaRelationship.relationshipCollection(data, "contents");
                if (serverData.isDefinedNonNullNonEmpty(contents) && contents.length === 1) {
                    const contentData = contents[0];
                    return productDataFromData(objectGraph, contentData);
                }
                break;
            }
            default: {
                return null;
            }
        }
        return null;
    });
}
/**
 * Create an offer action for the provided product data
 * @param data  The response data to read from.
 * @param isPreorder  Whether the product is a pre-order
 * @param isArcade  Whether the product is an Arcade product
 * @param offerType  The type of offer for the product
 * @param clientIdentifierOverride  The suggested client identifier for the given product
 * @param metricsClickOptions  TThe metrics click options for the product
 * @returns An offer action
 */
function offerActionFromData(objectGraph, data, isPreorder, isArcade, offerType, clientIdentifierOverride, metricsClickOptions) {
    if (serverData.isNull(data) || data.type !== "apps") {
        return null;
    }
    const offerData = offers.offerDataFromData(objectGraph, data);
    const appIcon = content.iconFromData(objectGraph, data, null, clientIdentifierOverride);
    const metricsPlatformDisplayStyle = metricsUtil.metricsPlatformDisplayStyleFromData(objectGraph, data, appIcon, clientIdentifierOverride);
    const offerAction = offers.offerActionFromOfferData(objectGraph, offerData, data, isPreorder, false, metricsPlatformDisplayStyle, metricsClickOptions, "flowPreview");
    return offerAction;
}
/**
 * Wraps an offer action if required
 * @param data  The response data to read from.
 * @param offerAction  The provided offer action to wrap
 * @param clientIdentifierOverride  The suggested client identifier for the given product
 * @param metricsClickOptions  TThe metrics click options for the product
 * @param metricsOptions The metrics options to use for reporting metrics actions.
 * @param externalDeepLink The promotional deep link url to use on the product's offer.
 * @returns A wrapped offer action
 */
function wrappedOfferActionFromData(objectGraph, data, offerAction, isPreorder, clientIdentifierOverride, metricsClickOptions, metricsOptions, externalDeepLinkUrl) {
    if (serverData.isNull(offerAction)) {
        return null;
    }
    let wrappedOfferAction = offers.wrapOfferActionIfNeeded(objectGraph, offerAction, data, isPreorder, metricsClickOptions, "flowPreview", clientIdentifierOverride);
    if ((externalDeepLinkUrl === null || externalDeepLinkUrl === void 0 ? void 0 : externalDeepLinkUrl.length) > 0) {
        // Configure cross link as well as deep link action.
        wrappedOfferAction = externalDeepLink.deepLinkActionWrappingAction(objectGraph, wrappedOfferAction, offerAction.adamId, null, externalDeepLinkUrl, false, metricsClickOptions);
    }
    return wrappedOfferAction;
}
/**
 * Creates and returns an action for sharing a product
 * @param data  The response data to read from.
 * @param metricsOptions The metrics options to use for reporting metrics actions.
 * @returns A share action or null
 */
function shareActionFromData(objectGraph, data, metricsOptions) {
    const shareAction = sharing.shareProductActionFromData(objectGraph, data, metricsOptions.pageInformation, metricsOptions.locationTracker);
    if (serverData.isDefinedNonNull(shareAction)) {
        shareAction.title = objectGraph.loc.string("FLOW_PREVIEW_ACTION_SHARE");
        shareAction.artwork = contentArtwork.createArtworkForResource(objectGraph, "systemimage://square.and.arrow.up");
        return shareAction;
    }
    return shareAction;
}
/**
 * Creates and returns an action for navigating to a product's ratings & reviews
 * @param data  The response data to read from.
 * @param clickAction  The flow action for viewing the product
 * @returns An action or null
 */
function seeRatingsAndReviewsActionFromData(objectGraph, data, clickAction) {
    const seeRatingsAndReviewsAction = reviews.seeRatingsAndReviewsActionFromClickAction(objectGraph, data.id, clickAction);
    if (serverData.isDefinedNonNull(seeRatingsAndReviewsAction)) {
        seeRatingsAndReviewsAction.title = objectGraph.loc.string("FLOW_PREVIEW_ACTION_SEE_RATINGS_AND_REVIEWS");
        seeRatingsAndReviewsAction.artwork = contentArtwork.createArtworkForResource(objectGraph, "systemimage://star");
        seeRatingsAndReviewsAction.animationBehavior = "never";
    }
    return seeRatingsAndReviewsAction;
}
/**
 * Creates and returns an action for writing a product review
 * @param data  The response data to read from.
 * @returns An action or null
 */
function writeReviewActionFromData(objectGraph, data, lockupSubtitle, lockupTitle) {
    const writeReviewAction = reviews.writeReviewActionFromData(objectGraph, data, lockupSubtitle, lockupTitle);
    if (serverData.isDefinedNonNull(writeReviewAction)) {
        writeReviewAction.title = objectGraph.loc.string("FLOW_PREVIEW_ACTION_WRITE_REVIEW");
        writeReviewAction.artwork = contentArtwork.createArtworkForResource(objectGraph, "systemimage://square.and.pencil");
    }
    return writeReviewAction;
}
/**
 * Create and returns an action for voting whether a review was helpful or not
 * @param data  The response data to read from.
 * @param deviceId  The UUID for the user's device.
 * @param helpful   Whether or not the vote is indicating the review was helpful, or not helpful.
 * @returns A new vote action.
 */
export function voteActionFromData(objectGraph, data, deviceId, helpful) {
    const baseVoteUrl = objectGraph.bag.voteUrl;
    const reviewId = serverData.asString(data, "id", "coercible");
    const voteUrl = new urls.URL(baseVoteUrl).param("userReviewId", reviewId);
    if (objectGraph.client.isVision) {
        // We only attach this parameter for visionOS, as the other platforms have legacy handling in place
        // that we do not want to interrupt.
        voteUrl.param("version", "2");
    }
    const action = new models.HttpAction(voteUrl.build());
    const successToast = new models.AlertAction("toast");
    if (helpful) {
        action.title = objectGraph.loc.string("ACTION_REVIEW_HELPFUL");
        successToast.title = objectGraph.loc.string("TOAST_HELPFUL_TITLE");
        successToast.message = objectGraph.loc.string("TOAST_HELPFUL_DESCRIPTION");
        action.artwork = contentArtwork.createArtworkForResource(objectGraph, "systemimage://hand.thumbsup");
        successToast.artwork = contentArtwork.createArtworkForResource(objectGraph, objectGraph.client.isVision ? "systemimage://hand.thumbsup.fill" : "systemimage://hand.thumbsup");
    }
    else {
        action.title = objectGraph.loc.string("ACTION_REVIEW_NOT_HELPFUL");
        successToast.title = objectGraph.loc.string("TOAST_NOT_HELPFUL_TITLE");
        successToast.message = objectGraph.loc.string("TOAST_NOT_HELPFUL_DESCRIPTION");
        action.artwork = contentArtwork.createArtworkForResource(objectGraph, "systemimage://hand.thumbsdown");
        successToast.artwork = contentArtwork.createArtworkForResource(objectGraph, objectGraph.client.isVision ? "systemimage://hand.thumbsdown.fill" : "systemimage://hand.thumbsdown");
    }
    action.method = "POST";
    action.isStoreRequest = true;
    action.disableCache = true;
    action.headers = { "Content-Type": http.FormBuilder.contentType };
    action.body = new http.FormBuilder()
        .param("vote", helpful ? "1" : "0")
        .param("guid", deviceId)
        .build();
    action.successAction = successToast;
    return action;
}
/**
 * Creates a report a concern action for a given review
 * @param data  The response data to read from.
 * @param deviceId  The UUID for the user's device.
 * @returns A report concern action
 */
export function reportConcernActionFromData(objectGraph, data, deviceId) {
    return validation.context("reportConcernActionFromApiRow", () => {
        const reviewId = serverData.asString(data, "id", "coercible");
        const reportConcernUrl = objectGraph.bag.reportConcernUrl;
        const sendAction = new models.HttpTemplateAction(reportConcernUrl);
        sendAction.method = "POST";
        sendAction.isStoreRequest = true;
        sendAction.disableCache = true;
        sendAction.needsAuthentication = true;
        sendAction.headers = { "Content-Type": http.FormBuilder.contentType };
        sendAction.body = new http.FormBuilder().param("userReviewId", reviewId).param("guid", deviceId).build();
        const reasonParameter = new models.HttpTemplateParameter("selectedReason", "formBody", "decimalPad");
        const explanationParameter = new models.HttpTemplateParameter("explanation", "formBody", "text");
        sendAction.parameters = [reasonParameter, explanationParameter];
        if (!objectGraph.client.isVision) {
            const successToast = new models.AlertAction("toast");
            successToast.title = objectGraph.loc.string("TOAST_CONCERN_REPORTED_TITLE");
            successToast.message = objectGraph.loc.string("TOAST_CONCERN_REPORTED_DESCRIPTION");
            successToast.artwork = contentArtwork.createArtworkForResource(objectGraph, "systemimage://exclamationmark.circle");
            sendAction.successAction = successToast;
        }
        const failureAlert = new models.AlertAction("default");
        failureAlert.title = objectGraph.loc.string("Alert.GenericError.Title");
        failureAlert.message = objectGraph.loc.string("Alert.GenericError.Message");
        failureAlert.isCancelable = true;
        sendAction.failureAction = failureAlert;
        let concernReasons = objectGraph.bag.reportConcernReasons;
        if (serverData.isNullOrEmpty(concernReasons)) {
            // Not available until 18G
            concernReasons = [
                {
                    reasonId: "1",
                    name: "It contains offensive material",
                    upperCaseName: "IT CONTAINS OFFENSIVE MATERIAL",
                },
                {
                    reasonId: "8",
                    name: "It's off-topic",
                    upperCaseName: "IT\u2019S OFF-TOPIC",
                },
                {
                    reasonId: "111003",
                    name: "It looks like spam",
                    upperCaseName: "IT LOOKS LIKE SPAM",
                },
                {
                    reasonId: "7",
                    name: "Something else",
                    upperCaseName: "SOMETHING ELSE",
                },
            ];
        }
        const reasons = concernReasons.map((reasonData) => {
            return new base.ReportConcernReason(serverData.asString(reasonData, "reasonId"), serverData.asString(reasonData, "name"), serverData.asString(reasonData, "upperCaseName"));
        });
        const action = new models.ReportConcernAction(reasons);
        action.title = objectGraph.loc.string("ACTION_REVIEW_REPORT");
        action.explanation = objectGraph.bag.reportConcernExplanation;
        if (serverData.isNullOrEmpty(action.explanation)) {
            // Not available until 18G
            action.explanation = "Tell us a little more (Optional)";
        }
        action.artwork = contentArtwork.createArtworkForResource(objectGraph, "systemimage://exclamationmark.circle");
        action.sendAction = sendAction;
        return action;
    });
}
export function copyReviewAction(objectGraph, reviewText) {
    const copyTextAction = new models.CopyTextAction(reviewText);
    copyTextAction.title = objectGraph.loc.string("ACTION_REVIEW_COPY");
    copyTextAction.artwork = contentArtwork.createArtworkForResource(objectGraph, "systemimage://doc.on.doc");
    return copyTextAction;
}
/**
 * Creates an action for filing a radar against a Review Summary
 * @param objectGraph Current object graph
 * @param adamId The ID of the app
 * @param appName The name of the app
 * @param reviewSummaryId The ID of the review summary
 * @param reviewSummaryText The text of the review summary
 * @returns An action that will deep link to Radar
 */
function fileReviewSummaryRadarAction(objectGraph, adamId, appName, reviewSummaryId, reviewSummaryText) {
    if (!["debug", "internal"].includes(objectGraph.client.buildType)) {
        return null;
    }
    const componentId = "999915"; // ASE App Store | Recommendations
    const title = `Review Summary Feedback: ${appName}`;
    const description = `App ID: ${adamId}\nApp name: ${appName}\nReview summary ID: ${reviewSummaryId}\nReview summary: ${reviewSummaryText}\n\nFeedback: `;
    const url = `tap-to-radar://new/problem?componentid=${componentId}&title=${title}&description=${description}`;
    const action = new models.ExternalUrlAction(url, true);
    action.title = objectGraph.loc.string("Action.ProvideFeedback");
    action.artwork = contentArtwork.createArtworkForResource(objectGraph, "systemimage://ant.circle");
    return action;
}
//# sourceMappingURL=flow-preview.js.map