"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 __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.FullPageEngineContextWrapper = FullPageEngineContextWrapper;
const contexts_1 = require("../index.js");
const hooks_1 = require("../../hooks/index.js");
const core_1 = require("@roomstay/core");
const gc_frontend_1 = require("@roomstay/gc-frontend");
const dayjs_1 = __importDefault(require("dayjs"));
const react_1 = __importStar(require("react"));
const react_router_dom_1 = require("react-router-dom");
const NaturallyProgressedStepRoute_1 = __importDefault(require("routes/NaturallyProgressedStepRoute"));
const BaseAPI_1 = require("../../api/BaseAPI");
const LargeLoader_1 = __importDefault(require("../../components/generic/loader/LargeLoader"));
const RoomstayMark_1 = require("../../components/generic/RoomstayMark");
const ScrollToTop_1 = __importDefault(require("../../components/generic/ScrollToTop"));
const Header_1 = __importDefault(require("../../components/navigation/Header"));
const PrivateRoute_1 = require("../../containers/PrivateRoute");
const HistoryConsistentPush_1 = require("../../hooks/HistoryConsistentPush");
const AppQueryParameters_1 = require("../../models/AppQueryParameters");
const BasketRow_1 = __importDefault(require("../../models/BasketRow"));
const RateTypeFilter_1 = __importDefault(require("../../models/Room/Filters/RateTypeFilter"));
const RoomTypeFilter_1 = __importDefault(require("../../models/Room/Filters/RoomTypeFilter"));
const FindReservation_1 = __importStar(require("../../pages/findReservation/FindReservation"));
const FindReservationResults_1 = __importDefault(require("../../pages/findReservation/FindReservationResults"));
const HotelInfo_1 = __importDefault(require("../../pages/hotel/HotelInfo"));
const HotelInfoPlaceholder_1 = __importDefault(require("../../pages/hotel/HotelInfoPlaceholder"));
const StepHotel_1 = __importDefault(require("../../pages/steps/StepHotel/StepHotel"));
const AnalyticsEventsFeature_1 = __importDefault(require("../../providers/feature/AnalyticsEventsFeature"));
const DerbysoftClickTrackingFeature_1 = __importDefault(require("../../providers/feature/DerbysoftClickTrackingFeature"));
const FeaturedPromoFeature_1 = __importDefault(require("../../providers/feature/FeaturedPromoFeature"));
const GiftCardFeature_1 = __importDefault(require("../../providers/feature/GiftCardFeature"));
const MemberPortalFeature_1 = __importDefault(require("../../providers/feature/MemberPortalFeature"));
const FeatureProvider_1 = __importDefault(require("../../providers/FeatureProvider"));
const GetStepRoom_1 = __importDefault(require("../../util/GetStepRoom"));
const RouteManager_1 = require("../../util/RouteManager");
const StepManager_1 = __importDefault(require("../../util/StepManager"));
const EngineBodyLayout_1 = require("./EngineBodyLayout");
const EnginePageLayout_1 = require("./EnginePageLayout");
const AccountRouter = react_1.default.lazy(() => Promise.resolve().then(() => __importStar(require('../../pages/account/AccountRouter'))).then(({ AccountRouter }) => ({
    default: AccountRouter,
})));
function FullPageEngineContextWrapper() {
    var _a, _b, _c, _d, _e, _f, _g;
    const basketContext = (0, react_1.useContext)(contexts_1.BasketContext);
    const ccx = (0, react_1.useContext)(contexts_1.CompanyContext);
    const beContext = (0, react_1.useContext)(contexts_1.BookingEngineContext);
    const [engineReady, setEngineReady] = (0, react_1.useState)(false);
    const [isDefaultValuesInitialized, setIsDefaultValuesInitialized] = (0, react_1.useState)(false);
    const [urlParameters, setUrlParameters] = (0, react_1.useState)({});
    const [currentStep, setCurrentStep] = (0, react_1.useState)((_b = StepManager_1.default.getStepFromName((_a = beContext.engine.getInitialSession()) === null || _a === void 0 ? void 0 : _a.step)) !== null && _b !== void 0 ? _b : StepManager_1.default.getFirstStep());
    const [initialStep, setInitialStep] = (0, react_1.useState)(StepManager_1.default.getFirstStep());
    const { hotel } = (0, hooks_1.useCurrentHotel)();
    const location = (0, react_router_dom_1.useLocation)();
    const historyConsistentPush = (0, HistoryConsistentPush_1.useHistoryConsistentPush)();
    const navigate = (0, react_router_dom_1.useNavigate)();
    const isInStepRoot = (0, react_router_dom_1.useMatch)(StepManager_1.default.STEP_BASE);
    (0, react_1.useEffect)(() => {
        var _a;
        (_a = beContext.sessionProvider) === null || _a === void 0 ? void 0 : _a.updateSession({ step: currentStep.getName() });
        if (currentStep === StepHotel_1.default) {
            ccx.changeHotel(null);
        }
    }, [currentStep]);
    (0, react_1.useEffect)(() => {
        var _a;
        if ((_a = hotel === null || hotel === void 0 ? void 0 : hotel.company) === null || _a === void 0 ? void 0 : _a.enableDerbysoftFeed) {
            FeatureProvider_1.default.load(DerbysoftClickTrackingFeature_1.default);
        }
    }, [(_c = hotel === null || hotel === void 0 ? void 0 : hotel.company) === null || _c === void 0 ? void 0 : _c.enableDerbysoftFeed]);
    // Analytics Events (Meta CAPI + Meta Pixel)
    (0, react_1.useEffect)(() => {
        var _a, _b;
        const isEnabled = (_a = hotel === null || hotel === void 0 ? void 0 : hotel.integrations) === null || _a === void 0 ? void 0 : _a.includes(core_1.EIntegration.AnalyticsEvents);
        if (isEnabled && (hotel === null || hotel === void 0 ? void 0 : hotel.hotelID) && (hotel === null || hotel === void 0 ? void 0 : hotel.defaultCurrency)) {
            FeatureProvider_1.default.load(AnalyticsEventsFeature_1.default, {
                hotelId: hotel.hotelID,
                currency: hotel.defaultCurrency,
                metaPixelId: hotel.metaPixelId, // TODO: Introduce separate option to load Meta Pixel?
                firePixelEvents: !!hotel.metaPixelId, // TODO: Make this a separate option?
                debug: (_b = hotel.enableAnalyticsDebug) !== null && _b !== void 0 ? _b : false,
            });
        }
    }, [hotel === null || hotel === void 0 ? void 0 : hotel.integrations, hotel === null || hotel === void 0 ? void 0 : hotel.hotelID, hotel === null || hotel === void 0 ? void 0 : hotel.defaultCurrency, hotel === null || hotel === void 0 ? void 0 : hotel.metaPixelId, hotel === null || hotel === void 0 ? void 0 : hotel.enableAnalyticsDebug]);
    (0, react_1.useEffect)(() => {
        // Initialize default values only on StepDate and StepRoom routes (run once)
        if (!isDefaultValuesInitialized) {
            initializeDefaultValuesInitialized();
        }
    }, [isDefaultValuesInitialized]);
    const initializeDefaultValuesInitialized = () => {
        var _a, _b, _c, _d, _e, _f, _g, _h, _j;
        // Centralize this logic here and trigger updates based on URL changes
        const currentBasketRows = basketContext.currentBasketRows;
        let addXRooms = 1;
        if (currentBasketRows.length === 0) {
            const urlParameterBuilder = {};
            // The Choose Hotel step should not apply the room filter
            const shouldEnableRoomCodeFilter = currentStep.getName() !== StepHotel_1.default.getName();
            if (location.search) {
                const query = new URLSearchParams(location.search);
                const format = BaseAPI_1.API_DATE_FORMAT;
                let start = (0, dayjs_1.default)(query.get(AppQueryParameters_1.EAppQueryParameters.Arrive), format);
                let end = (0, dayjs_1.default)(query.get(AppQueryParameters_1.EAppQueryParameters.Depart), format);
                const promoCode = query.get(AppQueryParameters_1.EAppQueryParameters.PromoCode);
                const promoOnly = query.get(AppQueryParameters_1.EAppQueryParameters.PromoOnly);
                const promoFeatured = query.get(AppQueryParameters_1.EAppQueryParameters.PromoFeatured);
                if (promoCode) {
                    urlParameterBuilder.promoCode = promoCode;
                }
                if (promoOnly && promoOnly.toLowerCase() !== 'false') {
                    urlParameterBuilder.promoOnly = Boolean(promoOnly);
                }
                if (promoFeatured && promoFeatured.toLowerCase() !== 'false') {
                    FeatureProvider_1.default.load(FeaturedPromoFeature_1.default);
                    urlParameterBuilder.promoFeatured = true;
                }
                const updatedCurrentFilters = Object.assign({}, beContext.currentFilters);
                const roomCodes = query.getAll(AppQueryParameters_1.EAppQueryParameters.Room);
                if (roomCodes.length > 0 && shouldEnableRoomCodeFilter) {
                    // TODO: Refactor this to come from this context instead.
                    updatedCurrentFilters['RoomType'] = new RoomTypeFilter_1.default(roomCodes);
                }
                const rateCodes = query.getAll(AppQueryParameters_1.EAppQueryParameters.Rate);
                if (rateCodes.length > 0) {
                    // TODO: Refactor this to come from this context instead.
                    updatedCurrentFilters['RateType'] = new RateTypeFilter_1.default(rateCodes);
                }
                beContext.setCurrentFilters(updatedCurrentFilters);
                const hotelId = query.get(AppQueryParameters_1.EAppQueryParameters.Hotel);
                if (hotelId) {
                    if (ccx.changeHotel(hotelId)) {
                        if (!start.isValid()) {
                            start = (0, dayjs_1.default)().add(1, 'day');
                        }
                        if (!end.isValid()) {
                            end = start.add(1, 'day');
                        }
                        setInitialStep((0, GetStepRoom_1.default)());
                    }
                    urlParameterBuilder.hotelId = hotelId;
                }
                const defaultCity = query.get(AppQueryParameters_1.EAppQueryParameters.DefaultCity);
                if (defaultCity) {
                    urlParameterBuilder.defaultCity = defaultCity;
                }
                // We're doing dates last, as other properties, like hotelID might change them if they're not already set
                if (start.isValid() && end.isValid()) {
                    const today = (0, dayjs_1.default)().startOf('day');
                    if (start.isBefore(today)) {
                        start = today;
                    }
                    if (end.isBefore(start) || end.isSame(start)) {
                        end = start.add(1, 'day');
                    }
                    else if (end.isBefore(today.add(1, 'day')) || end.isSame(today)) {
                        end = today.add(1, 'day');
                    }
                    urlParameterBuilder.startDate = start;
                    urlParameterBuilder.endDate = end;
                }
                const parseQueryInt = (key, min = 0) => {
                    var _a;
                    const value = Number.parseInt((_a = query.get(key)) !== null && _a !== void 0 ? _a : '', 10);
                    return Number.isNaN(value) || value < min ? undefined : value;
                };
                addXRooms = (_a = parseQueryInt(AppQueryParameters_1.EAppQueryParameters.Rooms, 1)) !== null && _a !== void 0 ? _a : 1;
                const globalAdults = parseQueryInt(AppQueryParameters_1.EAppQueryParameters.Adults, 1);
                const globalChildren = parseQueryInt(AppQueryParameters_1.EAppQueryParameters.Children);
                const globalInfants = parseQueryInt(AppQueryParameters_1.EAppQueryParameters.Infants);
                urlParameterBuilder.rooms = [];
                for (let i = 0; i < addXRooms; i++) {
                    let roomOccupancy = 1;
                    let adults = (_b = parseQueryInt(`adults-${i + 1}`, 1)) !== null && _b !== void 0 ? _b : globalAdults;
                    query.delete(`adults-${i + 1}`);
                    // Check mixed occupancy limits first, then fallback to maxOccupancy
                    if ((_c = hotel === null || hotel === void 0 ? void 0 : hotel.occupancyLimits) === null || _c === void 0 ? void 0 : _c.highestAdultConfig) {
                        if (adults && adults > hotel.occupancyLimits.highestAdultConfig) {
                            adults = hotel.occupancyLimits.highestAdultConfig;
                        }
                    }
                    else if (adults && (hotel === null || hotel === void 0 ? void 0 : hotel.maxOccupancy) && (roomOccupancy = adults) > hotel.maxOccupancy) {
                        adults = undefined;
                    }
                    let children = (_d = parseQueryInt(`children-${i + 1}`)) !== null && _d !== void 0 ? _d : globalChildren;
                    query.delete(`children-${i + 1}`);
                    // Check mixed occupancy limits for children
                    if (((_e = hotel === null || hotel === void 0 ? void 0 : hotel.occupancyLimits) === null || _e === void 0 ? void 0 : _e.maxSelectableChildren) && adults) {
                        const maxChildren = hotel.occupancyLimits.maxSelectableChildren[adults];
                        if (maxChildren !== undefined && children && children > maxChildren) {
                            children = maxChildren > 0 ? maxChildren : undefined;
                        }
                    }
                    else if (children && (hotel === null || hotel === void 0 ? void 0 : hotel.maxOccupancy) && (roomOccupancy += children) > hotel.maxOccupancy) {
                        children = undefined;
                    }
                    let infants = (_f = parseQueryInt(`infants-${i + 1}`)) !== null && _f !== void 0 ? _f : globalInfants;
                    query.delete(`infants-${i + 1}`);
                    // Check mixed occupancy limits for infants (only if countInfantsInOccupancy is true)
                    if ((hotel === null || hotel === void 0 ? void 0 : hotel.countInfantsInOccupancy) && ((_g = hotel === null || hotel === void 0 ? void 0 : hotel.occupancyLimits) === null || _g === void 0 ? void 0 : _g.maxSelectableInfants) && adults) {
                        const maxInfants = hotel.occupancyLimits.maxSelectableInfants[adults];
                        if (maxInfants !== undefined && infants && infants > maxInfants) {
                            infants = maxInfants > 0 ? maxInfants : undefined;
                        }
                    }
                    else if (infants && (hotel === null || hotel === void 0 ? void 0 : hotel.maxOccupancy) && hotel.countInfantsInOccupancy && (roomOccupancy += infants) > hotel.maxOccupancy) {
                        infants = undefined;
                    }
                    urlParameterBuilder.rooms[i] = { adults, children, infants };
                }
                navigate({ search: query.toString() }, { replace: true });
                setUrlParameters(urlParameterBuilder);
            }
            const defaultValues = beContext.engine.getConfig().defaultValues;
            if (!('startDate' in urlParameterBuilder && 'endDate' in urlParameterBuilder) && (defaultValues === null || defaultValues === void 0 ? void 0 : defaultValues.checkIn) && (defaultValues === null || defaultValues === void 0 ? void 0 : defaultValues.checkout)) {
                urlParameterBuilder.startDate = (0, dayjs_1.default)(defaultValues.checkIn);
                urlParameterBuilder.endDate = (0, dayjs_1.default)(defaultValues.checkout);
            }
            let firstBasketRow = undefined;
            const { startDate, endDate, promoCode, promoOnly, rooms } = urlParameterBuilder;
            for (let i = 0; i < addXRooms; i++) {
                const { adults, children, infants } = (_j = (_h = rooms === null || rooms === void 0 ? void 0 : rooms[i]) !== null && _h !== void 0 ? _h : defaultValues === null || defaultValues === void 0 ? void 0 : defaultValues.guests) !== null && _j !== void 0 ? _j : {};
                const basketRow = new BasketRow_1.default(undefined, undefined, shouldEnableRoomCodeFilter);
                if (startDate) {
                    basketRow.setStartDate(startDate);
                }
                if (endDate) {
                    basketRow.setEndDate(endDate);
                }
                if (promoCode) {
                    basketRow.setPromoCode(promoCode);
                }
                if (promoOnly) {
                    basketRow.setPromoOnly(promoOnly);
                }
                if (adults) {
                    basketRow.setAdults(adults);
                }
                if (children) {
                    basketRow.setChildren(children);
                }
                if (infants) {
                    basketRow.setInfants(infants);
                }
                basketContext.addBasketRow(basketRow);
                if (i === 0) {
                    firstBasketRow = basketRow;
                }
            }
            if ((firstBasketRow === null || firstBasketRow === void 0 ? void 0 : firstBasketRow.getStartDate()) && firstBasketRow.getEndDate() && StepManager_1.default.getFirstStep() !== StepHotel_1.default) {
                basketContext.selectBasketRow(firstBasketRow);
                setInitialStep((0, GetStepRoom_1.default)());
            }
        }
        else {
            const initialSession = beContext.engine.getInitialSession();
            if (initialSession) {
                setInitialStep(StepManager_1.default.getStepFromName(initialSession.step));
            }
        }
        setIsDefaultValuesInitialized(true);
    };
    /**
     * Engine Ready useEffect, used to deffer loading the UI until everything engine wise is set up properly
     */
    (0, react_1.useEffect)(() => {
        if (!engineReady) {
            if (ccx.hotels.length > 0 && isDefaultValuesInitialized) {
                setEngineReady(true);
            }
        }
    }, [ccx.hotels, isDefaultValuesInitialized]);
    (0, react_1.useEffect)(() => {
        if (engineReady) {
            if (isInStepRoot && initialStep) {
                // We want to respect the browsers pathname, and only redirect to a defined step if
                // the pathname isn't set, or matches an unknown page.
                // Is the current location in the path? i.e does the user want to be somewhere specific
                let pathInLoadedSteps = false;
                for (const step of StepManager_1.default.getSteps()) {
                    // Using match instead of equals as some clients have skipped the trailing slash
                    // We also want to make sure to only match the start of the path, in case step contains nested paths.
                    if (location.pathname.match(new RegExp(`${step.getStepUrl()}.+`, 'ig'))) {
                        pathInLoadedSteps = true;
                        break;
                    }
                }
                // We're in /step/ but on a not recognized one.
                if (!pathInLoadedSteps) {
                    historyConsistentPush(initialStep.getStepUrl());
                }
            }
        }
    }, [engineReady]);
    (0, react_1.useEffect)(() => {
        if (hotel) {
            if (hotel.currentRoomSort) {
                beContext.setCurrentRoomSort(hotel.currentRoomSort);
            }
            if (hotel.currentRoomRateSort) {
                beContext.setCurrentRoomRateSort(hotel.currentRoomRateSort);
            }
        }
    }, [hotel === null || hotel === void 0 ? void 0 : hotel.currentRoomSort, hotel === null || hotel === void 0 ? void 0 : hotel.currentRoomRateSort]);
    const workingContext = { urlParameters, currentStep, setCurrentStep };
    return (react_1.default.createElement(contexts_1.FullPageEngineContext.Provider, { value: workingContext },
        react_1.default.createElement(contexts_1.ModalContextWrapper, null,
            react_1.default.createElement(ScrollToTop_1.default, null),
            react_1.default.createElement("header", { className: "engine-header" },
                react_1.default.createElement(Header_1.default, null)),
            engineReady && (react_1.default.createElement(react_router_dom_1.Routes, null,
                react_1.default.createElement(react_router_dom_1.Route, { path: "/", element: react_1.default.createElement(react_router_dom_1.Navigate, { to: StepManager_1.default.getFirstStep().getStepUrl(), replace: true }) }),
                react_1.default.createElement(react_router_dom_1.Route, { path: "/step", element: react_1.default.createElement(EngineBodyLayout_1.EngineBodyLayout, null) }, StepManager_1.default.getSteps().map((step) => (react_1.default.createElement(react_router_dom_1.Route, { key: step.getName(), path: `${step.getStepUrl()}*`, element: react_1.default.createElement(NaturallyProgressedStepRoute_1.default, { step: step }) })))),
                react_1.default.createElement(react_router_dom_1.Route, { path: "/*", element: react_1.default.createElement(EnginePageLayout_1.EnginePageLayout, null) },
                    react_1.default.createElement(react_router_dom_1.Route, { path: RouteManager_1.ROUTES.HOTEL_INFO.startsWith('/') ? RouteManager_1.ROUTES.HOTEL_INFO.substring(1) : RouteManager_1.ROUTES.HOTEL_INFO, element: react_1.default.createElement(react_1.default.Suspense, { fallback: react_1.default.createElement(HotelInfoPlaceholder_1.default, null) },
                            react_1.default.createElement(HotelInfo_1.default, null)) }),
                    Object.values(FindReservation_1.EFindReservationPath)
                        .filter((path) => MemberPortalFeature_1.default.isActive() || path === FindReservation_1.EFindReservationPath.FindReservation)
                        .map((path) => (react_1.default.createElement(react_router_dom_1.Route, { key: path, path: path, element: react_1.default.createElement(react_1.default.Suspense, { fallback: react_1.default.createElement("div", null, "Loading...") },
                            react_1.default.createElement(FindReservation_1.default, null)) }))),
                    react_1.default.createElement(react_router_dom_1.Route, { path: "find-reservation/:ref/:email", element: react_1.default.createElement(react_1.default.Suspense, { fallback: react_1.default.createElement("div", null, "Loading...") },
                            react_1.default.createElement(FindReservationResults_1.default, null)) }),
                    react_1.default.createElement(react_router_dom_1.Route, { path: "account/*", element: react_1.default.createElement(PrivateRoute_1.PrivateRoute, null, MemberPortalFeature_1.default.isActive() && (react_1.default.createElement(react_1.default.Suspense, { fallback: react_1.default.createElement("div", null,
                                react_1.default.createElement(LargeLoader_1.default, null)) },
                            react_1.default.createElement(AccountRouter, null)))) }),
                    GiftCardFeature_1.default.isActive() && GiftCardFeature_1.default.config && (react_1.default.createElement(react_router_dom_1.Route, { path: "gift-cards/purchase", element: react_1.default.createElement(react_1.default.Suspense, { fallback: react_1.default.createElement("div", null, "Loading...") },
                            react_1.default.createElement(gc_frontend_1.PurchaseGiftCardEngine, { companyId: GiftCardFeature_1.default.config.companyId, companyName: (_d = hotel === null || hotel === void 0 ? void 0 : hotel.name) !== null && _d !== void 0 ? _d : '', logoUrl: (_f = (_e = GiftCardFeature_1.default.config.logoUrl) !== null && _e !== void 0 ? _e : hotel === null || hotel === void 0 ? void 0 : hotel.logo.toString()) !== null && _f !== void 0 ? _f : '', homeUrl: (_g = hotel === null || hotel === void 0 ? void 0 : hotel.hotelUrl) !== null && _g !== void 0 ? _g : '', apiUrl: GIFT_CARD_API_URL, assetUrl: GIFT_CARD_ASSET_URL })) })),
                    react_1.default.createElement(react_router_dom_1.Route, { path: "*", element: react_1.default.createElement(react_router_dom_1.Navigate, { to: StepManager_1.default.getFirstStep().getStepUrl(), replace: true }) })))),
            react_1.default.createElement(RoomstayMark_1.RoomstayMark, null))));
}
//# sourceMappingURL=FullPageEngineContextWrapper.js.map