import { isNothing, isSome } from "@jet/environment";
import * as models from "../../api/models";
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 color from "../../foundation/util/color-util";
import * as dateUtil from "../../foundation/util/date-util";
import * as appPromotionCommon from "./app-promotions-common";
/**
 * Creates an app event object or a Date, if the event should not yet be shown, from the given data.
 * @param data The data blob
 * @param parentAppData The related parent app of this app event. If not provided will be derived from `data`.
 * @param hideLockupWhenNotInstalled Whether to hide the lockup chin when the app is installed
 * @param includeClickAction Whether to generate a click action for the app event
 * @param offerEnvironment The preferred environment for the offer
 * @param offerStyle The preferred style of the offer
 * @param includeCrossLinkTitles Whether the cross link titles will be displayed when the app is installed
 * @param allowMissingParentApp Whether to still create the app event if the parent app is missing
 * @param baseMetricsOptions The base metrics options
 * @param allowEndedEvents Whether events in the past are allowed
 * @param includeLockupClickAction Whether to include the click action for the lockup
 * @param isArcadePage Whether or not this is presented on the Arcade page
 * @param allowUnpublishedAppEventPreviews Whether or not to allow app event previews
 * @returns an AppEvent, or a Date if the event's `promotionStartDate` is in the future.
 */
export function appEventOrPromotionStartDateFromData(objectGraph, data, parentAppData, hideLockupWhenNotInstalled, includeClickAction, offerEnvironment, offerStyle, includeCrossLinkTitles, baseMetricsOptions, allowEndedEvents, includeLockupClickAction, editorialKind, isArcadePage, allowUnpublishedAppEventPreviews) {
    var _a, _b, _c;
    if (data.type !== "app-events") {
        return null;
    }
    const promotionStartDateString = mediaAttributes.attributeAsString(data, "promotionStartDate");
    if (isNothing(promotionStartDateString) || promotionStartDateString.length === 0) {
        return null;
    }
    const promotionStartDate = new Date(promotionStartDateString);
    if (isNothing(promotionStartDate)) {
        return null;
    }
    const todayDate = new Date();
    const isFutureDate = promotionStartDate.getTime() > todayDate.getTime();
    if (isFutureDate && !allowUnpublishedAppEventPreviews) {
        return promotionStartDate;
    }
    // Artwork / video
    const moduleArtwork = appPromotionCommon.artworkFromData(objectGraph, data, "lockupArtwork");
    const moduleVideo = appPromotionCommon.videoFromData(objectGraph, data, "lockupVideo", false, false);
    if (isNothing(moduleArtwork) && serverData.isNullOrEmpty(moduleVideo)) {
        return null;
    }
    const selectedArtwork = (_a = moduleVideo === null || moduleVideo === void 0 ? void 0 : moduleVideo.preview) !== null && _a !== void 0 ? _a : moduleArtwork;
    const isArtworkDark = color.isDarkColor(selectedArtwork === null || selectedArtwork === void 0 ? void 0 : selectedArtwork.backgroundColor);
    const mediaOverlayStyle = isArtworkDark ? "dark" : "light";
    const includeBorderInDarkMode = color.isDarkColor(selectedArtwork === null || selectedArtwork === void 0 ? void 0 : selectedArtwork.backgroundColor, 10);
    // Other required fields
    const title = mediaAttributes.attributeAsString(data, "name");
    let kind = mediaAttributes.attributeAsString(data, "kind");
    if (serverData.isDefinedNonNullNonEmpty(editorialKind)) {
        kind = editorialKind;
    }
    const startDateString = mediaAttributes.attributeAsString(data, "startDate");
    if (isNothing(title) ||
        title.length === 0 ||
        isNothing(kind) ||
        kind.length === 0 ||
        isNothing(startDateString) ||
        startDateString.length === 0) {
        return null;
    }
    const startDate = new Date(startDateString);
    if (isNothing(startDate)) {
        return null;
    }
    // Description
    const detail = (_b = mediaAttributes.attributeAsString(data, "description.standard")) !== null && _b !== void 0 ? _b : "";
    // Lockup
    const resolvedParentAppData = parentAppData !== null && parentAppData !== void 0 ? parentAppData : mediaRelationship.relationshipData(objectGraph, data, "app");
    let lockup = null;
    if (isSome(resolvedParentAppData)) {
        lockup = appPromotionCommon.lockupFromData(objectGraph, data, resolvedParentAppData, title, offerEnvironment, offerStyle, includeCrossLinkTitles, baseMetricsOptions, includeLockupClickAction, null, isArcadePage, true);
    }
    if (isNothing(lockup)) {
        objectGraph.console.warn(`Parent app for event ${data.id} is missing, returning null.`);
        return null;
    }
    // Requirements
    const requirements = mediaAttributes.attributeAsString(data, "requirement");
    // Supplementary optional fields
    const subtitle = mediaAttributes.attributeAsString(data, "subtitle");
    const endDateString = mediaAttributes.attributeAsString(data, "endDate");
    let endDate;
    if (isSome(endDateString) && endDateString.length > 0) {
        endDate = new Date(endDateString);
    }
    const hasEventEnded = endDate !== undefined && endDate.getTime() <= todayDate.getTime();
    if (hasEventEnded && !allowEndedEvents) {
        return null;
    }
    // Formatted dates
    const badgeKindString = (_c = mediaAttributes.attributeAsString(data, "badgeKind")) !== null && _c !== void 0 ? _c : undefined;
    const badgeKind = badgeKindFromString(badgeKindString, startDate, endDate);
    const formattedDates = formattedDatesWithKind(objectGraph, badgeKind, startDate, endDate);
    const appEvent = new models.AppEvent(data.id, moduleArtwork !== null && moduleArtwork !== void 0 ? moduleArtwork : undefined, moduleVideo !== null && moduleVideo !== void 0 ? moduleVideo : undefined, title, subtitle !== null && subtitle !== void 0 ? subtitle : undefined, detail, startDate, endDate, badgeKind, kind, requirements !== null && requirements !== void 0 ? requirements : undefined, lockup, hideLockupWhenNotInstalled, formattedDates, mediaOverlayStyle, includeBorderInDarkMode);
    // Notifications
    if (serverData.isDefinedNonNull(resolvedParentAppData)) {
        const clickOptions = {
            ...baseMetricsOptions,
            id: resolvedParentAppData.id,
            inAppEventId: data.id,
            relatedSubjectIds: [resolvedParentAppData.id],
        };
        appEvent.notificationConfig = appPromotionCommon.notificationConfigFromData(objectGraph, data, appEvent, clickOptions, true);
    }
    // Click action
    if (includeClickAction && serverData.isDefinedNonNull(resolvedParentAppData)) {
        appEvent.clickAction = appPromotionCommon.detailPageClickActionFromData(objectGraph, data, resolvedParentAppData, appEvent, baseMetricsOptions, includeLockupClickAction);
    }
    return appEvent;
}
/**
 * Determines the badge kind from the given string.
 * @param badgeKindString The raw badge kind string
 * @param startDate The start date of the app event
 * @param endDate  The end date of the app event, if any
 * @returns An AppEventBadgeKind
 */
export function badgeKindFromString(badgeKindString, startDate, endDate) {
    let badgeKind = (badgeKindString !== null && badgeKindString !== void 0 ? badgeKindString : models.AppEventBadgeKind.live);
    if (badgeKind === models.AppEventBadgeKind.live && serverData.isDefinedNonNull(endDate)) {
        // If the event is longer than 6 hours, override with "happening now" so that
        // the blinking red live dot is less prevalent.
        const difference = endDate.getTime() - startDate.getTime();
        const sixHoursDifference = 1000 * 60 * 60 * 6;
        if (difference > sixHoursDifference) {
            badgeKind = models.AppEventBadgeKind.happening;
        }
    }
    return badgeKind;
}
/**
 * Generates a list of all the possible date variants for a given app event. The native
 * client will look at this list and determine which variant to display, based
 * on the current time. The reason for sending down all variants is that the client will
 * continue to update the display as time progresses, so it's feasible that the client will
 * cross over from date variant to the next (eg. TOMORROW 12:00 PM -> TODAY 12:00 PM).
 * @param badgeKind The kind of badge used
 * @param startDate The start date of the app event
 * @param endDate The end date of the app event, if any
 */
export function formattedDatesWithKind(objectGraph, badgeKind, startDate, endDate) {
    const formattedDates = [];
    const startMidnight = dateUtil.convertLocalDateToLocalMidnight(startDate);
    if (isNothing(startMidnight)) {
        // This is only possible if `startDate` is "nothing", which means we can't proceed to create formatted dates anyway.
        return [];
    }
    // Event starts 7+ days from now
    // Example: JAN 15
    const introductionDateFormat = objectGraph.loc.string("AppEvents.FormattedDate.SevenDaysOrMore.DateFormat");
    const introductionText = objectGraph.loc.uppercased(objectGraph.loc.formatDate(introductionDateFormat, startDate));
    const introductionFormattedDate = new models.AppEventFormattedDate(false, undefined, introductionText !== null && introductionText !== void 0 ? introductionText : undefined, undefined, undefined);
    formattedDates.push(introductionFormattedDate);
    // Event starts 2-6 days from now
    // Example: FRI 12:00 PM
    const sixDaysPrior = new Date(startMidnight);
    sixDaysPrior.setDate(sixDaysPrior.getDate() - 6);
    const sixDaysPriorDateFormat = objectGraph.loc.string("AppEvents.FormattedDate.SixDaysOrLess.DateFormat");
    const sixDaysPriorText = objectGraph.loc.formatDate(sixDaysPriorDateFormat, startDate);
    const sixDaysPriorTextUppercased = objectGraph.loc.uppercased(sixDaysPriorText);
    const sixDaysPriorFormattedDate = new models.AppEventFormattedDate(false, sixDaysPrior, sixDaysPriorTextUppercased !== null && sixDaysPriorTextUppercased !== void 0 ? sixDaysPriorTextUppercased : undefined, undefined, undefined);
    formattedDates.push(sixDaysPriorFormattedDate);
    // Event starts tomorrow
    // Example: TOMORROW 12:00 PM
    const oneDayPrior = new Date(startMidnight);
    oneDayPrior.setDate(oneDayPrior.getDate() - 1);
    const tomorrowSentence = objectGraph.loc.string("AppEvents.FormattedDate.Tomorrow");
    const tomorrowText = objectGraph.loc.formatDateInSentence(tomorrowSentence, "j:mm", startDate);
    const tomorrowTextUppercased = objectGraph.loc.uppercased(tomorrowText);
    const tomorrowFormattedDate = new models.AppEventFormattedDate(false, oneDayPrior, tomorrowTextUppercased !== null && tomorrowTextUppercased !== void 0 ? tomorrowTextUppercased : undefined, undefined, undefined);
    formattedDates.push(tomorrowFormattedDate);
    // Event starts today
    // If the event starts within 1 hour of midnight, we don't need to show this case
    // as it will be superceded by the 1 hour countdown
    // Example: TODAY 12:00 PM, TONIGHT 7:00 PM
    if (startDate.getHours() > 1 || (startDate.getHours() === 1 && startDate.getMinutes() > 0)) {
        let todaySentence;
        if (startDate.getHours() >= 19) {
            todaySentence = objectGraph.loc.string("AppEvents.FormattedDate.Tonight");
        }
        else {
            todaySentence = objectGraph.loc.string("AppEvents.FormattedDate.Today");
        }
        const todayText = objectGraph.loc.formatDateInSentence(todaySentence, "j:mm", startDate);
        const todayTextUppercased = objectGraph.loc.uppercased(todayText);
        const todayFormattedDate = new models.AppEventFormattedDate(false, startMidnight !== null && startMidnight !== void 0 ? startMidnight : undefined, todayTextUppercased !== null && todayTextUppercased !== void 0 ? todayTextUppercased : undefined, undefined, undefined);
        formattedDates.push(todayFormattedDate);
    }
    // Event is starting in 1 hour or less
    // Example: STARTS IN 59 MIN / AVAILABLE IN 59 MIN
    const oneHourPrior = new Date(startDate);
    oneHourPrior.setHours(oneHourPrior.getHours() - 1);
    let countdownStringKey;
    switch (badgeKind) {
        case models.AppEventBadgeKind.available:
            countdownStringKey = "AppEvents.FormattedDate.AvailableIn.MinutesCountdown";
            break;
        case models.AppEventBadgeKind.happening:
        case models.AppEventBadgeKind.live:
        default:
            countdownStringKey = "AppEvents.FormattedDate.StartsIn.MinutesCountdown";
            break;
    }
    const oneHourPriorFormattedDate = new models.AppEventFormattedDate(false, oneHourPrior, undefined, startDate, countdownStringKey);
    formattedDates.push(oneHourPriorFormattedDate);
    // Event is happening now
    // Example: LIVE, HAPPENING NOW, NOW AVAILABLE
    let liveText;
    let showLiveIndicator;
    switch (badgeKind) {
        case models.AppEventBadgeKind.available:
            liveText = objectGraph.loc.string("AppEvents.FormattedDate.NowAvailable");
            showLiveIndicator = false;
            break;
        case models.AppEventBadgeKind.happening:
            liveText = objectGraph.loc.string("AppEvents.FormattedDate.HappeningNow");
            showLiveIndicator = false;
            break;
        case models.AppEventBadgeKind.live:
        default:
            liveText = objectGraph.loc.string("AppEvents.FormattedDate.Live");
            showLiveIndicator = true;
            break;
    }
    const liveFormattedDate = new models.AppEventFormattedDate(showLiveIndicator, startDate, liveText, undefined, undefined);
    formattedDates.push(liveFormattedDate);
    // Event has ended
    // Example: EVENT ENDED
    if (endDate !== null) {
        const eventEndedFormattedDate = new models.AppEventFormattedDate(false, endDate, objectGraph.loc.string("AppEvents.FormattedDate.EventEnded"), undefined, undefined);
        formattedDates.push(eventEndedFormattedDate);
    }
    return formattedDates;
}
//# sourceMappingURL=app-event.js.map