import { useMemo, useRef } from 'react';
import { useUnmountEffect } from './unmount-effect';
export function useDebouncedCallback(callback, deps, delay, maxWait = 0) {
    const timeout = useRef();
    const waitTimeout = useRef();
    const lastCall = useRef();
    const clear = () => {
        if (timeout.current) {
            clearTimeout(timeout.current);
            timeout.current = undefined;
        }
        if (waitTimeout.current) {
            clearTimeout(waitTimeout.current);
            waitTimeout.current = undefined;
        }
    };
    // cancel scheduled execution on unmount
    useUnmountEffect(clear);
    return useMemo(() => {
        const execute = () => {
            if (!lastCall.current) {
                return;
            }
            const context = lastCall.current;
            lastCall.current = undefined;
            context.resolve(callback.apply(context.this, context.args));
            clear();
        };
        const wrapped = function (...args) {
            return new Promise((resolve, reject) => {
                if (timeout.current) {
                    clearTimeout(timeout.current);
                }
                lastCall.current = { args, this: this, resolve };
                if (delay === 0) {
                    execute();
                    return;
                }
                // plan regular execution
                timeout.current = setTimeout(execute, delay);
                // plan maxWait execution if required
                if (maxWait > 0 && !waitTimeout.current) {
                    waitTimeout.current = setTimeout(execute, maxWait);
                }
            });
        };
        Object.defineProperties(wrapped, {
            length: { value: callback.length },
            name: { value: `${callback.name || 'anonymous'}__debounced__${delay}` },
        });
        return wrapped;
    }, [delay, maxWait, ...deps]);
}
//# sourceMappingURL=debounced-callback.js.map