import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import * as React from 'react';
import { useUniqId } from '@gravity-ui/uikit';
import debounce from "lodash/debounce.js";
import get from "lodash/get.js";
import noop from "lodash/noop.js";
import SlickSlider from 'react-slick';
import Anchor from "../../components/Anchor/Anchor.js";
import AnimateBlock from "../../components/AnimateBlock/AnimateBlock.js";
import OutsideClick from "../../components/OutsideClick/OutsideClick.js";
import Title from "../../components/Title/Title.js";
import { BREAKPOINTS } from "../../constants.js";
import { MobileContext } from "../../gravity-blocks/context/mobileContext/index.js";
import { SSRContext } from "../../gravity-blocks/context/ssrContext/index.js";
import { StylesContext } from "../../gravity-blocks/context/stylesContext/StylesContext.js";
import useFocus from "../../gravity-blocks/hooks/useFocus.js";
import { SliderType, } from "../../models/index.js";
import { block } from "../../utils/index.js";
import Arrow from "./Arrow/Arrow.js";
import { i18n } from "./i18n/index.js";
import { getSliderResponsiveParams, getSlidesCountByBreakpoint, getSlidesToShowCount, getSlidesToShowWithDefaults, isFocusable, useRovingTabIndex, } from "./utils.js";
import './SliderOld.css';
const b = block('SliderOldBlock');
const slick = block('slick-origin');
const DOT_WIDTH = 8;
const DOT_GAP = 16;
// eslint-disable-next-line valid-jsdoc
/** @deprecated */
export 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);
    const isMobile = React.useContext(MobileContext);
    const [breakpoint, setBreakpoint] = React.useState(BREAKPOINTS.xl);
    const sliderId = 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(getSlidesToShowWithDefaults({
        contentLength: childrenCount,
        breakpoints: props.slidesToShow,
        mobileFullscreen: Boolean(props.type && Object.values(SliderType).includes(props.type)),
    }));
    const slidesToShowCount = getSlidesToShowCount(slidesToShow);
    const slidesCountByBreakpoint = 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 } = useFocus(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(debounce(() => {
        if (!slider) {
            return;
        }
        const newBreakpoint = get(slider, 'state.breakpoint') || 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(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 } = useRovingTabIndex({
        itemCount: barSlidesCount,
        activeIndex: currentIndex + 1,
        firstIndex: 1,
        uniqId: sliderId,
    });
    const renderBar = () => {
        return (slidesCountByBreakpoint > 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
        _jsx(React.Fragment, { children: slidesCountByBreakpoint > 0 && (_jsx("li", { className: b('accessible-bar'), role: "menuitemradio", "aria-checked": true, "aria-label": 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 (_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": 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 (_jsx("div", { className: b('dots', dotsClassName), children: _jsxs("ul", { className: b('dots-list'), role: "menu", "aria-label": i18n('pagination-label'), ...rovingListProps, children: [renderBar(), dotsList] }) }));
    };
    const renderDisclaimer = () => {
        return disclaimer ? (_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: getSliderResponsiveParams(slidesToShow),
            beforeChange: onBeforeChange,
            afterChange: onAfterChange,
            initialSlide: initialIndex,
            nextArrow: (_jsx(Arrow, { type: "right", handleClick: asUserInteraction(handleArrowClick), size: arrowSize })),
            prevArrow: (_jsx(Arrow, { type: "left", handleClick: asUserInteraction(handleArrowClick), size: arrowSize })),
            lazyLoad,
            accessibility: false,
        };
        return (_jsxs(OutsideClick, { onOutsideClick: isMobile ? unsetFocus : noop, children: [_jsx(SlickSlider, { ...settings, children: disclosedChildren }), _jsxs("div", { className: b('footer'), children: [renderDisclaimer(), renderNavigation()] })] }));
    };
    return (_jsx(StylesContext.Provider, { value: { ...childStyles, setStyles: setChildStyles }, children: _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 && _jsx(Anchor, { id: anchorId }), _jsx(Title, { title: title, subtitle: description, className: b('header', { 'no-description': !description }) }), _jsx(AnimateBlock, { className: b('animate-slides'), animate: animated, children: renderSlider() })] }) }));
};
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 (_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);
}
export default SliderOldBlock;
//# sourceMappingURL=SliderOld.js.map
