"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const core_1 = require("@roomstay/core");
const Fee_1 = require("./Fee");
class BasketAddonRow {
    constructor(addon) {
        if (addon) {
            this.setAddon(addon);
        }
        this.quantity = 1;
        this.adultQuantity = 1;
        this.childQuantity = 0;
        this.uniqId = btoa(((Date.now() % 1000) / 1000) * Math.random() + '');
        this.numberOfAvailableNights = Object.values(addon === null || addon === void 0 ? void 0 : addon.availability).length;
    }
    getAddon() {
        return this.addon;
    }
    getSelectedDate() {
        return this.selectedDate;
    }
    getSelectedTime() {
        return this.selectedTime;
    }
    getQuantity() {
        return this.quantity;
    }
    getAdultQuantity() {
        return this.adultQuantity;
    }
    getNumberOfAvailableNights() {
        return this.numberOfAvailableNights;
    }
    getCalculationParams() {
        var _a, _b;
        const addon = this.getAddon();
        const date = this.getSelectedDate();
        const priceInfo = addon.availability[date];
        return {
            availability: this.getAddon().availability,
            code: addon.code,
            inclusive: false,
            quantity: this.getQuantity(),
            adultQuantity: this.getAdultQuantity(),
            childQuantity: this.getChildQuantity(),
            description: addon.description,
            name: addon.name,
            category: addon.category,
            image: addon.image,
            price: (_a = priceInfo.price) !== null && _a !== void 0 ? _a : 0,
            adultPrice: priceInfo.adultPrice,
            childPrice: priceInfo.childPrice,
            fee: (_b = priceInfo.fee) !== null && _b !== void 0 ? _b : 0,
            adultFee: priceInfo.adultFee,
            childFee: priceInfo.childFee,
            fees: priceInfo.fees,
            adultFees: priceInfo.adultFees,
            childFees: priceInfo.childFees,
            pricingType: addon.pricingType,
            nights: addon.nights,
        };
    }
    getTotalFees() {
        return core_1.TotalCalculator.calculateBasketAddonTotal(this.getCalculationParams()).totalFees;
    }
    getTotalPrice() {
        return core_1.TotalCalculator.calculateBasketAddonTotal(this.getCalculationParams()).total;
    }
    getItemisedFees(hotelFees) {
        var _a, _b, _c;
        const addon = this.getAddon();
        const date = this.getSelectedDate();
        const priceInfo = addon.availability[date];
        const feeMap = new Map();
        if (((_a = priceInfo.fees) === null || _a === void 0 ? void 0 : _a.length) && this.getQuantity() > 0) {
            const fees = (0, Fee_1.mapSimpleFeesToItemisedFees)(priceInfo.fees, hotelFees);
            (0, Fee_1.accumulateFees)(feeMap, fees, this.getQuantity(), this.getNightModifier());
        }
        if (((_b = priceInfo.adultFees) === null || _b === void 0 ? void 0 : _b.length) && this.getAdultQuantity() > 0) {
            const fees = (0, Fee_1.mapSimpleFeesToItemisedFees)(priceInfo.adultFees, hotelFees);
            (0, Fee_1.accumulateFees)(feeMap, fees, this.getAdultQuantity(), this.getNightModifier());
        }
        if (((_c = priceInfo.childFees) === null || _c === void 0 ? void 0 : _c.length) && this.getChildQuantity() > 0) {
            const fees = (0, Fee_1.mapSimpleFeesToItemisedFees)(priceInfo.childFees, hotelFees);
            (0, Fee_1.accumulateFees)(feeMap, fees, this.getChildQuantity(), this.getNightModifier());
        }
        return (0, Fee_1.feeMapToArray)(feeMap);
    }
    /**
     * Returns the subtotal of an addon (without taking into account the nights modifier)
     */
    getAddonSubtotal() {
        const addon = this.getAddon();
        const date = this.getSelectedDate();
        const priceInfo = addon.availability[date];
        let price = 0;
        if (priceInfo.price && this.getQuantity() > 0) {
            price += this.getQuantity() * priceInfo.price;
        }
        if (priceInfo.adultPrice && this.getAdultQuantity() > 0) {
            price += this.getAdultQuantity() * priceInfo.adultPrice;
        }
        if (priceInfo.childPrice && this.getChildQuantity() > 0) {
            price += this.getChildQuantity() * priceInfo.childPrice;
        }
        return price;
    }
    getTotalQuantity() {
        const addon = this.getAddon();
        const date = this.getSelectedDate();
        const priceInfo = addon.availability[date];
        let quantity = 0;
        if (priceInfo.price) {
            quantity += this.getQuantity();
        }
        if (priceInfo.adultPrice || addon.pricingType === core_1.EAddonPricingType.PER_ADULT_OCCUPANCY_PER_NIGHT) {
            quantity += this.getAdultQuantity();
        }
        if (priceInfo.childPrice || addon.pricingType === core_1.EAddonPricingType.PER_CHILD_OCCUPANCY_PER_NIGHT) {
            quantity += this.getChildQuantity();
        }
        return quantity;
    }
    /**
     * This function returns a value that should multiply the total price of the addon for one (assumed) night
     * Depending on the pricing type
     * @returns number
     */
    getNightModifier() {
        const modifier = 1;
        if (core_1.ADDON_PER_NIGHT_TYPES.includes(this.addon.pricingType)) {
            return this.addon.checkOutDate.diff(this.addon.checkInDate, 'day');
        }
        else {
            return modifier;
        }
    }
    setAdultQuantity(value) {
        this.adultQuantity = value;
    }
    getChildQuantity() {
        return this.childQuantity;
    }
    setChildQuantity(value) {
        this.childQuantity = value;
    }
    getID() {
        return this.uniqId;
    }
    isValid() {
        return this.selectedDate && this.addon && this.quantity > 0;
    }
    setSelectedDate(date) {
        this.selectedDate = date;
    }
    setSelectedTime(time) {
        this.selectedTime = time;
    }
    setQuantity(quantity) {
        this.quantity = quantity;
    }
    setAddon(addon) {
        this.addon = addon;
    }
    /**
     * Calculate promo code discount for this addon
     * @param promoCode Promo code information
     * @param remainingFixedDiscount For flatQuantity and flatQuantityPerStay, the remaining discount after room nights consumed their share
     * @returns Discount amount
     */
    getDiscountAmount(promoCode, remainingFixedDiscount = 0) {
        if (!promoCode || !promoCode.applyToAddons) {
            return 0;
        }
        const basePriceWithoutFees = this.getAddonSubtotal() * this.getNightModifier();
        switch (promoCode.discountType) {
            case core_1.EPromoCodeDiscountType.FlatPercent:
                // Apply percentage discount to addon total
                return Math.round(basePriceWithoutFees * (promoCode.discountAmount / 100));
            case core_1.EPromoCodeDiscountType.FlatQuantity:
            case core_1.EPromoCodeDiscountType.FlatQuantityPerStay:
                // Use reamaining discount after room nights
                return Math.min(remainingFixedDiscount, basePriceWithoutFees);
            default:
                return 0;
        }
    }
    /**
     * Get total price before any promo code discount
     * @returns Price including fees but before discount
     */
    getPriceBeforeDiscount() {
        return this.getTotalPrice();
    }
    /**
     * Get total price after promo code discount
     * @param promoCode Promo code information
     * @param remainingFixedDiscount For flatQuantity and flatQuantityPerStay, the remaining discount after room nights consumed their share
     * @returns Final price after discount
     */
    getDiscountedTotalPrice(promoCode, remainingFixedDiscount = 0) {
        const originalPrice = this.getTotalPrice();
        const discount = this.getDiscountAmount(promoCode, remainingFixedDiscount);
        return Math.max(0, originalPrice - discount);
    }
    /**
     * Check if this addon has a discount applied
     * @param promoCode Promo code information
     * @param remainingFixedDiscount For flatQuantity and flatQuantityPerStay, the remaining discount after room nights consumed their share
     * @returns True if discount is applied
     */
    hasDiscount(promoCode, remainingFixedDiscount = 0) {
        return this.getDiscountAmount(promoCode, remainingFixedDiscount) > 0;
    }
}
exports.default = BasketAddonRow;
//# sourceMappingURL=BasketAddonRow.js.map