import {Fragment, useEffect, useState} from "react";

export default function Pagination({totalPages, onNewPage}) {
    const LEFT_PAGE = 'LEFT';
    const RIGHT_PAGE = 'RIGHT';

    const range = (from, to, step = 1) => {
        let i = from;
        const range = [];

        while (i <= to) {
            range.push(i);
            i += step;
        }

        return range;
    }

    const [currentPage, setCurrentPage] = useState(1)
    useEffect(() => {
        gotoPage(1);
    }, []) 

    const gotoPage = page => {
        setCurrentPage(page)
    }

    const handleClick = page => evt => {
        evt.preventDefault();
        gotoPage(page);
        onNewPage(page)
    }

    const handleMoveLeft = evt => {
        evt.preventDefault();
        gotoPage(currentPage - 3);
    }

    const handleMoveRight = evt => {
        evt.preventDefault();
        gotoPage(currentPage + 5);
    }

    /**
     * Let's say we have 10 pages and we set pageNeighbours to 2
     * Given that the current page is 6
     * The pagination control will look like the following:
     *
     * (1) < {4 5} [6] {7 8} > (10)
     *
     * (x) => terminal pages: first and last page(always visible)
     * [x] => represents current page
     * {...x} => represents page neighbours
     */
    const fetchPageNumbers = () => {

        const pageNeighbours = 2;

        /**
         * totalNumbers: the total page numbers to show on the control
         * totalBlocks: totalNumbers + 2 to cover for the left(<) and right(>) controls
         */
        const totalNumbers = 7;
        const totalBlocks = totalNumbers + 2;

        if (totalPages > totalBlocks) {

            const startPage = Math.max(2, currentPage - pageNeighbours);
            const endPage = Math.min(totalPages - 1, currentPage + pageNeighbours);

            let pages = range(startPage, endPage);

            /**
             * hasLeftSpill: has hidden pages to the left
             * hasRightSpill: has hidden pages to the right
             * spillOffset: number of hidden pages either to the left or to the right
             */
            const hasLeftSpill = startPage > 2;
            const hasRightSpill = (totalPages - endPage) > 1;
            const spillOffset = totalNumbers - (pages.length + 1);

            switch (true) {
                // handle: (1) < {5 6} [7] {8 9} (10)
                case (hasLeftSpill && !hasRightSpill): {
                    const extraPages = range(startPage - spillOffset, startPage - 1);
                    pages = [LEFT_PAGE, ...extraPages, ...pages];
                    break;
                }

                // handle: (1) {2 3} [4] {5 6} > (10)
                case (!hasLeftSpill && hasRightSpill): {
                    const extraPages = range(endPage + 1, endPage + spillOffset);
                    pages = [...pages, ...extraPages, RIGHT_PAGE];
                    break;
                }

                // handle: (1) < {4 5} [6] {7 8} > (10)
                case (hasLeftSpill && hasRightSpill):
                default: {
                    pages = [LEFT_PAGE, ...pages, RIGHT_PAGE];
                    break;
                }
            }

            return [1, ...pages, totalPages];

        }

        return range(1, totalPages);

    }

    if (totalPages === 1) return null;
    const pages = fetchPageNumbers();

    return (
        <Fragment>
            <nav aria-label="Pagination">
                <ul className="pagination">
                    { pages.map((page, index) => {

                        if (page === LEFT_PAGE) return (
                            <li key={index} className="page-item">
                                <a className="page-link" href="#" aria-label="Previous" onClick={handleMoveLeft}>
                                    <span aria-hidden="true">&laquo;</span>
                                    <span className="sr-only">قبلی</span>
                                </a>
                            </li>
                        );

                        if (page === RIGHT_PAGE) return (
                            <li key={index} className="page-item">
                                <a className="page-link" href="#" aria-label="Next" onClick={handleMoveRight}>
                                    <span className="sr-only">بعدی</span>
                                    <span aria-hidden="true">&raquo;</span>
                                </a>
                            </li>
                        );

                        return (
                            <li key={index} className={`page-item${ currentPage === page ? ' active' : ''}`}>
                                <a className="page-link" href="#" onClick={ handleClick(page) }>{ page }</a>
                            </li>
                        );

                    }) }

                </ul>
            </nav>
        </Fragment>
    );
}