import { useState, useEffect, useCallback, useMemo } from 'react';
import { IUsePartialRenderProps } from '../types';

export const usePartialRender = ({
  ref,
  elementSize,
  direction = 'vertical',
  disable,
}: IUsePartialRenderProps) => {
  const [shift, setShift] = useState(0);
  const [containerSize, setContainerSize] = useState(0);

  useEffect(() => {
    if (disable) return;

    const container = ref?.current as Element | null;

    if (container) {
      const size =
        direction === 'vertical'
          ? container.clientHeight
          : container.clientWidth;

      setContainerSize(size);
    }
  }, [ref, direction, disable]);

  const { ratio, visibleCount } = useMemo(
    () => ({
      ratio: elementSize / containerSize,
      visibleCount: Math.floor(containerSize / elementSize),
    }),
    [elementSize, containerSize]
  );
  const itemsCount = useMemo(
    () => Math.floor((containerSize / elementSize) * (1.4 + ratio)),
    [containerSize, elementSize, ratio]
  );
  const buffer = useMemo(
    () => Math.floor((itemsCount - visibleCount) / 2) + 2,
    [visibleCount, itemsCount]
  );

  const handleScroll = useCallback(() => {
    const container = ref?.current as Element | null;

    if (container) {
      const scrollPosition =
        direction === 'vertical' ? container.scrollTop : container.scrollLeft;

      const newShift = Math.floor(scrollPosition / elementSize);

      setShift((prev) => (newShift !== prev ? newShift : prev));
    }
  }, [elementSize, direction, ref]);

  useEffect(() => {
    const container = ref?.current as Element | null;

    if (!disable) {
      container?.addEventListener('scroll', handleScroll);
    }

    return () => container?.removeEventListener('scroll', handleScroll);
  }, [handleScroll, ref, direction, disable]);

  return {
    from: Math.max(shift - buffer, 0),
    to: shift + itemsCount,
  };
};
