"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const dayjs_1 = __importDefault(require("dayjs"));
const GetAvailabilityError_1 = __importDefault(require("errors/GetAvailabilityError"));
const NoHotelSelectedError_1 = require("errors/NoHotelSelectedError");
const RoomstayError_1 = require("errors/RoomstayError");
const BasketContextErrorHandler_1 = require("handlers/BasketContextErrorHandler");
const BaseAPI_1 = __importStar(require("./BaseAPI"));
const APIError_1 = require("../errors/APIError");
const BasketRow_1 = require("../models/BasketRow");
const Room_1 = require("../models/Room/Room");
const RoomRate_1 = require("../models/Room/RoomRate");
const RoomRateNight_1 = __importDefault(require("../models/Room/RoomRateNight"));
const RoomstayThemeEngine_1 = __importDefault(require("../providers/RoomstayThemeEngine"));
class AvailabilityAPI extends BaseAPI_1.default {
    constructor() {
        super();
        this.roomTypesData = null;
        this.ratePlansData = null;
        this.cachedMinNightStay = {};
        this.cachedHasMinStayUpsellOpportunities = {};
        this.calendar = {};
        this.arrivalMinNightStay = {};
        this.arrivalMaxNightStay = {};
        this.crossSellHotelInfo = {};
        this.calendarWarnings = {};
        this.availabilityWarnings = {};
        this.fetchDataPromise = {};
        this.calendarPromises = {};
        this.cachedMidNightStayPromises = {};
        this.promoCodeDetails = {};
        this.cachedAreaAvailability = {};
        this.areaAvailabilityPromises = {};
        this.getCheapestPricePerDay = (fromDate_1, toDate_1, adults_1, children_1, infants_1, promoCode_1, roomCode_1, rateCode_1, hotelId_1, ...args_1) => __awaiter(this, [fromDate_1, toDate_1, adults_1, children_1, infants_1, promoCode_1, roomCode_1, rateCode_1, hotelId_1, ...args_1], void 0, function* (fromDate, toDate, adults, children, infants, promoCode, roomCode, rateCode, hotelId, memberNumber = '', isCrossSell = false) {
            let dayPricingData = null;
            if (fromDate === undefined) {
                return {};
            }
            try {
                const response = yield this.fetchCalendar(fromDate, adults, children, infants, promoCode, roomCode, rateCode, hotelId, memberNumber, undefined, isCrossSell);
                dayPricingData = response === null || response === void 0 ? void 0 : response.prices;
            }
            catch (ex) {
                if (!(ex instanceof GetAvailabilityError_1.default)) {
                    throw ex;
                }
                else {
                    return {};
                }
            }
            if (!dayPricingData) {
                return {};
            }
            const daysBetween = toDate.diff(fromDate, 'day');
            const prices = {};
            for (let i = 0; i <= daysBetween; i++) {
                const currentDay = fromDate.add(i, 'day');
                prices[currentDay.format(BaseAPI_1.API_DATE_FORMAT)] = dayPricingData[currentDay.format(BaseAPI_1.API_DATE_FORMAT)];
            }
            return prices;
        });
        this.getCheapestPriceForDay = (day_1, adults_1, children_1, infants_1, promoCode_1, roomCode_1, rateCode_1, hotelID_1, ...args_1) => __awaiter(this, [day_1, adults_1, children_1, infants_1, promoCode_1, roomCode_1, rateCode_1, hotelID_1, ...args_1], void 0, function* (day, adults, children, infants, promoCode, roomCode, rateCode, hotelID, memberNumber = '', parseErrors = true) {
            if (!day || day.isBefore((0, dayjs_1.default)(), 'date'))
                return null;
            let dataForQuery = null;
            try {
                dataForQuery = yield this.fetchCalendar(day, adults, children, infants, promoCode, roomCode, rateCode, hotelID, memberNumber, parseErrors, false);
            }
            catch (ex) {
                console.log(ex);
            }
            if (!(dataForQuery === null || dataForQuery === void 0 ? void 0 : dataForQuery.prices)) {
                return null;
            }
            const priceForDay = dataForQuery.prices[day.format(BaseAPI_1.API_DATE_FORMAT)];
            const arrivalMinNightStay = dataForQuery.arrivalMinNightStay[day.format(BaseAPI_1.API_DATE_FORMAT)];
            const arrivalMaxNightStay = dataForQuery.arrivalMaxNightStay[day.format(BaseAPI_1.API_DATE_FORMAT)];
            return {
                price: priceForDay,
                perCent: 0,
                arrivalMinNightStay,
                arrivalMaxNightStay,
            };
        });
        this.fetchCalendar = (month_1, adults_1, children_1, infants_1, promoCode_1, roomCode_1, rateCode_1, hotelId_1, ...args_1) => __awaiter(this, [month_1, adults_1, children_1, infants_1, promoCode_1, roomCode_1, rateCode_1, hotelId_1, ...args_1], void 0, function* (month, adults, children, infants, promoCode, roomCode, rateCode, hotelId, memberNumber = '', parseErrors = true, isCrossSell = false) {
            month = month !== null && month !== void 0 ? month : (0, dayjs_1.default)();
            let fromMonth = month.startOf('month');
            fromMonth = Number(fromMonth.format('M')) % 2 === 0 ? fromMonth.subtract(1, 'month') : (fromMonth = month);
            fromMonth = fromMonth.startOf('month');
            const now = (0, dayjs_1.default)();
            if (fromMonth.isBefore(now, 'date')) {
                fromMonth = now;
            }
            const toMonth = fromMonth.add(1, 'month').endOf('month');
            const fromDatePretty = fromMonth.format(BaseAPI_1.API_DATE_FORMAT);
            const toDatePretty = toMonth.format(BaseAPI_1.API_DATE_FORMAT);
            const targetHotel = hotelId;
            if (!targetHotel) {
                return null;
            }
            const id = this.getQueryID([targetHotel, fromDatePretty, toDatePretty, adults, children, infants, promoCode, roomCode, rateCode, isCrossSell, memberNumber]);
            // Don't parse warnings when we're making a cross-hotel availability request
            if (this.calendar[id] && parseErrors) {
                if (this.calendarWarnings[id]) {
                    BasketContextErrorHandler_1.BasketContextErrorHandler.handleAvailabilityWarnings(this.calendarWarnings[id]);
                }
                else {
                    BasketContextErrorHandler_1.BasketContextErrorHandler.handlePromoSuccess(promoCode);
                }
                return {
                    prices: this.calendar[id],
                    arrivalMinNightStay: this.arrivalMinNightStay[id],
                    arrivalMaxNightStay: this.arrivalMaxNightStay[id],
                };
            }
            if (!!this.calendarPromises[id]) {
                return this.calendarPromises[id];
            }
            this.calendarPromises[id] = new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () {
                var _a, _b;
                const searchParams = Object.assign(Object.assign({ checkInDate: fromDatePretty, checkOutDate: toDatePretty, adults: `${adults}`, children: `${children}`, infants: `${infants}`, promoCode: `${promoCode}`, includeHotelInfo: isCrossSell ? `0` : `1`, memberNumber: `${memberNumber}` }, (roomCode ? { roomCode } : {})), (rateCode ? { rateCode } : {}));
                const queryParams = new URLSearchParams(searchParams);
                const apiPath = `${this.getApiPath()}availability/calendar/${targetHotel}?${queryParams.toString()}`;
                let response;
                try {
                    response = yield fetch(apiPath, {
                        credentials: 'omit',
                        headers: yield BaseAPI_1.default.getBaseHeaders(),
                    });
                }
                catch (error) {
                    console.error('Error fetching availability calendar:', error);
                }
                if (response === null || response === void 0 ? void 0 : response.ok) {
                    const json = yield response.json();
                    // Don't parse warnings when we're making a cross-hotel availability request
                    if (parseErrors) {
                        if (json.warnings && json.warnings.length) {
                            BasketContextErrorHandler_1.BasketContextErrorHandler.handleAvailabilityWarnings(json.warnings);
                            this.calendarWarnings[id] = json.warnings;
                        }
                        else {
                            BasketContextErrorHandler_1.BasketContextErrorHandler.handlePromoSuccess(promoCode);
                        }
                    }
                    Object.values(json.prices).forEach((price) => {
                        if (!AvailabilityAPI.minNightPrice || Number(price) < AvailabilityAPI.minNightPrice) {
                            AvailabilityAPI.minNightPrice = Number(price);
                        }
                        if (AvailabilityAPI.maxNightPrice < Number(price)) {
                            AvailabilityAPI.maxNightPrice = Number(price);
                        }
                    });
                    if (hotelId) {
                        this.crossSellHotelInfo[String(hotelId)] = json.hotel;
                    }
                    this.arrivalMinNightStay[id] = (_a = json === null || json === void 0 ? void 0 : json.arrivalMinNightStay) !== null && _a !== void 0 ? _a : {};
                    this.arrivalMaxNightStay[id] = (_b = json === null || json === void 0 ? void 0 : json.arrivalMaxNightStay) !== null && _b !== void 0 ? _b : {};
                    this.calendar[id] = json.prices;
                    resolve({
                        prices: this.calendar[id],
                        arrivalMinNightStay: this.arrivalMinNightStay[id],
                        arrivalMaxNightStay: this.arrivalMaxNightStay[id],
                    });
                }
                else {
                    reject(new GetAvailabilityError_1.default(fromMonth, toMonth));
                }
            }));
            return this.calendarPromises[id];
        });
        this.invalidateAvailability = (basketRow, hotelId) => __awaiter(this, void 0, void 0, function* () {
            var _a;
            const today = (0, dayjs_1.default)();
            const adults = basketRow.getAdults();
            const children = basketRow.getChildren();
            const infants = basketRow.getInfants();
            const promoCode = basketRow.getPromoCode();
            const roomCode = basketRow.getRoomCode();
            let toDate = basketRow.getEndDate();
            const fromDate = ((_a = basketRow.getStartDate()) === null || _a === void 0 ? void 0 : _a.isBefore(today, 'day')) ? today : basketRow.getStartDate();
            let oneNightStay = false;
            if (fromDate.isSameOrAfter(toDate, 'date')) {
                oneNightStay = true;
                toDate = fromDate.add(1, 'day');
            }
            const id = this.getQueryID([hotelId, fromDate, toDate, adults, children, infants, promoCode, roomCode, RoomstayThemeEngine_1.default.selectedLang, oneNightStay]);
            delete this.cachedAvailability[id];
        });
        this.fetchMinNightStayData = (basketRow, hotelID, memberNumber) => __awaiter(this, void 0, void 0, function* () {
            // TODO: refactor  this breakdown.
            var _a;
            if (!basketRow) {
                return;
            }
            if (!hotelID) {
                throw new NoHotelSelectedError_1.NoHotelSelectedError();
            }
            const today = (0, dayjs_1.default)();
            const adults = basketRow.getAdults();
            const children = basketRow.getChildren();
            const infants = basketRow.getInfants();
            const promoCode = basketRow.getPromoCode();
            const roomCode = basketRow.getRoomCode();
            let toDate = basketRow.getEndDate();
            const fromDate = ((_a = basketRow.getStartDate()) === null || _a === void 0 ? void 0 : _a.isBefore(today, 'day')) ? today : basketRow.getStartDate();
            let oneNightStay = false;
            if (fromDate.isSameOrAfter(toDate, 'date')) {
                oneNightStay = true;
                toDate = fromDate.add(1, 'day');
            }
            const id = this.getQueryID([hotelID, fromDate, toDate, adults, children, promoCode, roomCode, RoomstayThemeEngine_1.default.selectedLang, oneNightStay, memberNumber]);
            if (this.cachedMinNightStay[id]) {
                return this.cachedMinNightStay[id];
            }
            if (!!this.cachedMidNightStayPromises[id]) {
                return this.cachedMidNightStayPromises[id];
            }
            this.cachedMidNightStayPromises[id] = new Promise((resolve) => __awaiter(this, void 0, void 0, function* () {
                const json = yield this.get(BaseAPI_1.APIEndpoint.MinNightStay, Object.assign({ checkInDate: fromDate, checkOutDate: toDate, adults,
                    children,
                    infants,
                    promoCode,
                    memberNumber }, (roomCode ? { roomCode } : {})), '', hotelID);
                delete this.cachedMidNightStayPromises[id];
                this.cachedMinNightStay[id] = json;
                resolve(this.cachedMinNightStay[id]);
            }));
            return this.cachedMidNightStayPromises[id];
        });
        /**
         * Fetches availability data with minimum stay extensions.
         * This is used for finding upsell opportunities that require extending the stay.
         */
        this.fetchMinimumStayExtensions = (basketRow, hotelId, memberNumber) => __awaiter(this, void 0, void 0, function* () {
            return this.fetchAvailabilityData(basketRow, hotelId, memberNumber, false, false, true);
        });
        /**
         * Fetches availability data.
         *
         * @param basketRow - The basket row containing booking details.
         * @param hotelId - The unique identifier of the hotel.
         * @param memberNumber - (Optional) The membership number of the user.
         * @param ignoreRoomFilter - If true, skips sending the room code filter in the API request. Default: false.
         * @param eager - If true, returns alternative availability if selected dates are unavailable
         * @param findMinStayExtensions - If true, returns availability for extended dates to meet minimum stay requirements. Default: false.
         * @returns The fetched availability data.
         */
        this.fetchAvailabilityData = (basketRow_1, hotelId_1, memberNumber_1, ...args_1) => __awaiter(this, [basketRow_1, hotelId_1, memberNumber_1, ...args_1], void 0, function* (basketRow, hotelId, memberNumber, ignoreRoomFilter = false, eager = false, findMinStayExtensions = false) {
            var _a;
            const today = (0, dayjs_1.default)();
            if (!basketRow) {
                return;
            }
            const adults = basketRow.getAdults();
            const children = basketRow.getChildren();
            const infants = basketRow.getInfants();
            const promoCode = basketRow.getPromoCodeStatus() === BasketRow_1.EPromoCodeStatus.Forbidden ? '' : basketRow.getPromoCode();
            const promoOnly = basketRow.getPromoOnly();
            const enableRoomCodeFilter = basketRow.getEnableRoomCodeFilter();
            // If ignoreRoomFilter true, skips sending the room code filter
            // Otherwise, if the the URL's room parameter is present, send the room code filter
            const roomCodeParam = ignoreRoomFilter ? '' : enableRoomCodeFilter ? basketRow.getRoomCode() : '';
            let toDate = basketRow.getEndDate();
            const fromDate = ((_a = basketRow.getStartDate()) === null || _a === void 0 ? void 0 : _a.isBefore(today, 'day')) ? today : basketRow.getStartDate();
            let oneNightStay = false;
            if (fromDate.isSameOrAfter(toDate, 'date')) {
                oneNightStay = true;
                toDate = fromDate.add(1, 'day');
            }
            const id = this.getQueryID([
                hotelId,
                fromDate,
                toDate,
                adults,
                children,
                infants,
                promoCode,
                roomCodeParam,
                RoomstayThemeEngine_1.default.selectedLang,
                oneNightStay,
                memberNumber,
                findMinStayExtensions,
            ]);
            // Don't parse warnings when we're making a cross-hotel availability request
            if (this.cachedAvailability[id]) {
                if (this.availabilityWarnings[id]) {
                    BasketContextErrorHandler_1.BasketContextErrorHandler.handleAvailabilityWarnings(this.availabilityWarnings[id]);
                }
                else {
                    const promoCodeDetails = this.promoCodeDetails[promoCode];
                    BasketContextErrorHandler_1.BasketContextErrorHandler.handlePromoSuccess(promoCode, promoCodeDetails === null || promoCodeDetails === void 0 ? void 0 : promoCodeDetails.oneTimeUseOnly);
                }
                return this.cachedAvailability[id];
            }
            if (!!this.fetchDataPromise[id]) {
                return this.fetchDataPromise[id];
            }
            else {
                this.fetchDataPromise[id] = new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () {
                    var _a, _b;
                    try {
                        const json = yield this.get(BaseAPI_1.APIEndpoint.Availability, Object.assign(Object.assign(Object.assign({ checkInDate: fromDate, checkOutDate: toDate, adults,
                            children,
                            infants,
                            promoCode,
                            promoOnly,
                            memberNumber }, (eager && { searchType: 'eager' })), (roomCodeParam ? { roomCode: roomCodeParam } : {})), (findMinStayExtensions ? { findMinStayExtensions: 'true' } : {})), '', hotelId);
                        this.fetchDataPromise[id] = null;
                        if (eager && json.alternativeAvailability) {
                            // There was no availability for the currently selected dates, but we eagerly searched and found alternative dates with availability.
                            const roomArray = this.parseRoomsFromAvailability(json.alternativeAvailability.availability, oneNightStay);
                            const checkInDate = json.alternativeAvailability.checkInDate;
                            const checkOutDate = json.alternativeAvailability.checkOutDate;
                            basketRow.setStartDate((0, dayjs_1.default)(checkInDate));
                            basketRow.setEndDate((0, dayjs_1.default)(checkOutDate));
                            resolve(roomArray);
                            return;
                        }
                        const roomArray = this.parseRoomsFromAvailability(json, oneNightStay);
                        this.cachedAvailability[id] = roomArray;
                        this.cachedHasMinStayUpsellOpportunities[id] = json.hasMinStayUpsellOpportunities || false;
                        resolve(roomArray);
                        if ((_a = json.warnings) === null || _a === void 0 ? void 0 : _a.length) {
                            this.availabilityWarnings[id] = json.warnings.map((warning) => warning.message);
                            BasketContextErrorHandler_1.BasketContextErrorHandler.handleAvailabilityWarnings(json.warnings);
                        }
                        else {
                            if (json.promoCodeDetails) {
                                this.promoCodeDetails[promoCode] = json.promoCodeDetails;
                            }
                            BasketContextErrorHandler_1.BasketContextErrorHandler.handlePromoSuccess(promoCode, (_b = json.promoCodeDetails) === null || _b === void 0 ? void 0 : _b.oneTimeUseOnly);
                        }
                        resolve([]);
                    }
                    catch (ex) {
                        return reject(new APIError_1.APIError());
                    }
                })).catch((reason) => {
                    console.error(reason);
                    throw new RoomstayError_1.RoomstayError('Failed to load calendar availability');
                });
                return this.fetchDataPromise[id];
            }
        });
        this.fetchAvailability = (_a) => __awaiter(this, [_a], void 0, function* ({ fromDate, toDate, adults, children, infants, promoCode, roomCode, promoOnly, hotelId, }) {
            if (!fromDate || !toDate)
                return;
            return yield this.get(BaseAPI_1.APIEndpoint.Availability, Object.assign({ checkInDate: fromDate, checkOutDate: toDate, adults,
                children,
                infants,
                promoCode,
                promoOnly }, (roomCode ? { roomCode } : {})), '', hotelId);
        });
        this.fetchAreaAvailability = (basketRow, hotelId, auxiliaryFilters) => __awaiter(this, void 0, void 0, function* () {
            const roomCodes = Object.keys(this.rooms);
            const serializedAuxiliaryFilters = JSON.stringify(auxiliaryFilters);
            const id = this.getQueryID([hotelId, basketRow.getStartDate(), basketRow.getEndDate(), roomCodes.join(','), serializedAuxiliaryFilters]);
            if (id in this.cachedAreaAvailability) {
                return this.cachedAreaAvailability[id];
            }
            if (id in this.areaAvailabilityPromises) {
                return this.areaAvailabilityPromises[id];
            }
            this.areaAvailabilityPromises[id] = this.get(BaseAPI_1.APIEndpoint.AreaAvailability, {
                roomCodes: Object.keys(this.rooms),
                checkInDate: basketRow.getStartDate(),
                checkOutDate: basketRow.getEndDate(),
                auxiliaryFilters: serializedAuxiliaryFilters,
            }, '', hotelId);
            const result = yield this.areaAvailabilityPromises[id];
            this.cachedAreaAvailability[id] = result;
            return result;
        });
        this.getQueryID = (params) => {
            return params.map((param) => (param && param.format ? param.format(BaseAPI_1.API_DATE_FORMAT) : param)).join('-');
        };
        this.rooms = {};
        this.rates = {};
        this.cachedAvailability = {};
    }
    getCrossSellHotelInfo(hotelId) {
        var _a;
        return (_a = this.crossSellHotelInfo[String(hotelId)]) !== null && _a !== void 0 ? _a : {};
    }
    getPromoCodeDetails(promoCode) {
        var _a;
        return (_a = this.promoCodeDetails[promoCode]) !== null && _a !== void 0 ? _a : null;
    }
    /**
     * Check if minimum stay upsell opportunities exist.
     */
    hasMinStayUpsellOpportunities(basketRow, hotelId, memberNumber) {
        const params = this.getQueryIDParams(basketRow, hotelId, memberNumber);
        const id = this.getQueryID(params);
        return this.cachedHasMinStayUpsellOpportunities[id] || false;
    }
    // TODO: Add a type for the JSON response
    parseRoomsFromAvailability(json, oneNightStay = false) {
        const dateToObject = (data) => {
            data.validUntil = (0, dayjs_1.default)(data.validUntil);
            data.cachedSince = (0, dayjs_1.default)(data.cachedSince);
            return data;
        };
        Object.keys(json.guaranteePolicies).map((code) => {
            var _a, _b;
            if ((_b = (_a = json.guaranteePolicyDetails) === null || _a === void 0 ? void 0 : _a[code]) === null || _b === void 0 ? void 0 : _b.depositMode) {
                AvailabilityAPI.policyMappings.guarantee[code] = json.guaranteePolicyDetails[code];
            }
            else {
                // For backward compatibility and SynXis
                AvailabilityAPI.policyMappings.guarantee[code] = {
                    code,
                    name: code,
                    longDescription: json.guaranteePolicies[code],
                    hide: false,
                    depositMode: null,
                };
            }
        });
        if (json.cancelPolicies) {
            Object.keys(json.cancelPolicies).map((code) => {
                AvailabilityAPI.policyMappings.cancel[code] = json.cancelPolicies[code];
            });
        }
        const rooms = {};
        if (json.roomTypes) {
            const allRoomsByKey = Object.keys(json.roomTypes);
            if (allRoomsByKey.length) {
                this.roomTypesData = dateToObject(json.roomTypes);
                allRoomsByKey.forEach((roomCode) => {
                    this.roomTypesData[roomCode].code = roomCode;
                    this.rooms[roomCode] = Room_1.Room.fromData(this.roomTypesData[roomCode]);
                    this.rooms[roomCode].code = roomCode;
                    rooms[roomCode] = this.rooms[roomCode];
                });
            }
        }
        if (json.ratePlans) {
            const allRatesByKey = Object.keys(json.ratePlans);
            if (allRatesByKey.length) {
                this.ratePlansData = dateToObject(json.ratePlans);
                allRatesByKey.forEach((rateCode) => {
                    this.ratePlansData[rateCode].code = rateCode;
                    this.rates[rateCode] = RoomRate_1.RoomRate.fromData(this.ratePlansData[rateCode]);
                });
            }
        }
        if (json.roomNights) {
            const roomNights = json.roomNights;
            const allNightsByKey = Object.keys(roomNights);
            let first = true;
            if (allNightsByKey.length) {
                allNightsByKey.forEach((date) => {
                    const day = (0, dayjs_1.default)(date);
                    Object.keys(roomNights[date]).forEach((roomCode) => {
                        Object.keys(roomNights[date][roomCode].rates).forEach((rateKey) => {
                            var _a, _b, _c;
                            const nightData = roomNights[date][roomCode].rates[rateKey];
                            if (first) {
                                const rate = RoomRate_1.RoomRate.fromData(this.ratePlansData[rateKey]);
                                rate.code = rateKey;
                                rooms[roomCode].addRate(rate);
                            }
                            if (oneNightStay && Object.keys((_c = (_b = (_a = rooms[roomCode]) === null || _a === void 0 ? void 0 : _a.getRate(rateKey)) === null || _b === void 0 ? void 0 : _b.nightRates) !== null && _c !== void 0 ? _c : {}).length) {
                                return;
                            }
                            const rateNight = new RoomRateNight_1.default();
                            rateNight.available = roomNights[date][roomCode].available.toString();
                            rateNight.cost = nightData.cost.toString();
                            rateNight.discount = nightData.discount.toString();
                            rateNight.total = nightData.total.toString();
                            rateNight.tax = nightData.tax.toString();
                            rateNight.fee = nightData.fee.toString();
                            rateNight.date = day;
                            if (nightData.fees) {
                                for (const fee of nightData.fees) {
                                    rateNight.fees.push({ name: fee.name, amount: fee.amount });
                                }
                            }
                            rooms[roomCode].getRate(rateKey).nightRates[date] = rateNight;
                        });
                    });
                    first = false;
                });
            }
            return Object.values(rooms);
        }
        return [];
    }
    /**
     * TODO: This logic is repeated multiple times throughout this file, we should try and refactor parts of this file to use this function.
     */
    getQueryIDParams(basketRow, hotelId, memberNumber, ignoreRoomFilter = false, findMinStayExtensions = false) {
        var _a;
        const today = (0, dayjs_1.default)();
        const adults = basketRow.getAdults();
        const children = basketRow.getChildren();
        const infants = basketRow.getInfants();
        const promoCode = basketRow.getPromoCode();
        const enableRoomCodeFilter = basketRow.getEnableRoomCodeFilter();
        const roomCodeParam = ignoreRoomFilter ? '' : enableRoomCodeFilter ? basketRow.getRoomCode() : '';
        let toDate = basketRow.getEndDate();
        const fromDate = ((_a = basketRow.getStartDate()) === null || _a === void 0 ? void 0 : _a.isBefore(today, 'day')) ? today : basketRow.getStartDate();
        let oneNightStay = false;
        if (fromDate.isSameOrAfter(toDate, 'date')) {
            oneNightStay = true;
            toDate = fromDate.add(1, 'day');
        }
        return [
            hotelId,
            fromDate,
            toDate,
            adults,
            children,
            infants,
            promoCode,
            roomCodeParam,
            RoomstayThemeEngine_1.default.selectedLang,
            oneNightStay,
            memberNumber,
            findMinStayExtensions,
        ];
    }
}
AvailabilityAPI.policyMappings = { guarantee: {}, cancel: {} };
AvailabilityAPI.maxNightPrice = 0;
AvailabilityAPI.minNightPrice = null;
exports.default = AvailabilityAPI;
//# sourceMappingURL=AvailabilityAPI.js.map