'use strict';

var Icons = require('@transferwise/icons');
var clsx = require('clsx');
var React = require('react');
var ActionButton = require('../actionButton/ActionButton.js');
var Title = require('../title/Title.js');
var PromoCard = require('../promoCard/PromoCard.js');
var jsxRuntime = require('react/jsx-runtime');

const LEFT_SCROLL_OFFSET = 8;
const Carousel = ({
  header,
  className,
  cards,
  onClick
}) => {
  const [scrollPosition, setScrollPosition] = React.useState(0);
  const [previousScrollPosition, setPreviousScrollPosition] = React.useState(0);
  const [scrollIsAtEnd, setScrollIsAtEnd] = React.useState(false);
  const [visibleCardOnMobileView, setVisibleCardOnMobileView] = React.useState('');
  const carouselElementRef = React.useRef(null);
  const carouselCardsRef = React.useRef([]);
  const isLeftActionButtonEnabled = scrollPosition > LEFT_SCROLL_OFFSET;
  const areActionButtonsEnabled = isLeftActionButtonEnabled || !scrollIsAtEnd;
  const [focusedCard, setFocusedCard] = React.useState(cards?.[0]?.id);
  const updateScrollButtonsState = () => {
    if (carouselElementRef.current) {
      const {
        scrollWidth,
        offsetWidth
      } = carouselElementRef.current;
      const scrollAtEnd = scrollWidth - offsetWidth <= scrollPosition + LEFT_SCROLL_OFFSET;
      setScrollIsAtEnd(scrollAtEnd);
    }
    const scrollDirecton = scrollPosition > previousScrollPosition ? 'right' : 'left';
    const cardsInFullViewIds = [];
    carouselCardsRef.current.forEach(card => {
      if (isVisible(carouselElementRef.current, card.cardElement)) {
        // eslint-disable-next-line functional/immutable-data
        cardsInFullViewIds.push(card.cardElement.getAttribute('id') ?? '');
      }
    });
    if (cardsInFullViewIds.length >= 1) {
      const visibleCardIndex = scrollDirecton === 'right' ? cardsInFullViewIds.length - 1 : 0;
      const visibleCardId = cardsInFullViewIds[visibleCardIndex];
      setVisibleCardOnMobileView(visibleCardId);
      setFocusedCard(visibleCardId);
    }
    setPreviousScrollPosition(scrollPosition);
  };
  const scrollCarousel = (direction = 'right') => {
    if (carouselElementRef.current) {
      const {
        scrollWidth
      } = carouselElementRef.current;
      const cardWidth = scrollWidth / carouselCardsRef.current.length;
      const res = Math.floor(cardWidth - cardWidth * 0.05);
      carouselElementRef.current.scrollBy({
        left: direction === 'right' ? res : -res,
        behavior: 'smooth'
      });
    }
  };
  const handleOnKeyDown = (event, index) => {
    if (event.key === 'ArrowRight' || event.key === 'ArrowLeft') {
      const nextIndex = event.key === 'ArrowRight' ? index + 1 : index - 1;
      const nextCard = cards[nextIndex];
      if (nextCard) {
        const ref = carouselCardsRef.current[nextIndex];
        if (ref.type === 'promo') {
          ref.anchorElement?.focus();
        } else {
          ref.cardElement?.focus();
        }
        scrollCardIntoView(carouselCardsRef.current[nextIndex].cardElement, nextCard);
        event.preventDefault();
      }
    }
    if (event.key === 'Enter' || event.key === ' ') {
      event.currentTarget.click();
    }
  };
  const scrollCardIntoView = (element, card) => {
    element.scrollIntoView({
      behavior: 'smooth',
      block: 'nearest',
      inline: 'center'
    });
    setFocusedCard(card.id);
  };
  React.useEffect(() => {
    updateScrollButtonsState();
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [scrollPosition]);
  React.useEffect(() => {
    window.addEventListener('resize', updateScrollButtonsState);
    return () => {
      window.removeEventListener('resize', updateScrollButtonsState);
    };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);
  const addElementToCardsRefArray = (index, ref) => {
    if (ref) {
      // eslint-disable-next-line functional/immutable-data
      carouselCardsRef.current[index] = {
        type: ref.type ?? carouselCardsRef.current?.[index]?.type,
        cardElement: ref.cardElement ?? carouselCardsRef.current?.[index]?.cardElement,
        anchorElement: ref.anchorElement ?? carouselCardsRef.current?.[index]?.anchorElement
      };
    }
  };
  return /*#__PURE__*/jsxRuntime.jsxs("div", {
    className: clsx.clsx('carousel-wrapper', className),
    children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
      className: "d-flex justify-content-between carousel__header",
      children: [typeof header === 'string' ? /*#__PURE__*/jsxRuntime.jsx(Title, {
        as: "span",
        type: "title-body",
        children: header
      }) : header, areActionButtonsEnabled ? /*#__PURE__*/jsxRuntime.jsxs("div", {
        className: "hidden-xs",
        children: [/*#__PURE__*/jsxRuntime.jsx(ActionButton, {
          className: "carousel__scroll-button",
          tabIndex: -1,
          priority: "secondary",
          disabled: !isLeftActionButtonEnabled,
          "aria-hidden": "true",
          "data-testid": "scroll-carousel-left",
          onClick: () => scrollCarousel('left'),
          children: /*#__PURE__*/jsxRuntime.jsx(Icons.ChevronLeft, {})
        }), /*#__PURE__*/jsxRuntime.jsx(ActionButton, {
          tabIndex: -1,
          className: "carousel__scroll-button m-l-1",
          priority: "secondary",
          "aria-hidden": "true",
          "data-testid": "scroll-carousel-right",
          disabled: scrollIsAtEnd,
          onClick: () => scrollCarousel(),
          children: /*#__PURE__*/jsxRuntime.jsx(Icons.ChevronRight, {})
        })]
      }) : null]
    }), /*#__PURE__*/jsxRuntime.jsx("div", {
      ref: carouselElementRef,
      tabIndex: -1,
      role: "list",
      className: "carousel",
      onScroll: event => {
        const target = event.target;
        setScrollPosition(target.scrollLeft);
      },
      children: cards?.map((card, index) => {
        const sharedProps = {
          id: card.id,
          className: clsx.clsx('carousel__card', {
            'carousel__card--focused': card.id === focusedCard
          }),
          onClick: () => {
            card.onClick?.();
            onClick?.(card.id);
          },
          onFocus: event => {
            scrollCardIntoView(event.currentTarget, card);
          }
        };
        const cardContent = card.type !== 'promo' ? /*#__PURE__*/jsxRuntime.jsx("div", {
          id: `${card.id}-content`,
          className: clsx.clsx('carousel__card-content', {
            [card.className ?? '']: !!card.className
          })
          // eslint-disable-next-line react/forbid-dom-props
          ,
          style: card.styles,
          children: card.content
        }) : null;
        if (card.type === 'button') {
          return /*#__PURE__*/jsxRuntime.jsx("div", {
            "aria-labelledby": `${card.id}-content`,
            role: "listitem",
            children: /*#__PURE__*/jsxRuntime.jsx("div", {
              ...sharedProps,
              ref: el => {
                if (el) {
                  // eslint-disable-next-line functional/immutable-data
                  carouselCardsRef.current[index] = {
                    type: 'default',
                    cardElement: el
                  };
                }
              },
              role: "button",
              tabIndex: 0,
              onKeyDown: event => handleOnKeyDown(event, index),
              children: cardContent
            })
          }, card.id);
        }
        if (card.type === 'promo') {
          return /*#__PURE__*/jsxRuntime.jsx("div", {
            id: card.id,
            role: "listitem",
            "aria-labelledby": `${card.id}-anchor`,
            children: /*#__PURE__*/jsxRuntime.jsx(PromoCard, {
              ...card,
              type: undefined,
              ...sharedProps,
              ref: el => {
                if (el) {
                  addElementToCardsRefArray(index, {
                    type: 'promo',
                    cardElement: el
                  });
                }
              },
              anchorRef: el => {
                if (el) {
                  addElementToCardsRefArray(index, {
                    type: 'promo',
                    anchorElement: el
                  });
                }
              },
              anchorId: `${card.id}-anchor`,
              onKeyDown: event => handleOnKeyDown(event, index)
            })
          }, card.id);
        }
        return /*#__PURE__*/jsxRuntime.jsx("div", {
          "aria-labelledby": `${card.id}-content`,
          role: "listitem",
          children: /*#__PURE__*/jsxRuntime.jsx("a", {
            ...sharedProps,
            ref: el => {
              if (el) {
                // eslint-disable-next-line functional/immutable-data
                carouselCardsRef.current[index] = {
                  type: 'default',
                  cardElement: el
                };
              }
            },
            href: card.href,
            target: card.hrefTarget,
            rel: "noreferrer",
            onKeyDown: event => handleOnKeyDown(event, index),
            children: cardContent
          })
        }, card.id);
      })
    }), /*#__PURE__*/jsxRuntime.jsx("div", {
      className: "visible-xs",
      children: /*#__PURE__*/jsxRuntime.jsx("div", {
        className: "carousel__indicators",
        children: cards?.map((card, index) => /*#__PURE__*/jsxRuntime.jsx("button", {
          "data-testid": `${card.id}-indicator`,
          tabIndex: -1,
          "aria-hidden": true,
          type: "button",
          className: clsx.clsx('carousel__indicator', {
            'carousel__indicator--selected': card.id === visibleCardOnMobileView
          }),
          onClick: () => {
            scrollCardIntoView(carouselCardsRef.current[index].cardElement, card);
          }
        }, `${card.id}-indicator`))
      })
    })]
  });
};
const isVisible = (container, el) => {
  const cWidth = container.offsetWidth;
  const cScrollOffset = container.scrollLeft;
  const elemLeft = el.offsetLeft - container.offsetLeft;
  const elemRight = elemLeft + el.offsetWidth;
  return elemLeft >= cScrollOffset && elemRight <= cScrollOffset + cWidth;
};

module.exports = Carousel;
//# sourceMappingURL=Carousel.js.map
