import { useCallback, useEffect, useMemo, useRef, } from 'react';
import { unstable_IdlePriority as IdlePriority, unstable_scheduleCallback as scheduleCallback, } from 'scheduler';
import identity from '../../utils/identity';
import { ValidateOption } from './validate';
import { last } from './utils';
export function multi() {
    var funcs = [];
    for (var _i = 0; _i < arguments.length; _i++) {
        funcs[_i] = arguments[_i];
    }
    return function (t) {
        funcs.forEach(function (func) { return func(t); });
    };
}
export function useMulti() {
    var funcs = [];
    for (var _i = 0; _i < arguments.length; _i++) {
        funcs[_i] = arguments[_i];
    }
    var deps;
    if (Array.isArray(last(funcs))) {
        deps = funcs.pop();
    }
    else {
        deps = funcs;
    }
    return useCallback(multi.apply(void 0, funcs), deps);
}
export function compose() {
    var middlewares = [];
    for (var _i = 0; _i < arguments.length; _i++) {
        middlewares[_i] = arguments[_i];
    }
    return function (target) {
        return middlewares.reduceRight(function (currentTarget, middleware) { return middleware(currentTarget); }, target);
    };
}
export function useMAppend() {
    var fns = [];
    for (var _i = 0; _i < arguments.length; _i++) {
        fns[_i] = arguments[_i];
    }
    return useCallback(function (value) {
        for (var i = 0; i < fns.length; i += 1) {
            var f = fns[i];
            f(value);
        }
    }, fns);
}
export function usePipe() {
    var args = [];
    for (var _i = 0; _i < arguments.length; _i++) {
        args[_i] = arguments[_i];
    }
    var l = last(args);
    var deps;
    if (Array.isArray(l)) {
        args.pop();
        deps = l;
    }
    else {
        deps = args;
    }
    return useMemo(function () {
        var fn = args.reduceRight(function (next, f) { return function (arg) { return next(f(arg)); }; }, identity);
        return function (t) { return fn(t); };
    }, deps);
}
export function useChangeHandler(model, option, callback) {
    if (option === void 0) { option = ValidateOption.Default | ValidateOption.ExcludePristine; }
    var taskRef = useRef(null);
    var ref = useRef({
        option: option,
        callback: callback,
    });
    useEffect(function () {
        ref.current = {
            option: option,
            callback: callback,
        };
    }, [option, callback]);
    return useCallback(function (value) {
        var _a, _b;
        model.value = value;
        (_b = (_a = ref.current).callback) === null || _b === void 0 ? void 0 : _b.call(_a, value);
        if (model.isCompositing) {
            return;
        }
        if (!taskRef.current) {
            taskRef.current = scheduleCallback(IdlePriority, function () {
                taskRef.current = null;
                model.validate(ref.current.option);
            });
        }
    }, [model]);
}
export var makeChangeHandler = useChangeHandler;
export function useCompositionHandler(model, callbacks) {
    var ref = useRef(callbacks);
    useEffect(function () {
        ref.current = callbacks;
    });
    return useMemo(function () { return ({
        onCompositionStart: function (e) {
            var _a, _b;
            model.isCompositing = true;
            (_b = (_a = ref.current) === null || _a === void 0 ? void 0 : _a.onCompositionStart) === null || _b === void 0 ? void 0 : _b.call(_a, e);
        },
        onCompositionEnd: function (e) {
            var _a, _b;
            model.isCompositing = false;
            (_b = (_a = ref.current) === null || _a === void 0 ? void 0 : _a.onCompositionEnd) === null || _b === void 0 ? void 0 : _b.call(_a, e);
        },
    }); }, [model]);
}
