"use strict";
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 });
exports.usePromotionContainer = exports.removePromotion = exports.registerPromotion = void 0;
const contexts_1 = require("../contexts/index.js");
const dayjs_1 = __importDefault(require("dayjs"));
const react_1 = require("react");
const MemberOnlyFenceSignUp_1 = require("../events/actions/MemberOnlyFence/MemberOnlyFenceSignUp");
const PromotionAddedEvent_1 = require("../events/actions/Promotion/PromotionAddedEvent");
const PromotionClickedEvent_1 = require("../events/actions/Promotion/PromotionClickedEvent");
const PromotionRemovedEvent_1 = require("../events/actions/Promotion/PromotionRemovedEvent");
const RoomstayEventManager_1 = __importDefault(require("../events/RoomstayEventManager"));
const EventHook_1 = require("../hooks/EventHook");
const _loadedPromotions = [];
let basketContextLoaded = false;
const registerPromotion = (promotion) => {
    if (basketContextLoaded) {
        RoomstayEventManager_1.default.raise(new PromotionAddedEvent_1.PromotionAddEvent(promotion));
    }
    else {
        const promoIndex = getPromoIndex(promotion.name, _loadedPromotions);
        if (promoIndex === -1) {
            _loadedPromotions.push(promotion);
        }
        else {
            _loadedPromotions[promoIndex] = promotion;
        }
    }
};
exports.registerPromotion = registerPromotion;
const removePromotion = (promotion) => {
    if (basketContextLoaded) {
        RoomstayEventManager_1.default.raise(new PromotionRemovedEvent_1.PromotionRemoveEvent(promotion));
    }
    else {
        const promoIndex = getPromoIndex(promotion.name, _loadedPromotions);
        if (promoIndex !== -1) {
            _loadedPromotions.splice(promoIndex, 1);
        }
    }
};
exports.removePromotion = removePromotion;
const getPromoIndex = (name, promoList) => {
    for (let i = 0; i < promoList.length; i++) {
        if (promoList[i].name === name) {
            return i;
        }
    }
    return -1;
};
/**
 * Used by the Basket context to bind to state.
 */
const usePromotionContainer = ({ selectedBasketRow, updateBasketRow }) => {
    const ccx = (0, react_1.useContext)(contexts_1.CompanyContext);
    const [bump, setBump] = (0, react_1.useState)(0);
    const [allPromotions, setAllPromotions] = (0, react_1.useState)(_loadedPromotions !== null && _loadedPromotions !== void 0 ? _loadedPromotions : []);
    // TODO: Current implementation only supports a single promotion. In the future there will be multiple promotion locations
    const [loadedPromotion, setLoadedPromotion] = (0, react_1.useState)(null);
    const { on } = (0, EventHook_1.useEvent)();
    (0, react_1.useEffect)(() => {
        basketContextLoaded = true;
        const updateBasketRowContext = (promotion) => {
            if (!promotion) {
                // We don't care about non promo sign ups;
                return;
            }
            if (selectedBasketRow) {
                const criteria = {
                    checkInDate: selectedBasketRow.getStartDate(),
                    checkOutDate: selectedBasketRow.getEndDate(),
                    adults: selectedBasketRow.getAdults(),
                    children: selectedBasketRow.getChildren(),
                    infants: selectedBasketRow.getInfants(),
                    promoCode: selectedBasketRow.getPromoCode(),
                };
                const { checkInDate, checkOutDate, adults, children, infants, promoCode } = promotion.onApply(criteria);
                if (checkInDate) {
                    selectedBasketRow.setStartDate((0, dayjs_1.default)(checkInDate));
                }
                if (checkOutDate) {
                    selectedBasketRow.setEndDate((0, dayjs_1.default)(checkOutDate));
                }
                if (adults) {
                    selectedBasketRow.setAdults(adults);
                }
                if (children) {
                    selectedBasketRow.setChildren(children);
                }
                if (infants) {
                    selectedBasketRow.setInfants(infants);
                }
                if (promoCode) {
                    selectedBasketRow.setPromoCode(promoCode);
                }
                updateBasketRow(selectedBasketRow);
            }
        };
        on(PromotionAddedEvent_1.PromotionAddEvent, (event) => __awaiter(void 0, void 0, void 0, function* () {
            if (event === null || event === void 0 ? void 0 : event.promotion) {
                setAllPromotions((oldPromotions) => {
                    const promoIndex = getPromoIndex(event.promotion.name, oldPromotions);
                    if (promoIndex === -1) {
                        return [...oldPromotions, event.promotion];
                    }
                    else {
                        oldPromotions[promoIndex] = event.promotion;
                        return oldPromotions;
                    }
                });
            }
        }), 'root');
        on(PromotionRemovedEvent_1.PromotionRemoveEvent, (event) => __awaiter(void 0, void 0, void 0, function* () {
            if (event === null || event === void 0 ? void 0 : event.promotion) {
                setAllPromotions((oldPromotions) => {
                    if (oldPromotions.length === 0) {
                        return [];
                    }
                    return oldPromotions.filter((promo) => {
                        if (promo.name !== event.promotion.name) {
                            return promo;
                        }
                        return false;
                    });
                });
                setBump((a) => a + 1);
            }
        }), 'root');
        on(PromotionClickedEvent_1.PromotionClickedEvent, (event) => __awaiter(void 0, void 0, void 0, function* () {
            const { promotion } = event;
            if (!promotion) {
                // We shouldn't be here, but just in case we are...
                return;
            }
            if (!ccx.signedInUser && promotion.requireMemberPromotion) {
                // ccx.openMemberSignupModal(promotion);
            }
            else {
                updateBasketRowContext(promotion);
            }
        }), 'root');
        on(MemberOnlyFenceSignUp_1.MemberOnlyFenceSignUp, (event) => __awaiter(void 0, void 0, void 0, function* () {
            updateBasketRowContext(event.promotion);
        }), 'root');
    }, [ccx.signedInUser, selectedBasketRow, allPromotions, setAllPromotions, loadedPromotion, setLoadedPromotion]);
    (0, react_1.useEffect)(() => {
        if (selectedBasketRow) {
            const criteria = {
                checkInDate: selectedBasketRow.getStartDate(),
                checkOutDate: selectedBasketRow.getEndDate(),
                adults: selectedBasketRow.getAdults(),
                children: selectedBasketRow.getChildren(),
                infants: selectedBasketRow.getInfants(),
                promoCode: selectedBasketRow.getPromoCode(),
            };
            onPromotionCriteriaChanged(criteria);
        }
    }, [
        selectedBasketRow,
        selectedBasketRow === null || selectedBasketRow === void 0 ? void 0 : selectedBasketRow.getAdults(),
        selectedBasketRow === null || selectedBasketRow === void 0 ? void 0 : selectedBasketRow.getChildren(),
        selectedBasketRow === null || selectedBasketRow === void 0 ? void 0 : selectedBasketRow.getInfants(),
        selectedBasketRow === null || selectedBasketRow === void 0 ? void 0 : selectedBasketRow.getArrivalDate(),
        selectedBasketRow === null || selectedBasketRow === void 0 ? void 0 : selectedBasketRow.getEndDate(),
        selectedBasketRow === null || selectedBasketRow === void 0 ? void 0 : selectedBasketRow.getPromoCode(),
        allPromotions,
        bump,
    ]);
    (0, react_1.useEffect)(() => {
        if (!loadedPromotion) {
            return;
        }
        let loadedExists = false;
        for (const promotion of allPromotions) {
            if (promotion.name === loadedPromotion.name) {
                loadedExists = true;
                break;
            }
        }
        if (!loadedExists) {
            setLoadedPromotion(null);
        }
    }, [allPromotions, loadedPromotion]);
    /**
     * Checks all the registered promotions, and returns the first one that matches the criteria.
     *
     * @param criteria
     */
    const checkPromotions = (criteria) => __awaiter(void 0, void 0, void 0, function* () {
        for (const promotion of allPromotions) {
            if (yield promotion.testCriteria(criteria)) {
                return promotion;
            }
        }
        return null;
    });
    const onPromotionCriteriaChanged = (criteria) => {
        checkPromotions(criteria)
            .then((promo) => {
            setLoadedPromotion(promo);
        })
            .catch(() => {
            setLoadedPromotion(null);
        });
    };
    return {
        loadedPromotion,
    };
};
exports.usePromotionContainer = usePromotionContainer;
//# sourceMappingURL=PromotionProvider.js.map