/**
 * External dependencies
 */
import { __, sprintf } from '@wordpress/i18n';
import classNames from 'classnames';
import { Label } from '@woocommerce/blocks-components';

/**
 * Internal dependencies
 */
import { getIndexes } from './utils';
import './style.scss';

interface PaginationProps {
	/**
	 * Number of the page currently being displayed.
	 */
	currentPage: number;
	/**
	 * Total number of pages.
	 */
	totalPages: number;
	/**
	 * Displays first and last pages if they are not in the current range of pages displayed.
	 */
	displayFirstAndLastPages?: boolean;
	/**
	 * Displays arrows to navigate to the previous and next pages.
	 */
	displayNextAndPreviousArrows?: boolean;
	/**
	 * Callback function called when the user triggers a page change.
	 */
	onPageChange: ( currentPage: number ) => void;
	/**
	 * Number of pages to display at the same time, including the active page
	 * and the pages displayed before and after it. It doesn't include the first
	 * and last pages.
	 */
	pagesToDisplay?: number;
}

const Pagination = ( {
	currentPage,
	displayFirstAndLastPages = true,
	displayNextAndPreviousArrows = true,
	pagesToDisplay = 3,
	onPageChange,
	totalPages,
}: PaginationProps ): JSX.Element => {
	let { minIndex, maxIndex } = getIndexes(
		pagesToDisplay,
		currentPage,
		totalPages
	);

	const showFirstPage = displayFirstAndLastPages && Boolean( minIndex !== 1 );
	const showLastPage =
		displayFirstAndLastPages && Boolean( maxIndex !== totalPages );
	const showFirstPageEllipsis =
		displayFirstAndLastPages && Boolean( minIndex && minIndex > 3 );
	const showLastPageEllipsis =
		displayFirstAndLastPages &&
		Boolean( maxIndex && maxIndex < totalPages - 2 );

	// Handle the cases where there would be an ellipsis replacing one single page
	if ( showFirstPage && minIndex === 3 ) {
		minIndex = minIndex - 1;
	}
	if ( showLastPage && maxIndex === totalPages - 2 ) {
		maxIndex = maxIndex + 1;
	}

	const pages = [];
	if ( minIndex && maxIndex ) {
		for ( let i = minIndex; i <= maxIndex; i++ ) {
			pages.push( i );
		}
	}

	return (
		<div className="wc-block-pagination wc-block-components-pagination">
			<Label
				screenReaderLabel={ __(
					'Navigate to another page',
					'woo-gutenberg-products-block'
				) }
			/>
			{ displayNextAndPreviousArrows && (
				<button
					className="wc-block-pagination-page wc-block-components-pagination__page wc-block-components-pagination-page--arrow"
					onClick={ () => onPageChange( currentPage - 1 ) }
					title={ __(
						'Previous page',
						'woo-gutenberg-products-block'
					) }
					disabled={ currentPage <= 1 }
				>
					<Label
						label="&larr;"
						screenReaderLabel={ __(
							'Previous page',
							'woo-gutenberg-products-block'
						) }
					/>
				</button>
			) }
			{ showFirstPage && (
				<button
					className={ classNames(
						'wc-block-pagination-page',
						'wc-block-components-pagination__page',
						{
							'wc-block-pagination-page--active':
								currentPage === 1,
							'wc-block-components-pagination__page--active':
								currentPage === 1,
						}
					) }
					onClick={ () => onPageChange( 1 ) }
					disabled={ currentPage === 1 }
				>
					<Label
						label={ '1' }
						screenReaderLabel={ sprintf(
							/* translators: %d is the page number (1, 2, 3...). */
							__( 'Page %d', 'woo-gutenberg-products-block' ),
							1
						) }
					/>
				</button>
			) }
			{ showFirstPageEllipsis && (
				<span
					className="wc-block-pagination-ellipsis wc-block-components-pagination__ellipsis"
					aria-hidden="true"
				>
					{ __( '…', 'woo-gutenberg-products-block' ) }
				</span>
			) }
			{ pages.map( ( page ) => {
				return (
					<button
						key={ page }
						className={ classNames(
							'wc-block-pagination-page',
							'wc-block-components-pagination__page',
							{
								'wc-block-pagination-page--active':
									currentPage === page,
								'wc-block-components-pagination__page--active':
									currentPage === page,
							}
						) }
						onClick={
							currentPage === page
								? undefined
								: () => onPageChange( page )
						}
						disabled={ currentPage === page }
					>
						<Label
							label={ page.toString() }
							screenReaderLabel={ sprintf(
								/* translators: %d is the page number (1, 2, 3...). */
								__( 'Page %d', 'woo-gutenberg-products-block' ),
								page
							) }
						/>
					</button>
				);
			} ) }
			{ showLastPageEllipsis && (
				<span
					className="wc-block-pagination-ellipsis wc-block-components-pagination__ellipsis"
					aria-hidden="true"
				>
					{ __( '…', 'woo-gutenberg-products-block' ) }
				</span>
			) }
			{ showLastPage && (
				<button
					className={ classNames(
						'wc-block-pagination-page',
						'wc-block-components-pagination__page',
						{
							'wc-block-pagination-page--active':
								currentPage === totalPages,
							'wc-block-components-pagination__page--active':
								currentPage === totalPages,
						}
					) }
					onClick={ () => onPageChange( totalPages ) }
					disabled={ currentPage === totalPages }
				>
					<Label
						label={ totalPages.toString() }
						screenReaderLabel={ sprintf(
							/* translators: %d is the page number (1, 2, 3...). */
							__( 'Page %d', 'woo-gutenberg-products-block' ),
							totalPages
						) }
					/>
				</button>
			) }
			{ displayNextAndPreviousArrows && (
				<button
					className="wc-block-pagination-page wc-block-components-pagination__page wc-block-components-pagination-page--arrow"
					onClick={ () => onPageChange( currentPage + 1 ) }
					title={ __( 'Next page', 'woo-gutenberg-products-block' ) }
					disabled={ currentPage >= totalPages }
				>
					<Label
						label="&rarr;"
						screenReaderLabel={ __(
							'Next page',
							'woo-gutenberg-products-block'
						) }
					/>
				</button>
			) }
		</div>
	);
};

export default Pagination;
