/**
 * SaveButton component
 *
 * Shows an adjacent notice with the result of the save operation.
 *
 * @since   1.0.0
 * @author  StudioPress
 * @license GPL-2.0-or-later
 */

/**
 * WordPress dependencies
 */
import { speak } from '@wordpress/a11y';
import { Button } from '@wordpress/components';
import { dispatch, withSelect } from '@wordpress/data';
import { compose } from '@wordpress/compose';
import { useRef } from '@wordpress/element';
import { doAction } from '@wordpress/hooks';

function SaveButtonComponent( {
	form,
	settings,
	custom,
	children,
	successMessage,
	failMessage,
	messageDuration,
} ) {
	// Reference to the message timer that persists across re-renders.
	const messageTimerRef = useRef();

	/**
	 * Saves the current settings state to the database.
	 */
	function saveSettings() {
		doAction( 'genesisBlocks.savingSettings', settings, custom );
		clearTimeout( messageTimerRef.current ); // Existing timers must not remove new messages prematurely.
		dispatch( 'genesis-blocks/global-settings' ).saveSettings( settings );
	}

	/**
	 * Shows a success or failure message.
	 *
	 * Speaks successMessage or failureMessage text, then resets the form state
	 * in the Genesis Blocks data store after messageDuration.
	 */
	function showMessage() {
		messageTimerRef.current = setTimeout(
			() =>
				dispatch(
					'genesis-blocks/global-settings'
				).resetFormSaveState(),
			messageDuration * 1000
		);

		const message = form.success ? successMessage : failMessage;

		speak( message, 'polite' );

		const classes =
			'genesis-blocks-save-notice' +
			`${ form.success ? ' success' : '' }` +
			`${ form.fail ? ' fail' : '' }`;

		return <span className={ classes }>{ message }</span>;
	}

	return (
		<>
			<Button
				isPrimary
				isBusy={ form.is_saving }
				disabled={ form.is_saving }
				onClick={ saveSettings }
				className="genesis-blocks-settings-save has-notices"
			>
				{ children }
			</Button>
			{ form.success || form.fail ? showMessage() : '' }
		</>
	);
}

export const SaveButton = compose( [
	withSelect( ( select ) => ( {
		form: select( 'genesis-blocks/global-settings' ).getFormInfo(),
		settings: select(
			'genesis-blocks/global-settings'
		).getModifiedSettings(),
		custom: select( 'genesis-blocks/global-settings' ).getCustom(),
	} ) ),
] )( SaveButtonComponent );
