export const EASING_TYPES = {
    QUAD: 'quad',
    OUT_QUAD: 'out-quad',
    CUBIC: 'cubic',
    QUART: 'quart',
    QUINT: 'quint',
};
const traceBubblingByClass = (event, classNames) => {
    // composedPath() отсутствует в flow type Event,
    // однако он есть в действующей спецификации API EventDom https://developer.mozilla.org/en-US/docs/Web/API/Event/composedPath.
    // $FlowFixMe
    let path = (event.composedPath && event.composedPath()) || [];
    if (event.nativeEvent) {
        path = (event.nativeEvent.composedPath && event.nativeEvent.composedPath()) || [];
    }
    for (let i = 0; i < path.length; i += 1) {
        if (path[i].classList !== undefined) {
            let hasInclude;
            if (Array.isArray(classNames)) {
                hasInclude = classNames.reduce((acc, className) => acc || path[i].classList.contains(className), false);
            }
            else {
                hasInclude = path[i].classList.contains(classNames);
            }
            if (hasInclude) {
                return hasInclude;
            }
        }
        else
            break;
    }
    return false;
};
const findElementsByCondition = (nodeList, callBack) => Array.from(nodeList).reduce((acc, el) => {
    let newAcc = [];
    if (el.childNodes.length) {
        newAcc = findElementsByCondition(el.childNodes, callBack);
    }
    if (callBack(el)) {
        newAcc = [el, ...newAcc];
    }
    return [...newAcc, ...acc];
}, []);
const scrollTo = (target, duration, easingType) => {
    const start = Date.now(), to = target !== window ? target.getBoundingClientRect().top : window.pageYOffset, path = 0 - to;
    const currentPosition = window.pageYOffset;
    if (Math.floor(to) === path) {
        return;
    }
    const ease = (time, option) => {
        switch (option) {
            case EASING_TYPES.QUAD:
                return time * time;
            case EASING_TYPES.OUT_QUAD:
                return time * (2 - time);
            case EASING_TYPES.CUBIC:
                return time * time * time;
            case EASING_TYPES.QUART:
                return time * time * time * time;
            case EASING_TYPES.QUINT:
                return time * time * time * time * time;
            default:
                return time * time;
        }
    };
    const min = (a, b) => (a < b ? a : b);
    const scroll = () => {
        const currentTime = Date.now(), time = min(1, (currentTime - start) / duration), easedT = ease(time, easingType);
        if (target === window) {
            window.scroll({ top: to + easedT * (path - to) });
        }
        else {
            window.scroll({ top: currentPosition + easedT * to });
        }
        if (time < 1)
            window.requestAnimationFrame(scroll);
    };
    window.requestAnimationFrame(scroll);
};
const getParentNodes = (node, path) => {
    path = path || [];
    const parentNode = node.parentNode;
    if (!parentNode) {
        return path;
    }
    return getParentNodes(parentNode, path.concat(parentNode));
};
const getEventPath = (event) => {
    if (event.composedPath) {
        return event.composedPath();
    }
    return getParentNodes(event.target);
};
export { getEventPath, getParentNodes, scrollTo, findElementsByCondition, traceBubblingByClass };
