'use client';
import { jsxDEV as _jsxDEV } from "react/jsx-dev-runtime";
import { dequal } from 'dequal/lite';
// lite: no need for Map and Set support
import { formatAdminURL } from 'payload/shared';
import React, { createContext, use, useCallback, useEffect, useRef } from 'react';
import { useTranslation } from '../../providers/Translation/index.js';
import { requests } from '../../utilities/api.js';
import { deepMergeSimple } from '../../utilities/deepMerge.js';
import { useAuth } from '../Auth/index.js';
import { useConfig } from '../Config/index.js';
/**
   * @param key - a string identifier for the property being set
   * @param value - preference data to store
   * @param merge - when true will combine the existing preference object batch the change into one request for objects, default = false
   */ const Context = /*#__PURE__*/ createContext({});
const requestOptions = (value, language)=>({
        body: JSON.stringify({
            value
        }),
        headers: {
            'Accept-Language': language,
            'Content-Type': 'application/json'
        }
    });
export const PreferencesProvider = ({ children })=>{
    const contextRef = useRef({});
    const preferencesRef = useRef({});
    const pendingUpdate = useRef({});
    const { config } = useConfig();
    const { user } = useAuth();
    const { i18n } = useTranslation();
    const { routes: { api } } = config;
    useEffect(()=>{
        if (!user) {
            // clear preferences between users
            preferencesRef.current = {};
        }
    }, [
        user
    ]);
    const getPreference = useCallback(async (key)=>{
        const prefs = preferencesRef.current;
        if (typeof prefs[key] !== 'undefined') {
            return prefs[key];
        }
        const promise = new Promise((resolve)=>{
            void (async ()=>{
                const request = await requests.get(formatAdminURL({
                    apiRoute: api,
                    path: `/payload-preferences/${key}`
                }), {
                    credentials: 'include',
                    headers: {
                        'Accept-Language': i18n.language
                    }
                });
                let value = null;
                if (request.status === 200) {
                    const preference = await request.json();
                    value = preference.value;
                }
                preferencesRef.current[key] = value;
                resolve(value);
            })();
        });
        prefs[key] = promise;
        return promise;
    }, [
        i18n.language,
        api,
        preferencesRef
    ]);
    const setPreference = useCallback(async (key, value, merge = false)=>{
        if (merge === false) {
            preferencesRef.current[key] = value;
            await requests.post(formatAdminURL({
                apiRoute: api,
                path: `/payload-preferences/${key}`
            }), requestOptions(value, i18n.language));
            return;
        }
        let newValue = value;
        const currentPreference = await getPreference(key);
        // handle value objects where multiple values can be set under one key
        if (typeof value === 'object' && typeof currentPreference === 'object' && typeof newValue === 'object') {
            // merge the value with any existing preference for the key
            if (currentPreference) {
                newValue = deepMergeSimple(currentPreference, newValue);
            }
            if (dequal(newValue, currentPreference)) {
                return;
            }
            // add the requested changes to a pendingUpdate batch for the key
            pendingUpdate.current[key] = {
                ...pendingUpdate.current[key],
                ...newValue
            };
        } else {
            if (newValue === currentPreference) {
                return;
            }
            pendingUpdate.current[key] = newValue;
        }
        const updatePreference = async ()=>{
            // compare the value stored in context before sending to eliminate duplicate requests
            if (dequal(pendingUpdate.current[key], preferencesRef.current[key])) {
                return;
            }
            // preference set in context here to prevent other updatePreference at the same time
            preferencesRef.current[key] = pendingUpdate.current[key];
            await requests.post(formatAdminURL({
                apiRoute: api,
                path: `/payload-preferences/${key}`
            }), requestOptions(preferencesRef.current[key], i18n.language));
            // reset any changes for this key after sending the request
            delete pendingUpdate.current[key];
        };
        // use timeout to allow multiple changes of different values using the same key in one request
        setTimeout(()=>{
            void updatePreference();
        });
    }, [
        api,
        getPreference,
        i18n.language,
        pendingUpdate
    ]);
    contextRef.current.getPreference = getPreference;
    contextRef.current.setPreference = setPreference;
    return /*#__PURE__*/ _jsxDEV(Context, {
        value: contextRef.current,
        children: children
    }, void 0, false, {
        fileName: "src/providers/Preferences/index.tsx",
        lineNumber: 174,
        columnNumber: 10
    }, this);
};
export const usePreferences = ()=>use(Context);

//# sourceMappingURL=index.js.map