import React, {
  useRef, useEffect, useState, useCallback,
} from 'react';
import { CSSTransition } from 'react-transition-group';
import { motion } from 'framer-motion';

import {
  theme, useHover, Popover, Tooltip,
} from '@veeqo/ui';
import generateId from 'utils/generateId';
import ConditonalWrapper from 'components/common/ConditionalWrapper';
import {
  IStoreIcon, StoreIconProps, StoreIconsProps, StoreIconState,
} from './types';

import {
  Container,
  Integration,
  IconWrap,
  ShowMore,
  Text,
  ItemsCard,
  Item,
  InactiveCover,
  iconOffset,
} from './styled';

const iconWidth = 21.8;

const StoreIcon = ({
  index,
  icon,
  onClick = () => { },
  animated = true,
  hasTooltip = true,
}: StoreIconProps) => {
  const [isHovered, handleEnter, handleLeave] = useHover();
  const shouldShowInactive = icon.state === StoreIconState.inactive;
  const handleIconClick = useCallback(
    () => onClick(icon),
    [icon, onClick],
  );

  return (
    <CSSTransition
      in={animated && isHovered}
      timeout={350}
      classNames="store-icon"
    >
      <IconWrap
        index={index}
        isInteractive={hasTooltip || animated}
        onClick={handleIconClick}
        onMouseEnter={handleEnter}
        onMouseLeave={handleLeave}
      >
        <ConditonalWrapper
          condition={hasTooltip}
          wrapper={(children: JSX.Element) => <Tooltip text={icon.name}>{children}</Tooltip>}
        >
          <Integration name={icon.type} />
        </ConditonalWrapper>
        {shouldShowInactive && <InactiveCover />}
      </IconWrap>
    </CSSTransition>
  );
};

const StoreIcons = ({
  icons,
  onClick = () => { },
  numberOfShownIcons = 3,
  disableInteraction = false,
}: StoreIconsProps) => {
  const [isShowMoreHovered, showMoreEnter, showMoreLeave] = useHover();
  const [isPopoverHovered, onPopoverEnter, onPopoverLeave] = useHover();

  const [isClicked, setIsClicked] = useState(false);
  const shownIconsWidth = numberOfShownIcons * iconWidth - (numberOfShownIcons - 1) * iconOffset;
  const [totalWidth, setTotalWidth] = useState(shownIconsWidth);
  const visibleIcons = icons.slice(0, numberOfShownIcons);
  const remainingIcons = icons.slice(numberOfShownIcons);
  const showMoreRef = useRef<HTMLDivElement>(null);
  const shouldShowMore = remainingIcons.length > 0;
  const recievedInteraction = isClicked || isShowMoreHovered || isPopoverHovered;
  const shouldShowPopover = recievedInteraction && !disableInteraction;

  // Required due to issue with popover backdrop, read more:
  // https://github.com/veeqo/veeqo-frontend/pull/390/files#r970534798
  const onShouldClose = isClicked ? (() => setIsClicked(false)) : undefined;

  const handleClick = disableInteraction ? undefined : () => setIsClicked(!isClicked);
  const handleIconClick = (icon: IStoreIcon) => () => onClick(icon);

  useEffect(() => {
    if (showMoreRef.current) {
      setTotalWidth(totalWidth + showMoreRef.current.clientWidth - 10);
    }
  }, [setTotalWidth]);

  return (
    <Container width={totalWidth}>
      {visibleIcons.map((icon, index) => (
        <StoreIcon
          key={generateId(icon.type)}
          onClick={onClick}
          index={index}
          icon={icon}
          animated={visibleIcons.length > 1 && !disableInteraction}
          hasTooltip={!disableInteraction}
        />
      ))}

      {
        shouldShowMore && (
          <ShowMore
            ref={showMoreRef}
            onClick={handleClick}
            onMouseEnter={showMoreEnter}
            onMouseLeave={showMoreLeave}
            numIcons={visibleIcons.length}
            isInteractive={!disableInteraction}
          >
            <Text variant="bodySmall">
              {`+${remainingIcons.length}`}
            </Text>
          </ShowMore>
        )
      }

      {
        shouldShowPopover && (
          <Popover
            anchorElement={showMoreRef.current}
            onShouldClose={onShouldClose}
            zIndex={theme.layers.tooltip}
          >
            <motion.div
              initial={{ opacity: 0, transform: 'translateY(-6px)' }}
              animate={{ opacity: 1, transform: 'translateY(0px)' }}
              transition={{ duration: 0.35 }}
              onMouseEnter={onPopoverEnter}
              onMouseLeave={onPopoverLeave}
            >
              <ItemsCard>
                {remainingIcons.map((icon) => (
                  <Item onClick={handleIconClick(icon)} key={generateId(icon.type)}>
                    <Integration name={icon.type} />
                    <Text variant="bodySmall">
                      {icon.name}
                    </Text>
                  </Item>
                ))}
              </ItemsCard>
            </motion.div>
          </Popover>
        )
      }
    </Container>
  );
};

export default StoreIcons;
