import { useEffect, useMemo, useRef } from 'react';
import { useUnmountEffect } from '../useUnmountEffect/index.js';
export function useDebouncedCallback(callback, deps, delay, maxWait = 0) {
    const timeout = useRef();
    const waitTimeout = useRef();
    const cb = useRef(callback);
    const lastCall = useRef();
    const clear = () => {
        if (timeout.current) {
            clearTimeout(timeout.current);
            timeout.current = undefined;
        }
        if (waitTimeout.current) {
            clearTimeout(waitTimeout.current);
            waitTimeout.current = undefined;
        }
    };
    useUnmountEffect(clear);
    useEffect(() => {
        cb.current = callback;
    }, deps);
    return useMemo(() => {
        const execute = () => {
            clear();
            if (!lastCall.current)
                return;
            const context = lastCall.current;
            lastCall.current = undefined;
            cb.current.apply(context.this, context.args);
        };
        const wrapped = function (...args) {
            if (timeout.current) {
                clearTimeout(timeout.current);
            }
            lastCall.current = { args, this: this };
            timeout.current = setTimeout(execute, delay);
            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]);
}
