"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.SliderOldBlock = void 0;
const tslib_1 = require("tslib");
const jsx_runtime_1 = require("react/jsx-runtime");
const React = tslib_1.__importStar(require("react"));
const uikit_1 = require("@gravity-ui/uikit");
const debounce_1 = tslib_1.__importDefault(require("lodash/debounce.js"));
const get_1 = tslib_1.__importDefault(require("lodash/get.js"));
const noop_1 = tslib_1.__importDefault(require("lodash/noop.js"));
const react_slick_1 = tslib_1.__importDefault(require("react-slick"));
const Anchor_1 = tslib_1.__importDefault(require("../../components/Anchor/Anchor.js"));
const AnimateBlock_1 = tslib_1.__importDefault(require("../../components/AnimateBlock/AnimateBlock.js"));
const OutsideClick_1 = tslib_1.__importDefault(require("../../components/OutsideClick/OutsideClick.js"));
const Title_1 = tslib_1.__importDefault(require("../../components/Title/Title.js"));
const constants_1 = require("../../constants.js");
const mobileContext_1 = require("../../gravity-blocks/context/mobileContext/index.js");
const ssrContext_1 = require("../../gravity-blocks/context/ssrContext/index.js");
const StylesContext_1 = require("../../gravity-blocks/context/stylesContext/StylesContext.js");
const useFocus_1 = tslib_1.__importDefault(require("../../gravity-blocks/hooks/useFocus.js"));
const models_1 = require("../../models/index.js");
const utils_1 = require("../../utils/index.js");
const Arrow_1 = tslib_1.__importDefault(require("./Arrow/Arrow.js"));
const i18n_1 = require("./i18n/index.js");
const utils_2 = require("./utils.js");
const b = (0, utils_1.block)('SliderOldBlock');
const slick = (0, utils_1.block)('slick-origin');
const DOT_WIDTH = 8;
const DOT_GAP = 16;
// eslint-disable-next-line valid-jsdoc
/** @deprecated */
const SliderOldBlock = (props) => {
    const { animated, title, description, type, anchorId, arrows = true, adaptive, autoplay: autoplaySpeed, dots = true, dotsClassName, disclaimer, children, className, blockClassName, lazyLoad, arrowSize, onAfterChange: handleAfterChange, onBeforeChange: handleBeforeChange, initialIndex = 0, } = props;
    const { isServer } = React.useContext(ssrContext_1.SSRContext);
    const isMobile = React.useContext(mobileContext_1.MobileContext);
    const [breakpoint, setBreakpoint] = React.useState(constants_1.BREAKPOINTS.xl);
    const sliderId = (0, uikit_1.useUniqId)();
    const disclosedChildren = React.useMemo(() => discloseAllNestedChildren(children, sliderId), [children, sliderId]);
    const childrenCount = disclosedChildren.length;
    const isAutoplayEnabled = autoplaySpeed !== undefined && autoplaySpeed > 0;
    const isUserInteractionRef = React.useRef(false);
    const [slidesToShow] = React.useState((0, utils_2.getSlidesToShowWithDefaults)({
        contentLength: childrenCount,
        breakpoints: props.slidesToShow,
        mobileFullscreen: Boolean(props.type && Object.values(models_1.SliderType).includes(props.type)),
    }));
    const slidesToShowCount = (0, utils_2.getSlidesToShowCount)(slidesToShow);
    const slidesCountByBreakpoint = (0, utils_2.getSlidesCountByBreakpoint)(breakpoint, slidesToShow);
    const [currentIndex, setCurrentIndex] = React.useState(initialIndex);
    const [childStyles, setChildStyles] = React.useState({});
    const [slider, setSlider] = React.useState();
    const prevIndexRef = React.useRef(0);
    const autoplayTimeId = React.useRef();
    const { hasFocus, unsetFocus } = (0, useFocus_1.default)(slider?.innerSlider?.list);
    const asUserInteraction = (fn) => (...args) => {
        isUserInteractionRef.current = true;
        return fn(...args);
    };
    // eslint-disable-next-line react-hooks/exhaustive-deps
    const onResize = React.useCallback((0, debounce_1.default)(() => {
        if (!slider) {
            return;
        }
        const newBreakpoint = (0, get_1.default)(slider, 'state.breakpoint') || constants_1.BREAKPOINTS.xl;
        if (newBreakpoint !== breakpoint) {
            setBreakpoint(newBreakpoint);
            setCurrentIndex(0);
            slider.slickGoTo(0);
        }
    }, 100), [slider, breakpoint]);
    const scrollLastSlide = React.useCallback((current) => {
        const lastSlide = childrenCount - slidesToShowCount;
        if (isAutoplayEnabled && lastSlide === current) {
            // Slick doesn't support autoplay with no infinity scroll
            autoplayTimeId.current = setTimeout(() => {
                if (slider) {
                    slider.slickGoTo(0, false);
                    slider.slickPause();
                }
                setTimeout(() => {
                    if (slider) {
                        slider.slickPlay();
                    }
                }, 500);
            }, autoplaySpeed);
        }
    }, [autoplaySpeed, childrenCount, isAutoplayEnabled, slider, slidesToShowCount]);
    React.useEffect(() => {
        if (hasFocus && autoplayTimeId.current) {
            clearTimeout(autoplayTimeId.current);
        }
        else {
            scrollLastSlide(currentIndex);
        }
    }, [currentIndex, hasFocus, scrollLastSlide]);
    React.useEffect(() => {
        onResize();
        window.addEventListener('resize', onResize, { passive: true });
        return () => window.removeEventListener('resize', onResize);
    }, [onResize]);
    const handleArrowClick = (direction) => {
        let nextIndex;
        if (direction === 'right') {
            nextIndex =
                currentIndex === childrenCount - slidesCountByBreakpoint ? 0 : currentIndex + 1;
        }
        else {
            nextIndex =
                currentIndex === 0 ? childrenCount - slidesCountByBreakpoint : currentIndex - 1;
        }
        if (slider) {
            slider.slickGoTo(nextIndex);
        }
    };
    const onBeforeChange = React.useCallback((current, next) => {
        if (handleBeforeChange) {
            handleBeforeChange(current, next);
        }
        prevIndexRef.current = current;
        setCurrentIndex(Math.ceil(next));
    }, [handleBeforeChange]);
    const onAfterChange = React.useCallback((current) => {
        if (handleAfterChange) {
            handleAfterChange(current);
        }
        if (autoplayTimeId.current) {
            clearTimeout(autoplayTimeId.current);
        }
        if (!hasFocus) {
            scrollLastSlide(current);
        }
        if (isUserInteractionRef.current) {
            const focusIndex = prevIndexRef.current >= current
                ? current
                : Math.max(current, prevIndexRef.current + slidesCountByBreakpoint);
            const firstNewSlide = document.getElementById(getSlideId(sliderId, focusIndex));
            if (firstNewSlide) {
                const focusableChild = Array.from(firstNewSlide.querySelectorAll('*')).find(utils_2.isFocusable);
                focusableChild?.focus();
            }
        }
        isUserInteractionRef.current = false;
    }, [handleAfterChange, hasFocus, scrollLastSlide, sliderId, slidesCountByBreakpoint]);
    const handleDotClick = (index) => {
        const nextIndex = index > currentIndex ? index + 1 - slidesCountByBreakpoint : index;
        if (slider) {
            slider.slickGoTo(nextIndex);
        }
    };
    const barSlidesCount = childrenCount - slidesCountByBreakpoint + 1;
    const barPosition = (DOT_GAP + DOT_WIDTH) * currentIndex;
    const barWidth = DOT_WIDTH + (DOT_GAP + DOT_WIDTH) * (slidesCountByBreakpoint - 1);
    const { getRovingItemProps, rovingListProps } = (0, utils_2.useRovingTabIndex)({
        itemCount: barSlidesCount,
        activeIndex: currentIndex + 1,
        firstIndex: 1,
        uniqId: sliderId,
    });
    const renderBar = () => {
        return (slidesCountByBreakpoint > 1 && ((0, jsx_runtime_1.jsx)("li", { className: b('bar'), style: {
                left: barPosition,
                width: barWidth,
            } })));
    };
    // renders additional bar, not visible in the layout but visible for screenreaders
    const renderAccessibleBar = (index) => {
        return (
        // To have this key differ from keys used in renderDot function, added `-accessible-bar` part
        (0, jsx_runtime_1.jsx)(React.Fragment, { children: slidesCountByBreakpoint > 0 && ((0, jsx_runtime_1.jsx)("li", { className: b('accessible-bar'), role: "menuitemradio", "aria-checked": true, "aria-label": (0, i18n_1.i18n)('dot-label', {
                    index: currentIndex + 1,
                    count: barSlidesCount,
                }), style: {
                    left: barPosition,
                    width: barWidth,
                }, ...getRovingItemProps(currentIndex + 1) })) }, `${index}-accessible-bar`));
    };
    const getCurrentSlideNumber = (index) => {
        const currentIndexDiff = index - currentIndex;
        let currentSlideNumber;
        if (0 <= currentIndexDiff && currentIndexDiff < slidesCountByBreakpoint) {
            currentSlideNumber = currentIndex + 1;
        }
        else if (currentIndexDiff >= slidesCountByBreakpoint) {
            currentSlideNumber = index - slidesCountByBreakpoint + 2;
        }
        else {
            currentSlideNumber = index + 1;
        }
        return currentSlideNumber;
    };
    const isVisibleSlide = (index) => {
        const currentIndexDiff = index - currentIndex;
        const result = slidesCountByBreakpoint > 0 &&
            0 <= currentIndexDiff &&
            currentIndexDiff < slidesCountByBreakpoint;
        return result;
    };
    const renderDot = (index) => {
        const isVisible = isVisibleSlide(index);
        const currentSlideNumber = getCurrentSlideNumber(index);
        const rovingItemProps = isVisible ? undefined : getRovingItemProps(currentSlideNumber);
        return ((0, jsx_runtime_1.jsx)("li", { className: b('dot', { active: index === currentIndex }), onClick: asUserInteraction(() => handleDotClick(index)), onKeyDown: (e) => {
                const key = e.key.toLowerCase();
                if (key === 'space' || key === 'enter') {
                    e.currentTarget.click();
                }
            }, role: "menuitemradio", "aria-checked": false, tabIndex: -1, "aria-hidden": isVisible, "aria-label": (0, i18n_1.i18n)('dot-label', {
                index: currentSlideNumber,
                count: barSlidesCount,
            }), ...rovingItemProps }, index));
    };
    const renderNavigation = () => {
        if (childrenCount <= slidesCountByBreakpoint || !dots || childrenCount === 1) {
            return null;
        }
        const dotsList = Array(childrenCount)
            .fill(null)
            .map((_item, index) => renderDot(index));
        dotsList.splice(currentIndex, 0, renderAccessibleBar(currentIndex));
        return ((0, jsx_runtime_1.jsx)("div", { className: b('dots', dotsClassName), children: (0, jsx_runtime_1.jsxs)("ul", { className: b('dots-list'), role: "menu", "aria-label": (0, i18n_1.i18n)('pagination-label'), ...rovingListProps, children: [renderBar(), dotsList] }) }));
    };
    const renderDisclaimer = () => {
        return disclaimer ? ((0, jsx_runtime_1.jsx)("div", { className: b('disclaimer', { size: disclaimer.size || 'm' }), children: disclaimer.text })) : null;
    };
    const renderSlider = () => {
        /* Disable adding of width in inline styles when SSR to prevent overriding of default styles */
        /* Calculate appropriate breakpoint for mobile devices with user agent */
        const variableWidth = isServer && isMobile;
        const settings = {
            ref: (slickSlider) => setSlider(slickSlider),
            className: slick(null, className),
            arrows,
            variableWidth,
            infinite: false,
            speed: 1000,
            adaptiveHeight: adaptive,
            autoplay: isAutoplayEnabled,
            autoplaySpeed,
            slidesToShow: slidesToShowCount,
            slidesToScroll: 1,
            responsive: (0, utils_2.getSliderResponsiveParams)(slidesToShow),
            beforeChange: onBeforeChange,
            afterChange: onAfterChange,
            initialSlide: initialIndex,
            nextArrow: ((0, jsx_runtime_1.jsx)(Arrow_1.default, { type: "right", handleClick: asUserInteraction(handleArrowClick), size: arrowSize })),
            prevArrow: ((0, jsx_runtime_1.jsx)(Arrow_1.default, { type: "left", handleClick: asUserInteraction(handleArrowClick), size: arrowSize })),
            lazyLoad,
            accessibility: false,
        };
        return ((0, jsx_runtime_1.jsxs)(OutsideClick_1.default, { onOutsideClick: isMobile ? unsetFocus : noop_1.default, children: [(0, jsx_runtime_1.jsx)(react_slick_1.default, { ...settings, children: disclosedChildren }), (0, jsx_runtime_1.jsxs)("div", { className: b('footer'), children: [renderDisclaimer(), renderNavigation()] })] }));
    };
    return ((0, jsx_runtime_1.jsx)(StylesContext_1.StylesContext.Provider, { value: { ...childStyles, setStyles: setChildStyles }, children: (0, jsx_runtime_1.jsxs)("div", { className: b({
                'align-left': childrenCount < slidesCountByBreakpoint,
                'one-slide': childrenCount === 1,
                'only-arrows': (!title || (typeof title !== 'string' && !title?.text)) &&
                    !description &&
                    arrows,
                mobile: isMobile,
                type,
            }, blockClassName), children: [anchorId && (0, jsx_runtime_1.jsx)(Anchor_1.default, { id: anchorId }), (0, jsx_runtime_1.jsx)(Title_1.default, { title: title, subtitle: description, className: b('header', { 'no-description': !description }) }), (0, jsx_runtime_1.jsx)(AnimateBlock_1.default, { className: b('animate-slides'), animate: animated, children: renderSlider() })] }) }));
};
exports.SliderOldBlock = SliderOldBlock;
function getSlideId(sliderId, index) {
    return `slider-${sliderId}-child-${index}`;
}
// TODO remove this and rework PriceDetailed CLOUDFRONT-12230
function discloseAllNestedChildren(children, sliderId) {
    if (!children) {
        return [];
    }
    let childIndex = 0;
    const wrapped = (child) => {
        const id = getSlideId(sliderId, childIndex++);
        return ((0, jsx_runtime_1.jsx)("div", { id: id, children: child }, id));
    };
    return React.Children.map(children, (child) => {
        if (child) {
            // TODO: if child has 'items' then 'items' determinate like nested children for Slider.
            const nestedChildren = child.props.data?.items;
            if (nestedChildren) {
                return nestedChildren.map((nestedChild) => {
                    return wrapped(React.cloneElement(child, {
                        data: {
                            ...child.props.data,
                            items: [nestedChild],
                        },
                    }));
                });
            }
        }
        return child && wrapped(child);
    }).filter(Boolean);
}
exports.default = exports.SliderOldBlock;
//# sourceMappingURL=SliderOld.js.map
