import React from "react";
import { StyleProp, TextStyle, ViewStyle } from "react-native";

import { Button } from "../Button";
import { Icon } from "../Icon";
import { Stack } from "../Stack";
import styles from "./styles";

type Props = {
  count: number; // total pages
  rangeSize?: number; // number of pages to show
  selected: number;
  previousIcon?: React.ReactNode;
  nextIcon?: React.ReactNode;
  buttonStyle?: StyleProp<ViewStyle>;
  selectedButtonStyle?: StyleProp<ViewStyle>;
  buttonTextStyle?: StyleProp<TextStyle>;
  onPageChange: (index: number) => void;
};

const Pagination = ({
  count,
  selected,
  rangeSize = 4,
  buttonStyle,
  buttonTextStyle,
  selectedButtonStyle,
  previousIcon = <Icon name="caret-left" />,
  nextIcon = <Icon name="caret-right" />,
  onPageChange,
}: Props) => {
  const pages = [];
  const getPageButton = (index) => (
    <Button
      key={index}
      title={index + 1}
      style={[
        styles.button,
        buttonStyle,
        index === selected ? [styles.selected, selectedButtonStyle] : {},
      ]}
      textStyle={[styles.buttonText, buttonTextStyle]}
      onPress={() => onPageChange(index)}
    />
  );
  const jumpBack = () => {
    const newIndex = selected - rangeSize;
    return newIndex < 0 ? 0 : newIndex;
  };

  const jumpForward = () => {
    const newIndex = selected + rangeSize;
    return newIndex >= count ? count - 1 : newIndex;
  };

  const clickGap = (clickedIndex) => {
    onPageChange(selected < clickedIndex ? jumpForward() : jumpBack());
  };

  if (selected > 0) {
    pages.push(
      <Button
        key="Previous"
        style={[styles.button, buttonStyle]}
        onPress={() => onPageChange(selected - 1)}
        accessibilityLabel="Previous"
      >
        {previousIcon}
      </Button>
    );
  }
  if (count <= rangeSize) {
    for (let index = 0; index < count; index++) {
      pages.push(getPageButton(index));
    }
  } else {
    let rangeStart = rangeSize / 2;
    let rangeEnd = rangeSize - rangeStart;

    if (selected > count - rangeSize / 2) {
      rangeEnd = count - selected;
      rangeStart = rangeSize - rangeEnd;
    } else if (selected < rangeSize / 2) {
      rangeStart = selected;
      rangeEnd = rangeSize - rangeStart;
    }
    let page;
    let gapView;
    for (let index = 0; index < count; index++) {
      page = index + 1;

      if (page <= 1) {
        pages.push(getPageButton(index));
        continue;
      }
      if (page > count - 1) {
        pages.push(getPageButton(index));
        continue;
      }
      if (index >= selected - rangeStart && index <= selected + rangeEnd) {
        pages.push(getPageButton(index));
        continue;
      }
      if (pages[pages.length - 1] !== gapView) {
        gapView = (
          <Button
            key={"gap" + index}
            title="…"
            style={[styles.button, buttonStyle]}
            textStyle={[styles.buttonText, buttonTextStyle]}
            onPress={() => clickGap(index)}
          />
        );
        pages.push(gapView);
      }
    }
  }
  if (selected < count - 1) {
    pages.push(
      <Button
        key="Next"
        style={[styles.button, buttonStyle]}
        onPress={() => onPageChange(selected + 1)}
        accessibilityLabel="Next"
      >
        {nextIcon}
      </Button>
    );
  }

  return (
    pages.length > 1 && (
      <Stack inline align="center" justify="center" py={2} gap={4}>
        {pages}
      </Stack>
    )
  );
};

export default Pagination;
