"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 __rest = (this && this.__rest) || function (s, e) {
    var t = {};
    for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
        t[p] = s[p];
    if (s != null && typeof Object.getOwnPropertySymbols === "function")
        for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
            if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
                t[p[i]] = s[p[i]];
        }
    return t;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.RoomstayMemberContextProvider = void 0;
const contexts_1 = require("../../index.js");
const dayjs_1 = __importDefault(require("dayjs"));
const react_1 = __importStar(require("react"));
const MembersServiceAPI_1 = require("../../../api/members-service/MembersServiceAPI");
const EventsHelper_1 = require("../../../util/EventsHelper");
const ROOMSTAY_MEMBER_CACHE_TIME = 60 * 60; // 1 hour
const ROOMSTAY_MEMBER_CACHE_KEY = 'roomstay-member';
const getCachedRoomstayMember = () => {
    const roomstayMember = localStorage.getItem(ROOMSTAY_MEMBER_CACHE_KEY);
    if (roomstayMember) {
        const parsedRoomstayMember = JSON.parse(roomstayMember);
        if (parsedRoomstayMember.timestamp && (0, dayjs_1.default)().unix() - parsedRoomstayMember.timestamp < ROOMSTAY_MEMBER_CACHE_TIME) {
            return parsedRoomstayMember.data;
        }
        localStorage.removeItem(ROOMSTAY_MEMBER_CACHE_KEY);
    }
    return undefined;
};
const cacheRoomstayMember = (member) => {
    if (member) {
        localStorage.setItem(ROOMSTAY_MEMBER_CACHE_KEY, JSON.stringify({
            data: member,
            timestamp: (0, dayjs_1.default)().unix(),
        }));
    }
    else {
        localStorage.removeItem(ROOMSTAY_MEMBER_CACHE_KEY);
    }
};
const useRoomstayMemberContext = () => {
    const { loading: acLoading, cognitoUser } = (0, react_1.useContext)(contexts_1.AuthenticationContext);
    const { signUserIn, signUserOut } = (0, react_1.useContext)(contexts_1.CompanyContext);
    const { hasCheckedOut } = (0, react_1.useContext)(contexts_1.BasketContext);
    const [isFetching, isFetchingSet] = (0, react_1.useState)(true);
    const [roomstayMember, roomstayMemberSet] = (0, react_1.useState)();
    const [cards, cardsSet] = (0, react_1.useState)([]);
    const [allBookings, setAllBookings] = (0, react_1.useState)([]);
    const [allItineraries, setAllItineraries] = (0, react_1.useState)([]);
    const [cancelledBookings, setCancelledBookings] = (0, react_1.useState)([]);
    const [pastBookings, setPastBookings] = (0, react_1.useState)([]);
    const [upcomingBookings, setUpcomingBookings] = (0, react_1.useState)([]);
    const updateRoomstayMember = (member) => {
        roomstayMemberSet(member);
        cacheRoomstayMember(member);
    };
    (0, react_1.useEffect)(() => {
        isFetchingSet(true);
        try {
            const roomstayMember = getCachedRoomstayMember();
            if (roomstayMember) {
                roomstayMemberSet(roomstayMember);
            }
        }
        finally {
            isFetchingSet(false);
        }
    }, []);
    (0, react_1.useEffect)(() => {
        if (roomstayMember) {
            setAllBookings(roomstayMember.bookings);
            signUserIn({
                saveState: false,
                memberNumber: roomstayMember.email,
                firstName: roomstayMember.forename,
                lastName: roomstayMember.surname,
                email: roomstayMember.email,
            });
        }
        else {
            signUserOut();
            setAllBookings([]);
        }
    }, [roomstayMember]);
    (0, react_1.useEffect)(() => {
        const itineraries = [];
        for (const booking of allBookings !== null && allBookings !== void 0 ? allBookings : []) {
            const itineraryKeys = Object.keys(booking.itinerary);
            for (const key of itineraryKeys) {
                const bookingItem = Object.assign(Object.assign({}, booking.itinerary[key]), { bookingId: booking.itineraryId, hotel: booking.hotel, hotelId: booking.hotelId });
                itineraries.push(bookingItem);
            }
        }
        itineraries.sort((a, b) => {
            return (0, dayjs_1.default)(b.checkInDate).diff((0, dayjs_1.default)(a.checkInDate));
        });
        setAllItineraries(itineraries);
    }, [allBookings]);
    (0, react_1.useEffect)(() => {
        const bookingBrackets = {
            past: [],
            upcoming: [],
            cancelled: [],
        };
        const sortedAllItineraries = allItineraries.sort(({ checkInDate: aCheckInDateString, checkOutDate: aCheckOutDateString }, { checkInDate: bCheckInDateString, checkOutDate: bCheckOutDateString }) => {
            const aCheckInDate = (0, dayjs_1.default)(aCheckInDateString);
            const bCheckInDate = (0, dayjs_1.default)(bCheckInDateString);
            if (aCheckInDate.isSame(bCheckInDate)) {
                const aCheckOutDate = (0, dayjs_1.default)(aCheckOutDateString);
                const bCheckOutDate = (0, dayjs_1.default)(bCheckOutDateString);
                if (aCheckOutDate.isSame(bCheckOutDate))
                    return 0;
                else if (aCheckOutDate.isBefore(bCheckOutDate))
                    return -1;
                else
                    return 1;
            }
            else if (aCheckInDate.isBefore(bCheckInDate))
                return -1;
            else
                return 1;
        });
        for (const booking of sortedAllItineraries) {
            if ((0, EventsHelper_1.isCancelledBooking)(booking)) {
                bookingBrackets.cancelled.push(booking);
            }
            else if ((0, EventsHelper_1.isPastBooking)(booking)) {
                bookingBrackets.past.push(booking);
            }
            else {
                bookingBrackets.upcoming.push(booking);
            }
        }
        setCancelledBookings(bookingBrackets.cancelled);
        setUpcomingBookings(bookingBrackets.upcoming);
        setPastBookings(bookingBrackets.past);
    }, [allItineraries]);
    const loading = (0, react_1.useMemo)(() => isFetching || acLoading, [isFetching, acLoading]);
    const fetchRoomstayMember = (0, react_1.useCallback)(() => __awaiter(void 0, void 0, void 0, function* () {
        var _a;
        if (cognitoUser) {
            isFetchingSet(true);
            try {
                const member = yield (0, MembersServiceAPI_1.GetMemberDetails)();
                updateRoomstayMember(member);
                cardsSet((_a = member.cards) !== null && _a !== void 0 ? _a : []);
            }
            catch (e) {
                // TODO deal with members that we haven't been able to fetch
                console.log(e);
            }
            isFetchingSet(false);
        }
        else {
            updateRoomstayMember(undefined);
            cardsSet([]);
        }
    }), [cognitoUser]);
    (0, react_1.useEffect)(() => {
        fetchRoomstayMember();
    }, [fetchRoomstayMember]);
    (0, react_1.useEffect)(() => {
        if (hasCheckedOut) {
            fetchRoomstayMember();
        }
    }, [hasCheckedOut]);
    const updateCardToMemberDetail = (card) => {
        const index = roomstayMember === null || roomstayMember === void 0 ? void 0 : roomstayMember.cards.findIndex((item) => item.cardId === card.cardId);
        if (index && (roomstayMember === null || roomstayMember === void 0 ? void 0 : roomstayMember.cards[index])) {
            if (index !== -1) {
                roomstayMember.cards[index] = card;
            }
            else {
                roomstayMember.cards.push(card);
            }
        }
        if (roomstayMember === null || roomstayMember === void 0 ? void 0 : roomstayMember.cards)
            cardsSet([...roomstayMember.cards]);
        updateRoomstayMember(roomstayMember);
    };
    const updateMemberDetails = (newMemberDetails) => __awaiter(void 0, void 0, void 0, function* () {
        const memberDetailsToSubmit = __rest(newMemberDetails, []);
        isFetchingSet(true);
        try {
            const updatedMember = yield (0, MembersServiceAPI_1.UpdateMemberDetails)(memberDetailsToSubmit);
            if (updatedMember && updatedMember.username) {
                updateRoomstayMember(updatedMember);
            }
            if (updatedMember === null || updatedMember === void 0 ? void 0 : updatedMember.cards)
                cardsSet([...updatedMember.cards]);
        }
        catch (e) {
            // TODO
        }
        isFetchingSet(false);
    });
    return {
        loading,
        roomstayMember,
        cards,
        allBookings,
        allItineraries,
        upcomingBookings,
        pastBookings,
        cancelledBookings,
        updateCardToMemberDetail,
        updateMemberDetails,
        fetchRoomstayMember,
        isFetchingMember: isFetching,
    };
};
const RoomstayMemberContextProvider = ({ children }) => {
    return react_1.default.createElement(contexts_1.RoomstayMemberContext.Provider, { value: useRoomstayMemberContext() }, children);
};
exports.RoomstayMemberContextProvider = RoomstayMemberContextProvider;
//# sourceMappingURL=RoomstayMemberContextProvider.js.map