import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { createContext, useState, useEffect, memo } from 'react';
import jwtDecode from 'jwt-decode';
import { SecurityContext } from './SecurityContext';
import { useAppContext, useIsMounted, useLocalStorage } from '../../hooks';
export const SecurityContextContext = createContext({
    payload: '',
    token: null,
    currentToken: null,
    isModalOpen: false,
});
let mutex = 0;
let refreshingToken = null;
export const SecurityContextProvider = memo(function SecurityContextProvider({ children, tokenUpdater, onTokenPayloadChange, }) {
    const isMounted = useIsMounted();
    const [savedToken, setToken, removeToken] = useLocalStorage('cubejsToken', null);
    const { token: appToken, setContext } = useAppContext();
    const [payload, setPayload] = useState('');
    const [isModalOpen, setIsModalOpen] = useState(false);
    const token = savedToken || appToken;
    async function refreshToken(removeSavedToken = false) {
        const tokenToRefresh = removeSavedToken ? appToken : token;
        if (tokenToRefresh != null &&
            tokenUpdater &&
            refreshingToken !== tokenToRefresh) {
            refreshingToken = tokenToRefresh;
            const currentMutex = mutex;
            const refreshedToken = await tokenUpdater(tokenToRefresh);
            if (isMounted() && currentMutex === mutex) {
                if (savedToken && removeSavedToken === false) {
                    setToken(refreshedToken);
                }
                else {
                    setContext({ token: refreshedToken });
                }
                refreshingToken = null;
                mutex++;
            }
        }
    }
    useEffect(() => {
        if (token) {
            try {
                const payload = jwtDecode(token);
                setPayload(JSON.stringify(payload, null, 2));
            }
            catch (error) {
                setPayload('');
                console.error('Invalid JWT token', token);
            }
        }
        else {
            setPayload('');
        }
    }, [token]);
    return (_jsxs(SecurityContextContext.Provider, { value: {
            token: savedToken,
            currentToken: token,
            payload,
            isModalOpen,
            setIsModalOpen,
            async saveToken(token) {
                if (!token) {
                    await refreshToken(true);
                    removeToken();
                }
                else {
                    setToken(token);
                }
            },
            refreshToken,
            onTokenPayloadChange,
        }, children: [children, _jsx(SecurityContext, {})] }));
});
//# sourceMappingURL=SecurityContextProvider.js.map