import { React, PropTypes, classnames } from '@gravityforms/libraries';
import { sprintf } from '@gravityforms/utils';
import Calendar from '../../Calendar';
import { DATE_KEY, getModules } from '../utils';

const { forwardRef } = React;

/**
 * @module DateFilters
 * @description The DateFilters module.
 *
 * @since 5.1.0
 *
 * @param {object}      props                   The component props.
 * @param {boolean}     props.isLoading         Whether the component is loading.
 * @param {Array}       props.modules           The list of modules.
 * @param {object}      props.moduleAttributes  The module attributes.
 * @param {object}      props.moduleState       The module state.
 * @param {Function}    props.setIsLoading      Set the loading state of the component.
 * @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 DateFilters component.
 */
const DateFilters = forwardRef( ( {
	isLoading = false,
	modules = [],
	moduleAttributes = {},
	moduleState = {},
	setIsLoading = () => {},
	updateModuleState = () => {},
	useAjax = false,
}, ref ) => {
	const {
		calendarAttributes = {},
		customClasses = [],
		dateFormatOptions = {
			day: 'numeric',
			month: 'short',
			year: 'numeric',
		},
		onChange = () => {},
		triggerAttributes: {
			ariaText = '',
			...restTriggerAttributes
		} = {},
		i18n: {
			pillLabel: pillLabelI18n = 'Date: %s',
		} = {},
		...restDateFilterAttributes
	} = moduleAttributes?.dateFilters || {};
	const { filters = [], dateFilters = [] } = moduleState;
	const hasFilter = dateFilters.length > 0;
	const updatedAriaText = dateFilters.length ? sprintf( ariaText, dateFilters[ 0 ], dateFilters[ 1 ] ) : '';

	const calendarProps = {
		calendarAttributes: {
			onChange: ( value ) => {
				// Return early if not using AJAX.
				if ( ! useAjax ) {
					return;
				}
				// Return early if already loading.
				if ( isLoading ) {
					return;
				}

				const { BulkActions, GridPagination, SimpleFilters } = getModules( modules, [ 'BulkActions', 'GridPagination', 'SimpleFilters' ] );
				const updatedState = {
					dateFilters: value,
					...( ( SimpleFilters && { filters: SimpleFilters?.getUpdatedFilters( filters, DATE_KEY, value, pillLabelI18n, dateFormatOptions ) } ) || {} ),
					...( ( BulkActions && BulkActions?.getDefaultState() ) || {} ),
					...( ( GridPagination && GridPagination?.getDefaultState() ) || {} ),
				};
				const combinedState = { ...moduleState, ...updatedState };
				setIsLoading( true );
				onChange( combinedState )
					.then( () => {
						setIsLoading( false );
						updateModuleState( updatedState );
					} )
					.catch( ( error ) => {
						// handle error.
						setIsLoading( false );
						console.info( error );
					} );
			},
			selectRange: true,
			value: dateFilters,
			...calendarAttributes,
		},
		customClasses: classnames(
			'gform-data-grid__controls-date-filters-calendar',
			customClasses,
		),
		showResetButton: true,
		triggerAttributes: {
			ariaText: updatedAriaText,
			...restTriggerAttributes,
		},
		withTrigger: true,
		...restDateFilterAttributes,
	};
	const componentProps = {
		className: classnames( {
			'gform-data-grid__controls-date-filters': true,
			'gform-data-grid__controls-date-filters--has-filter': hasFilter,
		} ),
	};

	return (
		<div { ...componentProps } ref={ ref }>
			<Calendar { ...calendarProps } />
		</div>
	);
} );

DateFilters.propTypes = {
	isLoading: PropTypes.bool,
	modules: PropTypes.array,
	moduleAttributes: PropTypes.object,
	moduleState: PropTypes.object,
	setIsLoading: PropTypes.func,
	updateModuleState: PropTypes.func,
};

DateFilters.displayName = 'DateFilters';

/**
 * @function getDefaultState
 * @description Returns the default state.
 *
 * @since 5.1.0
 *
 * @return {object} The default state.
 */
const getDefaultState = () => ( {
	dateFilters: [],
} );

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