import React, { useImperativeHandle, useRef } from 'react';
import { useEventListener } from '@devesharp/react-hooks/lib/useEventListener';

export interface IScrollInfiniteProps
   extends React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement> {
   scrolledDown?: () => void;
   scrolledUp?: () => void;
   infiniteScrollDistance?: number;
}

export const InfiniteScroll = React.forwardRef(function InfiniteScroll(
   { children, scrolledDown, scrolledUp, infiniteScrollDistance = 200, ...rest }: IScrollInfiniteProps,
   ref,
): any {
   const refEl = useRef();
   const clientHeight = useRef(0);
   const scrollHeight = useRef(0);
   const oldScrollHeight = useRef(0);
   // Pode chamar o evento novamente
   const lastEvent = useRef('');

   useImperativeHandle(ref, () => refEl.current, []);

   useEventListener(
      'scroll',
      ($event: any) => {
         // Tamanho do Scroll
         scrollHeight.current = $event.target.scrollHeight;
         clientHeight.current = $event.target.clientHeight;
         const scrollPositionDown = $event.target.scrollTop + clientHeight.current;

         if ($event.target.scrollTop === 0) {
            if (lastEvent.current !== 'top' || oldScrollHeight.current !== scrollHeight.current) {
               oldScrollHeight.current = scrollHeight.current;
               lastEvent.current = 'top';
               if (scrolledUp) scrolledUp();
            }
         } else if (infiniteScrollDistance >= scrollHeight.current - scrollPositionDown) {
            if (lastEvent.current !== 'bottom' || oldScrollHeight.current !== scrollHeight.current) {
               oldScrollHeight.current = scrollHeight.current;
               lastEvent.current = 'bottom';
               if (scrolledDown) scrolledDown();
            }
         } else if (infiniteScrollDistance >= $event.target.scrollTop) {
            if (lastEvent.current !== 'top' || oldScrollHeight.current !== scrollHeight.current) {
               oldScrollHeight.current = scrollHeight.current;
               lastEvent.current = 'top';
               if (scrolledUp) scrolledUp();
            }
         } else {
            lastEvent.current = 'idle';
         }
      },
      refEl,
   );

   return (
      <div ref={refEl} {...rest}>
         {children}
      </div>
   );
});
