import React from "react";
import ArrowButton from "./ArrowButton";
import Dots from "./Dots";
import PaginationArrow from "../assets/PaginationArrow";
import StyledPagination from "./StyledPagination";
import PageButton from "./PageButton";

type classes = {
  root?: string;
  arrowButton?: string;
  pageButton?: string;
  dots?: string;
};

type PaginationProps = {
  changePage: (page: number) => void;
  classes?: classes;
  currentPage: number;
  pageCount: number;
  siblingCount?: number;
  props?: any;
};

const DOTS: string = "...";

const Pagination: React.FC<PaginationProps> = ({
  changePage,
  classes,
  currentPage,
  pageCount,
  siblingCount = 1,
  ...props
}) => {
  const range = (start: number, end: number): Array<number> => {
    let length = end - start + 1;
    return [...Array(length).keys()].map((index) => index + start);
  };

  const calculatePaginationRange = (): Array<number | string> => {
    const minimumPageCount: number = siblingCount + 5;

    if (minimumPageCount >= pageCount) return range(1, pageCount);

    const leftSiblingIndex: number = Math.max(currentPage - siblingCount, 1);
    const rightSiblingIndex: number = Math.min(
      currentPage + siblingCount,
      pageCount
    );

    const shouldShowLeftDots: boolean = leftSiblingIndex > 2;
    const shouldShowRightDots: boolean = rightSiblingIndex < pageCount - 2;

    if (shouldShowLeftDots && !shouldShowRightDots) {
      const rightRangeCount: number = pageCount - (2 + 2 * siblingCount);
      const rightRange: Array<number> = range(rightRangeCount, pageCount);

      return [1, DOTS, ...rightRange];
    } else if (!shouldShowLeftDots && shouldShowRightDots) {
      const leftRangeCount: number = 3 + 2 * siblingCount;
      const leftRange: Array<number> = range(1, leftRangeCount);

      return [...leftRange, DOTS, pageCount];
    } else if (shouldShowLeftDots && shouldShowRightDots) {
      const middleRange: Array<number> = range(
        leftSiblingIndex,
        rightSiblingIndex
      );

      return [1, DOTS, ...middleRange, DOTS, pageCount];
    } else return [];
  };

  const prevPage = (): void => changePage(currentPage - 1);

  const nextPage = (): void => changePage(currentPage + 1);

  return (
    <StyledPagination className={classes?.root} {...props}>
      <ArrowButton
        className={classes?.arrowButton}
        clickHandler={prevPage}
        disabled={currentPage === 1}
      >
        <PaginationArrow />
      </ArrowButton>

      {calculatePaginationRange().map(
        (page: number | string, index: number) => {
          if (typeof page === "number")
            return (
              <PageButton
                className={classes?.pageButton}
                key={index}
                active={currentPage === page}
                clickHandler={() => changePage(page)}
              >
                {page}
              </PageButton>
            );
          else
            return (
              <Dots className={classes?.dots} key={index}>
                {page}
              </Dots>
            );
        }
      )}

      <ArrowButton
        clickHandler={nextPage}
        disabled={currentPage === pageCount}
        className={classes?.arrowButton}
      >
        <PaginationArrow style={{ transform: "rotate(180deg)" }} />
      </ArrowButton>
    </StyledPagination>
  );
};

export default Pagination;
