import { React, PropTypes, classnames, ReactPaginate } from '@gravityforms/libraries';
import { spacerClasses, deepMerge } from '@gravityforms/utils';

const { forwardRef } = React;

/**
 * @constant
 * @type {object}
 * @description Default props for the ReactPagination component.
 *
 * @since 3.3.0
 *
 * @property {string}          activeClassName        The classname for the active page. It is concatenated to base class pageClassName.
 * @property {string}          activeLinkClassName    The classname for the active page link. It is concatenated to base class pageLinkClassName.
 * @property {string}          breakAriaLabels        Aria labels of ellipsis elements (Default are { forward: 'Jump forward', backward: 'Jump backward' }).
 * @property {string}          breakClassName         The classname on tag li of the ellipsis element.
 * @property {string}          breakLabel             The label of the ellipsis element.
 * @property {string}          breakLinkClassName     The classname on tag a of the ellipsis element.
 * @property {string}          className              The classname for the pagination container.
 * @property {string}          disabledClassName      The classname for disabled previous and next buttons.
 * @property {string}          disabledLinkClassName  The classname on tag a for disabled previous and next buttons.
 * @property {boolean}         disableInitialCallback Disable onPageChange callback with initial page. Default: false
 * @property {boolean}         hrefAllControls        By default the hrefBuilder add href only to active controls. Set this prop to true so href are generated on all controls.
 * @property {number}          initialPage            The initial page selected when the component is first mounted.
 * @property {number}          marginPagesDisplayed   The number of pages to display for margins.
 * @property {string}          nextAriaLabel          The aria label for the next button.
 * @property {string}          nextClassName          The classname on tag li of the next button.
 * @property {string}          nextLabel              The label for the next button.
 * @property {string}          nextLinkClassName      The classname on tag a of the next button.
 * @property {string}          nextPageRel            The rel property on the a tag just before the selected page. Default value prev. Set to null to disable.
 * @property {string}          nextRel                The rel propery on the a tag for the next page control. Default value next. Set to null to disable.
 * @property {string}          pageClassName          The classname on tag li of each page element.
 * @property {number}          pageCount              The total number of pages.
 * @property {string}          pageLinkClassName      The classname on tag a of each page element.
 * @property {number}          pageRangeDisplayed     The number of pages to display for margins.
 * @property {string}          previousAriaLabel      The aria label for the previous button.
 * @property {string}          previousClassName      The classname on tag li of the previous button.
 * @property {string}          previousLabel          The label for the previous button.
 * @property {string}          previousLinkClassName  The classname on tag a of the previous button.
 * @property {string}          prevPageRel            The rel property on the a tag just before the selected page. Default value prev. Set to null to disable.
 * @property {string}          prevRel                The rel property on the a tag for the previous page control. Default value prev. Set to null to disable.
 * @property {Function | null} renderOnZeroPageCount  Render component even with zero pages. Default: undefined
 * @property {string}          selectedPageRel        The rel property on the a tag for the selected page. Default value null. Set to null to disable.
 */
const defaultPaginationProps = {
	activeClassName: 'gform-pagination__item--selected',
	activeLinkClassName: 'gform-pagination__link--selected',
	breakAriaLabels: {
		forward: 'Jump forward',
		backward: 'Jump backward',
	},
	breakClassName: 'gform-pagination__item--break',
	breakLabel: '...',
	breakLinkClassName: 'gform-pagination__link--break',
	className: 'gform-pagination',
	disabledClassName: 'gform-pagination__item--disabled',
	disabledLinkClassName: 'gform-pagination__link--disabled',
	disableInitialCallback: false,
	eventListener: 'onClick',
	hrefAllControls: false,
	initialPage: 0,
	marginPagesDisplayed: 1,
	nextAriaLabel: 'Next page',
	nextClassName: 'gform-pagination__item--next',
	nextLinkClassName: 'gform-pagination__link--next',
	nextLabel: 'Next',
	nextPageRel: 'next',
	nextRel: 'next',
	pageClassName: 'gform-pagination__item',
	pageCount: 0,
	pageLinkClassName: 'gform-pagination__link',
	pageRangeDisplayed: 1,
	previousAriaLabel: 'Previous page',
	previousClassName: 'gform-pagination__item--previous',
	previousLabel: 'Previous',
	previousLinkClassName: 'gform-pagination__link--previous',
	prevPageRel: 'prev',
	prevRel: 'prev',
	renderOnZeroPageCount: undefined,
	selectedPageRel: 'canonical',
};

/**
 * @module Pagination
 * @description Renders a pagination component.
 *
 * @since 3.3.0
 *
 * @param {object}                     props                  Component props.
 * @param {object}                     props.customAttributes Custom attributes for the component
 * @param {string|Array|object}        props.customClasses    Custom classes for the component.
 * @param {object}                     props.paginationProps  Props for the pagination component.
 * @param {string|number|Array|object} props.spacing          The spacing for the component, as a string, number, array, or object.
 * @param {object|null}                ref                    Ref to the component.
 *
 * @return {JSX.Element} The pagination component.
 *
 * @example
 * import Pagination from '@gravityforms/components/react/admin/modules/Pagination';
 *
 * return <Pagination />;
 *
 */
const Pagination = forwardRef( ( {
	customAttributes = {},
	customClasses = [],
	paginationProps = {},
	spacing = '',
}, ref ) => {
	const componentProps = {
		className: classnames( {
			'gform-pagination': true,
			...spacerClasses( spacing ),
		}, customClasses ),
		ref,
		...customAttributes,
	};
	const mergedPaginationProps = deepMerge( defaultPaginationProps, paginationProps );

	// do not pass both force page and initial page, against paginate rules
	if ( ! isNaN( mergedPaginationProps.forcePage ) && ! isNaN( mergedPaginationProps.initialPage ) ) {
		delete mergedPaginationProps.initialPage;
	}

	return <ReactPaginate { ...mergedPaginationProps } { ...componentProps } />;
} );

Pagination.propTypes = {
	customAttributes: PropTypes.object,
	customClasses: PropTypes.oneOfType( [
		PropTypes.string,
		PropTypes.array,
		PropTypes.object,
	] ),
	paginationProps: PropTypes.object,
	spacing: PropTypes.oneOfType( [
		PropTypes.string,
		PropTypes.number,
		PropTypes.array,
		PropTypes.object,
	] ),
};

Pagination.displayName = 'Pagination';

export default Pagination;
