import { React, PropTypes } from '@gravityforms/libraries';
import PaginationModule from '../../Pagination';
import { getModules } from '../utils';

const { forwardRef } = React;

/**
 * @module Pagination
 * @description The Pagination component for the DataGrid.
 *
 * @since 4.3.0
 *
 * @param {object}      props                   Component props.
 * @param {number}      props.dataPerPage       The number of data rows to show per page.
 * @param {boolean}     props.isLoading         Whether the data grid is loading.
 * @param {Array}       props.modules           The modules for the data grid.
 * @param {object}      props.moduleAttributes  The module attributes.
 * @param {object}      props.moduleState       The module state.
 * @param {Function}    props.setIsLoading      Set the loading state of the data grid.
 * @param {Array}       props.sortedData        The sorted data.
 * @param {Function}    props.updateModuleState Update the module state.
 * @param {boolean}     props.useAjax           Whether to use ajax.
 * @param {object|null} ref                     Ref to the component.
 *
 * @return {JSX.Element} The Pagination component.
 */
const Pagination = forwardRef( ( {
	dataPerPage = 20,
	isLoading = false,
	modules = [],
	moduleAttributes = {},
	moduleState = {},
	setIsLoading = () => {},
	sortedData = [],
	updateModuleState = () => {},
	useAjax = false,
}, ref ) => {
	const {
		onClick = () => {},
		onPageChange = () => {},
		pageCount = 0,
		...restAttributes
	} = moduleAttributes?.pagination || {};

	const paginationProps = {
		...restAttributes,
	};

	if ( useAjax ) {
		if ( onClick ) {
			paginationProps.onPageChange = onPageChange;
			paginationProps.onClick = ( clickData ) => {
				// Next selected page must be defined.
				if ( ! Number.isInteger( clickData.nextSelectedPage ) || isLoading ) {
					return false;
				}

				const { BulkActions } = getModules( modules, [ 'BulkActions' ] );
				const updatedState = {
					currentPage: clickData.nextSelectedPage,
					...( ( BulkActions && BulkActions?.getDefaultState() ) || {} ),
				};
				const combinedState = { ...moduleState, ...updatedState };
				setIsLoading( true );
				onClick( combinedState )
					.then( () => {
						setIsLoading( false );
						updateModuleState( updatedState );
					} )
					.catch( ( error ) => {
						// handle error.
						setIsLoading( false );
						console.info( error );
					} );

				return false;
			};
			paginationProps.forcePage = moduleState?.currentPage;
			if ( Number.isInteger( pageCount ) ) {
				paginationProps.pageCount = pageCount;
			}
		}
	} else {
		paginationProps.onPageChange = ( data ) => {
			updateModuleState( {
				currentPage: data.selected,
			} );
			onPageChange( data );
		};
		paginationProps.pageCount = Math.ceil( sortedData.length / dataPerPage );
	}

	return (
		<div className="gform-data-grid__pagination" data-testid="data-grid-pagination" ref={ ref }>
			<PaginationModule paginationProps={ paginationProps } />
		</div>
	);
} );

Pagination.propTypes = {
	dataPerPage: PropTypes.number,
	isLoading: PropTypes.bool,
	modules: PropTypes.array,
	moduleAttributes: PropTypes.object,
	moduleState: PropTypes.object,
	setIsLoading: PropTypes.func,
	sortedData: PropTypes.array,
	updateModuleState: PropTypes.func,
	useAjax: PropTypes.bool,
};

Pagination.displayName = 'Pagination';

/**
 * @function getDefaultState
 * @description Get the default state for the Pagination module.
 *
 * @since 4.3.0
 *
 * @return {object} The default state.
 */
const getDefaultState = () => ( {
	currentPage: 0,
} );

export default {
	name: 'Pagination',
	Pagination,
	getDefaultState,
};
