import React, { useEffect, useRef } from 'react';
import { LoadingIndicator } from '@theorchard/suite-components';
import { debounce } from 'lodash';
import { MAIN_CONTENT_CLASSNAME } from 'src/constants';

export interface InfiniteScrollProps {
    fetchMore: (limit: number, offset: number) => void;
    totalLimit?: number;
    totalResults?: number;
    loadLimit?: number;
    count: number;
    loading: boolean;
    scrollContainerClassName?: string;
    children: React.ReactNode;
}

const CLASSNAME = 'InfiniteScroll';
const CLASSNAME_FOOTER = `${CLASSNAME}-footer`;
export const TESTID = CLASSNAME;

const InfiniteScroll: React.FC<InfiniteScrollProps> = ({
    fetchMore,
    children,
    totalLimit = Number.MAX_SAFE_INTEGER,
    totalResults = Number.MAX_SAFE_INTEGER,
    loadLimit = 100,
    count,
    loading,
    scrollContainerClassName = MAIN_CONTENT_CLASSNAME,
}) => {
    const container = useRef<HTMLDivElement>(null);

    const calculateScrollPosition = debounce(() => {
        if (
            container.current &&
            !loading &&
            count < totalLimit &&
            count < totalResults
        ) {
            const rect = container.current.getBoundingClientRect();
            const viewportBottom = window.scrollY + window.innerHeight;
            const elementBottom = rect.top + rect.height + window.scrollY;

            const activationPoint = window.innerHeight * 1.5;
            if (viewportBottom > elementBottom - activationPoint)
                fetchMore(Math.min(loadLimit, totalLimit - count), count);
        }
    }, 100);

    useEffect(() => {
        const scrollContainer = document
            .getElementsByClassName(scrollContainerClassName)
            .item(0);
        if (scrollContainer)
            scrollContainer.addEventListener('scroll', calculateScrollPosition);
        return () => {
            if (scrollContainer)
                scrollContainer.removeEventListener(
                    'scroll',
                    calculateScrollPosition
                );
        };
    }, [scrollContainerClassName, calculateScrollPosition]);

    return (
        <div ref={container} className={CLASSNAME} data-testid={TESTID}>
            {children}
            <div className={CLASSNAME_FOOTER}>
                {loading && count > 0 && <LoadingIndicator />}
                {count > totalLimit && (
                    <div className="text-muted">
                        {$t('neighbouringRights.infiniteScroll.tooManyResults')}
                    </div>
                )}
            </div>
        </div>
    );
};

export default InfiniteScroll;
