/**
 * Creates a debounce manager for the given function
 * Use case: a debounced function (eg. change handler) has to be synchronized in order to work with the most recent data
 * Note: invokeSync and sync can work with async/await (result forwarding)
 * @author boda@redhotmagma.de
 * @param {function} callbackFn
 * @param {number} delay The delay in ms
 */
export const createDebounceManager = (callbackFn, delay = 200) => {
    let lastChangeTimeout;
    let needsInvocation = false;
    let storedArgs = [];
    const invokeStored = () => {
        if (needsInvocation) {
            needsInvocation = false;
            return callbackFn(...storedArgs);
        }
    };
    return {
        /**
         * @param args
         * @return {*}
         */
        invokeSync: (...args) => {
            window.clearTimeout(lastChangeTimeout);
            needsInvocation = false;
            return callbackFn(...args);
        },
        /**
         * @param args
         */
        invokeDebounced: (...args) => {
            window.clearTimeout(lastChangeTimeout);
            needsInvocation = true;
            storedArgs = args;
            lastChangeTimeout = window.setTimeout(invokeStored, delay);
        },
        /**
         * @return {*}
         */
        sync: () => {
            window.clearTimeout(lastChangeTimeout);
            return invokeStored();
        },
    };
};
