import { easingMap, timingMap, } from '../constants';
export const getPercentageValue = (percentage) => {
    const percentRegex = /^((100)|(\d{1,2}(\.\d*)?))%$/g;
    if (percentage.match(percentRegex)) {
        const percentNumber = Number(percentage.split('%')[0]);
        if (Number.isFinite(percentNumber)) {
            return percentNumber / 100;
        }
    }
    return 0;
};
const getFadeProps = (fade) => {
    if (fade === true) {
        return {
            duration: 'medium01',
        };
    }
    return fade;
};
const getMoveProps = (move) => {
    if (move === true) {
        return {
            duration: 'medium01',
            direction: 'bottomToTop',
            distance: '10px',
        };
    }
    return move;
};
const getToggleProps = (toggle) => {
    if (toggle === true) {
        return {
            duration: 'medium01',
            direction: 'bottomToTop',
        };
    }
    return toggle;
};
const getScaleProps = (scale, isExiting) => {
    if (scale === true) {
        return {
            duration: 'medium01',
            direction: 'center',
            scale: isExiting ? '0' : '1',
        };
    }
    return { ...scale, scale: `${getPercentageValue(scale.scale)}` };
};
const getDefaultStyles = (props) => {
    const easing = props.easing
        ? {
            transitionTimingFunction: easingMap[props.easing],
        }
        : undefined;
    const delay = props.delay
        ? {
            transitionDelay: `${timingMap[props.delay]}ms`,
        }
        : undefined;
    return {
        ...easing,
        ...delay,
    };
};
const getFadeStyles = (fadeProps, isExiting) => {
    const { duration } = fadeProps;
    const defaultStyles = getDefaultStyles(fadeProps);
    return {
        [isExiting ? 'exiting' : 'entering']: {
            opacity: 0,
            transitionProperty: 'opacity',
            transitionDuration: `${timingMap[duration]}ms`,
            ...(isExiting ? defaultStyles : {}),
        },
        [isExiting ? 'exited' : 'entered']: {
            opacity: 1,
            transitionProperty: 'opacity',
            transitionDuration: `${timingMap[duration]}ms`,
            ...(!isExiting ? defaultStyles : {}),
        },
    };
};
export const getMoveStyles = (moveProps, isExiting) => {
    const { direction, distance, duration } = moveProps;
    const defaultStyles = getDefaultStyles(moveProps);
    let transform = '';
    switch (direction) {
        case 'topToBottom':
            transform = `translateY(${isExiting ? distance : `-${distance}`})`;
            break;
        case 'bottomToTop':
            transform = `translateY(${isExiting ? `-${distance}` : distance})`;
            break;
        case 'leftToRight':
            transform = `translateX(${isExiting ? distance : `-${distance}`})`;
            break;
        case 'rightToLeft':
            transform = `translateX(${isExiting ? `-${distance}` : distance})`;
            break;
        default:
            throw new Error('unsupported direction');
    }
    return {
        [isExiting ? 'exiting' : 'entering']: {
            transform,
            transitionProperty: 'transform',
            transitionDuration: `${timingMap[duration]}ms`,
            ...(isExiting ? defaultStyles : {}),
        },
        [isExiting ? 'exited' : 'entered']: {
            transform: 'none',
            transitionProperty: 'transform',
            transitionDuration: `${timingMap[duration]}ms`,
            ...(!isExiting ? defaultStyles : {}),
        },
    };
};
const isDirectionVertical = (direction) => {
    return direction === 'bottomToTop' || direction === 'topToBottom';
};
const getToggleStyles = (toggleProps, isExiting, height, width, oppositeProps) => {
    const { direction, duration } = toggleProps;
    const defaultStyles = getDefaultStyles(toggleProps);
    const isVertical = isDirectionVertical(direction);
    const transitionOrigin = isVertical ? 'bottom' : 'left';
    const isOppositeVertical = oppositeProps?.direction && isDirectionVertical(oppositeProps?.direction);
    const isOppositeOnAnotherAxis = isOppositeVertical !== undefined && isOppositeVertical !== isVertical;
    const transitionOriginOutValue = oppositeProps?.direction === 'bottomToTop' ||
        oppositeProps?.direction === 'leftToRight'
        ? '-100%'
        : '100%';
    const oppositeTransitionOrigin = isOppositeVertical ? 'bottom' : 'left';
    let transitionOriginIn = '';
    switch (direction) {
        case 'topToBottom':
        case 'rightToLeft':
            transitionOriginIn = isExiting ? '-100%' : '100%';
            break;
        case 'bottomToTop':
        case 'leftToRight':
            transitionOriginIn = isExiting ? '100%' : '-100%';
            break;
        default:
            throw new Error('unsupported direction');
    }
    const commonStyles = {
        height: isVertical ? `${height}px` : '100%',
        width: isVertical ? '100%' : `${width}px`,
        position: 'relative',
        overflow: 'hidden',
        transitionProperty: 'bottom, left',
        transitionDuration: `${timingMap[duration]}ms`,
    };
    const styles = {
        in: {
            ...commonStyles,
            [transitionOrigin]: transitionOriginIn,
            ...(isExiting ? defaultStyles : {}),
        },
        out: {
            ...commonStyles,
            [transitionOrigin]: oppositeProps?.direction === direction ||
                isOppositeVertical === isVertical
                ? transitionOriginOutValue
                : '0%',
            ...(isOppositeOnAnotherAxis
                ? {
                    [oppositeTransitionOrigin]: transitionOriginOutValue,
                }
                : {}),
            ...(!isExiting ? defaultStyles : {}),
        },
    };
    if (isExiting) {
        return {
            entered: {
                ...commonStyles,
                [transitionOrigin]: '0%',
                ...(isOppositeOnAnotherAxis
                    ? {
                        [oppositeTransitionOrigin]: '0%',
                    }
                    : {}),
                ...defaultStyles,
            },
            exiting: styles.in,
            exited: styles.out,
        };
    }
    return {
        entering: styles.in,
        entered: styles.out,
    };
};
const getScaleStyles = (scaleProps, isExiting) => {
    const { direction, scale, duration } = scaleProps;
    const defaultStyles = getDefaultStyles(scaleProps);
    let transformOrigin = '';
    switch (direction) {
        case 'bottom':
            transformOrigin = '50% 100%';
            break;
        case 'bottomEnd':
            transformOrigin = '100% 100%';
            break;
        case 'bottomStart':
            transformOrigin = '0% 100%';
            break;
        case 'center':
            transformOrigin = '50% 50%';
            break;
        case 'left':
            transformOrigin = '0% 50%';
            break;
        case 'right':
            transformOrigin = '100% 50%';
            break;
        case 'top':
            transformOrigin = '50% 0%';
            break;
        case 'topEnd':
            transformOrigin = '100% 0%';
            break;
        case 'topStart':
            transformOrigin = '0% 0%';
            break;
        default:
            throw new Error('unsupported direction');
    }
    return {
        [isExiting ? 'exiting' : 'entering']: {
            transform: 'scale(0, 0)',
            transitionProperty: 'transform',
            transitionDuration: `${timingMap[duration]}ms`,
            transformOrigin,
            ...(isExiting ? defaultStyles : {}),
        },
        [isExiting ? 'exited' : 'entered']: {
            transform: `scale(${scale}, ${scale})`,
            transitionProperty: 'transform',
            transitionDuration: `${timingMap[duration]}ms`,
            transformOrigin,
            ...(!isExiting ? defaultStyles : {}),
        },
    };
};
const getToggleWrapperStyles = (expandProps, collapseProps, height, width) => {
    if (expandProps?.direction === 'topToBottom' &&
        collapseProps?.direction === 'bottomToTop') {
        return {};
    }
    const commonStyles = { overflow: 'hidden', height, width };
    return {
        entering: commonStyles,
        entered: commonStyles,
        exiting: commonStyles,
        exited: commonStyles,
    };
};
const getMergedStyles = (target, source) => {
    return {
        entering: {
            ...target.entering,
            ...source.entering,
        },
        entered: {
            ...target.entered,
            ...source.entered,
        },
        exiting: {
            ...target.exiting,
            ...source.exiting,
        },
        exited: {
            ...target.exited,
            ...source.exited,
        },
    };
};
export const getTransitionStyles = ({ width, height }, enterAnimation, exitAnimation) => {
    const transitionStyles = {
        fade: {},
        move: {},
        scale: {},
        toggle: {},
    };
    if (enterAnimation?.fadeIn) {
        const props = getFadeProps(enterAnimation?.fadeIn);
        const styles = getFadeStyles(props, false);
        Object.assign(transitionStyles.fade, styles);
    }
    if (exitAnimation?.fadeOut) {
        const props = getFadeProps(exitAnimation?.fadeOut);
        const styles = getFadeStyles(props, true);
        Object.assign(transitionStyles.fade, styles);
    }
    if (enterAnimation?.moveIn) {
        const props = getMoveProps(enterAnimation?.moveIn);
        const styles = getMoveStyles(props, false);
        Object.assign(transitionStyles.move, styles);
    }
    if (exitAnimation?.moveOut) {
        const props = getMoveProps(exitAnimation?.moveOut);
        const styles = getMoveStyles(props, true);
        Object.assign(transitionStyles.move, styles);
    }
    const expandProps = enterAnimation?.expand
        ? getToggleProps(enterAnimation?.expand)
        : undefined;
    const collapseProps = exitAnimation?.collapse
        ? getToggleProps(exitAnimation?.collapse)
        : undefined;
    if (expandProps) {
        const styles = getToggleStyles(expandProps, false, height, width, collapseProps);
        Object.assign(transitionStyles.toggle, styles);
    }
    if (collapseProps) {
        const styles = getToggleStyles(collapseProps, true, height, width, expandProps);
        Object.assign(transitionStyles.toggle, styles);
    }
    if (enterAnimation?.scaleUp) {
        const props = getScaleProps(enterAnimation?.scaleUp);
        const styles = getScaleStyles(props, false);
        Object.assign(transitionStyles.scale, styles);
    }
    if (exitAnimation?.scaleDown) {
        const props = getScaleProps(exitAnimation?.scaleDown, true);
        const styles = getScaleStyles(props, true);
        Object.assign(transitionStyles.scale, styles);
    }
    if (!!expandProps || !!collapseProps) {
        const wrapperStyles = getToggleWrapperStyles(expandProps, collapseProps, height, width);
        const mergedStyles = getMergedStyles(transitionStyles.scale, wrapperStyles);
        Object.assign(transitionStyles.scale, mergedStyles);
    }
    return transitionStyles;
};
const getTiming = (type, animation) => {
    if (!animation) {
        return 0;
    }
    const entry = Object.entries(animation).find(([key]) => key === type);
    if (entry) {
        const [_, value] = entry;
        if (typeof value !== 'boolean') {
            const delay = value.delay ? timingMap[value.delay] : 0;
            return timingMap[value.duration] + delay;
        }
        else if (value === true) {
            // Setting default duration to medium01
            return timingMap.medium01;
        }
    }
    return 0;
};
export const getTimeout = (enterAnimation, exitAnimation) => {
    const fadeEnter = getTiming('fadeIn', enterAnimation);
    const fadeExit = getTiming('fadeOut', exitAnimation);
    const moveEnter = getTiming('moveIn', enterAnimation);
    const moveExit = getTiming('moveOut', exitAnimation);
    const expand = getTiming('expand', enterAnimation);
    const collapse = getTiming('collapse', exitAnimation);
    const scaleUp = getTiming('scaleUp', enterAnimation);
    const scaleDown = getTiming('scaleDown', exitAnimation);
    return {
        enter: Math.max(fadeEnter, moveEnter, expand, scaleUp),
        exit: Math.max(fadeExit, moveExit, collapse, scaleDown),
    };
};
//# sourceMappingURL=utils.js.map