import { useCallback, useEffect, useMemo } from "react";
import { of } from "rxjs";
import { catchError, distinctUntilChanged, map, tap } from "rxjs/operators";
import { useStored } from "../hooks/common";
import { useObservable } from "../hooks/rxjs";
import { createSimpleContext } from "./simple";
const isSession = (raw) => !!raw && Reflect.has(raw, "accountIndex");
const defaultSession = {
    accountIndex: 0,
};
const Context = createSimpleContext("session-rx", {
    data$: of(defaultSession),
    set() {
        throw new Error("not implemented; make sure you have session context provider enabled");
    },
    remove() {
        throw new Error("not implemented; make sure you have session context provider enabled");
    },
}, ({ sessionKey = "APP-SESSION" }) => {
    const { data: sessionStored, set: setSession, remove: removeSession, } = useStored(sessionKey, globalThis.localStorage);
    const raw$ = useObservable(sessionStored);
    const session$ = useMemo(() => raw$.pipe(distinctUntilChanged(), map((val) => {
        if (!val) {
            return defaultSession;
        }
        const obj = JSON.parse(val);
        if (!isSession(obj)) {
            throw new Error("wrong session format");
        }
        return obj;
    }), catchError((e) => {
        if (e instanceof Error) {
            console.error(e.message);
        }
        return of(defaultSession);
    })), [raw$]);
    const set = useCallback((key, value) => {
        let sub;
        sub = session$.subscribe((val) => {
            setSession(JSON.stringify({ ...val, [key]: value }));
            sub?.unsubscribe();
        });
    }, [session$, setSession]);
    const remove = useCallback(() => {
        let sub;
        sub = session$.subscribe(() => {
            removeSession();
            sub?.unsubscribe();
        });
    }, [session$, removeSession]);
    const _debug$ = useMemo(() => session$.pipe(tap(() => {
        Object.assign(window, {
            __debugSessionSet(...args) {
                set(...args);
            },
        });
    })), [session$, set]);
    // TODO moveout to an rx/hook
    useEffect(() => {
        // naming a/la useTap(observeble$) mb inject
        const sub = _debug$.subscribe();
        return () => sub.unsubscribe();
    }, [_debug$]);
    return { data$: session$, set, remove };
});
export const useSession = Context.useContext;
export const SessionProvider = Context.Provider;
//# sourceMappingURL=session.js.map