"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.EPromoCodeStatus = void 0;
const dayjs_1 = __importDefault(require("dayjs"));
const CalendarHelper_1 = require("../util/CalendarHelper");
const Color_1 = require("../util/Color");
const DefaultValueManager_1 = require("../util/DefaultValueManager");
const AppQueryParameters_1 = require("./AppQueryParameters");
var EPromoCodeStatus;
(function (EPromoCodeStatus) {
    EPromoCodeStatus["Valid"] = "valid";
    EPromoCodeStatus["Invalid"] = "invalid";
    EPromoCodeStatus["New"] = "new";
    EPromoCodeStatus["Forbidden"] = "forbidden";
})(EPromoCodeStatus || (exports.EPromoCodeStatus = EPromoCodeStatus = {}));
class BasketRow {
    /**
     *
     * @param rate - Optional `RoomRate` object associated with the basket row.
     * @param uniqId - Optional unique identifier for this basket row instance.
     * @param shouldEnableRoomCodeFilter - Whether to check the URL for a room code and enable filtering accordingly.
     *                                Defaults to `true`.
     */
    constructor(rate, uniqId, shouldEnableRoomCodeFilter = true) {
        var _a, _b, _c;
        this.preGuestsState = {
            adults: 0,
            children: 0,
            infants: 0,
            startDate: (0, dayjs_1.default)(),
            endDate: (0, dayjs_1.default)(),
        };
        /**
         * Warning message associated with an invalid promo code.
         * Used for displaying tooltip or error messages to the user.
         */
        this.promoCodeWarningMessage = '';
        /**
         * Enable room code filter when the the URL's room parameter is present
         */
        this.enableRoomCodeFilter = false;
        /**
         * Indicates availability for a specific room extracted from the URL's room parameter
         */
        this.roomCode = '';
        /**
         * Ensures endDate is always at least 1 day after startDate.
         * Prevents invalid basket date ranges inherited from previous rows.
         */
        this.normalizeDateRange = () => {
            if (!this.startDate)
                return;
            const minimumEndDate = this.startDate.clone().add(1, 'day');
            if (!this.endDate || this.endDate.isBefore(minimumEndDate, 'day')) {
                this.endDate = minimumEndDate;
            }
        };
        /**
         * Returns the tooltip text based on the promo code status.
         *
         * - If status is EPromoCodeStatus.New: returns 'Checking' or 'No value'.
         * - If status is EPromoCodeStatus.Valid: returns 'Valid'.
         * - If status is EPromoCodeStatus.Invalid: returns the warning message.
         *
         * @param t - Translation function.
         * @param Translation - Translation object with tooltip message strings.
         * @returns Tooltip string to display.
         */
        this.getPromoCodeTooltip = (t, Translation) => {
            let promoCodeTooltip = '';
            if ((this === null || this === void 0 ? void 0 : this.getPromoCodeStatus()) === EPromoCodeStatus.New) {
                promoCodeTooltip = this.getPromoCode() ? t(Translation.Step.Date.PromoCodeTooltip.Checking) : t(Translation.Step.Date.PromoCodeTooltip.NoValue);
            }
            else {
                if ((this === null || this === void 0 ? void 0 : this.getPromoCodeStatus()) === EPromoCodeStatus.Valid) {
                    promoCodeTooltip = t(Translation.Step.Date.PromoCodeTooltip.Valid);
                }
                else {
                    promoCodeTooltip = this.getPromoCodeWarningMessage() || t(Translation.Step.Date.PromoCodeTooltip.Invalid);
                }
            }
            return promoCodeTooltip;
        };
        /*
         * Rate is optional since we can create row entries on first step, where there is no ability to select rate.
         */
        if (rate) {
            this.setRate(rate);
        }
        this.adults = (_a = DefaultValueManager_1.DEFAULT_VALUES.ADULTS) !== null && _a !== void 0 ? _a : 1;
        this.children = (_b = DefaultValueManager_1.DEFAULT_VALUES.CHILDREN) !== null && _b !== void 0 ? _b : 0;
        this.infants = (_c = DefaultValueManager_1.DEFAULT_VALUES.INFANTS) !== null && _c !== void 0 ? _c : 0;
        this.promoCode = '';
        this.promoCodeStatus = EPromoCodeStatus.New;
        this.promoOnly = false;
        if (shouldEnableRoomCodeFilter) {
            const roomCode = (0, CalendarHelper_1.getQueryParamFromHash)(AppQueryParameters_1.EAppQueryParameters.Room); // Extract the the URL's room parameter
            this.enableRoomCodeFilter = !!roomCode;
            this.roomCode = roomCode || '';
        }
        this.manualInputPromoCode = false;
        this.uniqId = uniqId ? uniqId : btoa(((Date.now() % 1000) / 1000) * Math.random() + '');
    }
    getStale() {
        return this.isStale;
    }
    getRate() {
        return this.rate;
    }
    getPromoCode(memberOnlyPromoCode) {
        if (!memberOnlyPromoCode) {
            return this.promoCode.toUpperCase();
        }
        if (memberOnlyPromoCode !== this.promoCode.toUpperCase() || this.isManualInputPromoCode()) {
            return this.promoCode.toUpperCase();
        }
        return '';
    }
    getPromoOnly() {
        return this.promoOnly;
    }
    getPromoCodeColour() {
        if (this.promoCodeStatus === EPromoCodeStatus.Valid) {
            return Color_1.Color.Success;
        }
        else if ([EPromoCodeStatus.Invalid, EPromoCodeStatus.Forbidden].includes(this.promoCodeStatus)) {
            return Color_1.Color.Alert;
        }
        return Color_1.Color.Navy;
    }
    isPromoCodeValid() {
        const rate = this.getRate();
        return ((rate === null || rate === void 0 ? void 0 : rate.getAveragePrice(true)) < (rate === null || rate === void 0 ? void 0 : rate.getAveragePriceBeforeDiscount(true)) &&
            this.getPromoCode() &&
            this.getPromoCodeStatus() === EPromoCodeStatus.Valid);
    }
    isManualInputPromoCode() {
        return this.manualInputPromoCode;
    }
    setManualInputPromoCode(value) {
        this.manualInputPromoCode = value;
    }
    getNumberOfDays() {
        if (this.endDate && this.startDate) {
            return this.endDate.diff(this.startDate, 'day');
        }
        return 0;
    }
    getRoom() {
        return this.room;
    }
    getStartDate() {
        return this.startDate;
    }
    getEndDate() {
        return this.endDate;
    }
    getArrivalDate() {
        if (this.startDate) {
            return this.startDate.format('D MMM');
        }
        return null;
    }
    getDepartureDate() {
        if (this.endDate) {
            return this.endDate.format('D MMM');
        }
        return null;
    }
    getStayDateRange(format = 'ddd D MMM', separator = ',') {
        if (this.startDate && this.endDate) {
            return `${this.startDate.format(format)}${separator} ${this.endDate.format(format)}`;
        }
    }
    getAdults() {
        return this.adults;
    }
    getChildren() {
        return this.children;
    }
    getInfants() {
        return this.infants;
    }
    getPreGuestsState() {
        return this.preGuestsState;
    }
    getID() {
        return this.uniqId;
    }
    getPromoCodeStatus() {
        return this.promoCodeStatus;
    }
    isValid() {
        return !!this.startDate && !!this.endDate && this.startDate.isBefore(this.endDate) && !!this.rate;
    }
    setPromoCode(code) {
        if (this.promoCode !== code.toUpperCase()) {
            this.setPromoCodeStatus(EPromoCodeStatus.New);
            this.promoOnly = false;
        }
        this.promoCode = code.toUpperCase();
    }
    setPromoOnly(value) {
        this.promoOnly = value;
    }
    setStale(status) {
        this.isStale = status;
    }
    /**
     * Sets the promo code status and optionally a warning message.
     *
     * @param status - The new status: EPromoCodeStatus.
     * @param warningMessage - Optional warning message shown when status is 'invalid'.
     */
    setPromoCodeStatus(status, warningMessage) {
        this.promoCodeStatus = this.promoCode ? status : EPromoCodeStatus.New;
        this.setPromoCodeWarningMessage([EPromoCodeStatus.Invalid, EPromoCodeStatus.Forbidden].includes(this.promoCodeStatus) ? warningMessage || '' : '');
    }
    /**
     * Stores the warning message for an invalid promo code.
     *
     * @param message - The warning message to display.
     */
    setPromoCodeWarningMessage(message) {
        this.promoCodeWarningMessage = message;
    }
    /**
     * Gets the stored warning message for the promo code.
     *
     * @returns The warning message as a string.
     */
    getPromoCodeWarningMessage() {
        return this.promoCodeWarningMessage;
    }
    setStartDate(date) {
        if ((date === null || date === void 0 ? void 0 : date.isValid()) || date === undefined) {
            this.startDate = date;
        }
    }
    setEndDate(date) {
        if ((date === null || date === void 0 ? void 0 : date.isValid()) || date === undefined) {
            this.endDate = date;
        }
    }
    setAdults(adults) {
        this.adults = adults;
    }
    setChildren(children) {
        this.children = children;
    }
    setInfants(infants) {
        this.infants = infants;
    }
    setPreGuestsState() {
        this.preGuestsState.adults = this.adults;
        this.preGuestsState.children = this.children;
        this.preGuestsState.infants = this.infants;
        this.preGuestsState.startDate = this.startDate;
        this.preGuestsState.endDate = this.endDate;
    }
    discardGuestsState() {
        this.setAdults(this.preGuestsState.adults);
        this.setChildren(this.preGuestsState.children);
        this.setInfants(this.preGuestsState.infants);
        this.setStartDate(this.preGuestsState.startDate);
        this.setEndDate(this.preGuestsState.endDate);
    }
    setRate(rate, upsellEnabled) {
        if (upsellEnabled && this.rate) {
            this.setPreUpsellRoomRate(this.rate);
        }
        this.rate = rate;
        if (rate) {
            const room = rate.getRoom();
            this.room = room;
            if (room.code) {
                this.roomCode = room.code; // [step/room] Update Indicates availability for a specific room
            }
        }
    }
    setPreUpsellRoomRate(roomRate) {
        this.preUpsellRoomRate = roomRate;
    }
    getPreUpsellRoomRate() {
        return this.preUpsellRoomRate;
    }
    getTotalPrice(getCost = false) {
        var _a;
        return (_a = this.getRate()) === null || _a === void 0 ? void 0 : _a.getTotalPrice(getCost);
    }
    checkDiffFromReservation(res) {
        const differences = {};
        if (res.total.beforeFees) {
            // This beforeFees field will be included when we're using Itemised Fees. Because fees can be a part of
            // rates, we'll just confirm that the price excluding fees is correct for now.
            if (Number(res.total.beforeFees).toFixed(2) !== Number(this.getTotalPrice(true)).toFixed(2)) {
                differences.totalPrice = {
                    before: this.getTotalPrice(true),
                    after: res.total.beforeFees,
                };
            }
        }
        else {
            if (Number(res.total.afterTax).toFixed(2) !== Number(this.getTotalPrice()).toFixed(2)) {
                differences.totalPrice = {
                    before: this.getTotalPrice(),
                    after: res.total.afterTax,
                };
            }
        }
        if (Object.keys(differences).length) {
            differences.id = this.getID();
            return differences;
        }
        else {
            return false;
        }
    }
    setAuxiliaryFilter(value) {
        this.auxiliaryFilter = value;
    }
    getAuxiliaryFilter() {
        return this.auxiliaryFilter;
    }
    getEnableRoomCodeFilter() {
        return this.enableRoomCodeFilter;
    }
    setEnableRoomCodeFilter(enable) {
        this.enableRoomCodeFilter = enable;
    }
    getRoomCode() {
        return this.roomCode || '';
    }
    setRoomCode(roomCode) {
        this.roomCode = roomCode;
    }
}
exports.default = BasketRow;
//# sourceMappingURL=BasketRow.js.map