import { useCallback, useImperativeHandle, useRef } from 'react';

import type { ClickableOnClick } from '~/src/components/Clickable';
import type { FC, ReactNode, RefObject } from 'react';

import Box from '~/src/components/Box';
import Clickable from '~/src/components/Clickable';
import { usePageTheme } from '../../../hooks/theme';

export interface PaginatedDotsApi {
  setIndex: (index: number) => void;
}

const PaginatedDots: FC<{
  onItemClick?: (index: number) => void;
  apiRef?: RefObject<PaginatedDotsApi | null>;
  total: number;
}> = ({ apiRef, total, onItemClick = () => {} }) => {
  const SIZE = '.75rem';
  const SPACE_BETWEEN_REMS = 0.23;
  const items: ReactNode[] = [];
  const currentIndexRef = useRef(0);
  const rootElRef = useRef<HTMLElement>(null);
  const pageTheme = usePageTheme();

  const setIndex = (newIndex: number) => {
    const els = rootElRef.current?.querySelectorAll('.dot');

    [].forEach.call(els, (el, index) => {
      const isActive = index === newIndex;

      el.style.opacity = isActive ? '.8' : '.25';
      el.style.transform = isActive ? '' : 'scale(.89)';
    });

    currentIndexRef.current = newIndex;
  };

  useImperativeHandle(apiRef, () => ({
    setIndex,
  }));

  const onItemClickInternal = useCallback<ClickableOnClick<number>>(
    ({ data: index }) => {
      onItemClick(index);
      setIndex(index);
    },
    [onItemClick]
  );

  for (let i = 0; i < total; i++) {
    const isActive = i === currentIndexRef.current;

    items.push(
      <Clickable
        key={i}
        className="dot"
        testId="paginatedDot"
        withActiveStyle={false}
        withHoverStyle={false}
        onClick={onItemClickInternal}
        data={i}
        style={{
          background: pageTheme.textColor,
          width: SIZE,
          height: SIZE,
          borderRadius: '50%',
          margin: `0 ${SPACE_BETWEEN_REMS}rem`,
          opacity: isActive ? 0.8 : 0.2,
          transform: isActive ? '' : 'scale(.8)',
        }}
      />
    );
  }

  return (
    <Box
      flexBox
      margin={`0 -${SPACE_BETWEEN_REMS}rem`}
      centerContent
      alignCenter
      nodeRef={rootElRef}
    >
      {items}
    </Box>
  );
};

export default PaginatedDots;
