/**
 * RSM suite Gutenberg block preview + canvas layout helpers.
 *
 * @package Rsmspark_Suite
 */
( function ( wp ) {
	'use strict';

	if ( ! wp || ! wp.element || ! wp.blocks ) {
		return;
	}

	var el = wp.element.createElement;
	var Fragment = wp.element.Fragment;
	var useState = wp.element.useState;
	var useEffect = wp.element.useEffect;
	var useRef = wp.element.useRef;
	var useSelect = wp.data && wp.data.useSelect;
	var useBlockProps = wp.blockEditor && wp.blockEditor.useBlockProps;
	var useBlockEditContext = wp.blockEditor && wp.blockEditor.useBlockEditContext;
	var ServerSideRender = null;
	if ( wp.serverSideRender ) {
		if ( typeof wp.serverSideRender === 'function' ) {
			ServerSideRender = wp.serverSideRender;
		} else if ( typeof wp.serverSideRender.default === 'function' ) {
			ServerSideRender = wp.serverSideRender.default;
		}
	}
	var Spinner = wp.components && wp.components.Spinner;
	var Button = wp.components && wp.components.Button;
	var __ = wp.i18n && wp.i18n.__;

	var branding = window.RSMBlockBranding || {};
	var CATEGORY_SLUG = branding.CATEGORY_SLUG || 'rsm-spark';
	var CATEGORY_TITLE = branding.CATEGORY_TITLE || 'RSM Spark';
	var BRAND_ORANGE = branding.BRAND_ORANGE || '#FF6B35';

	function t( text, fallback, domain ) {
		return __ ? __( text, domain || 'rsmspark-suite' ) : fallback;
	}

	function brandButtonClass( variant, extra ) {
		var classes = [ 'rsmspark-block-editor__button' ];
		if ( variant === 'primary' ) {
			classes.push( 'rsmspark-block-editor__button--brand' );
		} else if ( variant === 'secondary' ) {
			classes.push( 'rsmspark-block-editor__button--brand-secondary' );
		}
		if ( extra ) {
			classes.push( extra );
		}
		return classes.join( ' ' );
	}

	function DebouncedServerSideRender( props ) {
		var block = props.block;
		var attributes = props.attributes || {};
		var debounced = useState( attributes );
		var debouncedAttrs = debounced[ 0 ];
		var setDebouncedAttrs = debounced[ 1 ];

		useEffect(
			function () {
				var timer = window.setTimeout( function () {
					setDebouncedAttrs( attributes );
				}, props.debounceMs || 450 );
				return function () {
					window.clearTimeout( timer );
				};
			},
			[ attributes ]
		);

		if ( ! ServerSideRender ) {
			return el(
				'p',
				{ className: 'rsmspark-block-preview__error' },
				t( 'previewUnavailable', 'Preview unavailable.' )
			);
		}

		return el( ServerSideRender, {
			block: block,
			attributes: debouncedAttrs,
			httpMethod: 'POST',
			urlQueryArgs: props.urlQueryArgs,
			LoadingResponsePlaceholder: function () {
				return el(
					'div',
					{ className: 'rsmspark-block-preview__loading' },
					Spinner ? el( Spinner, null ) : null,
					el(
						'span',
						null,
						t( 'previewLoading', 'Loading preview…' )
					)
				);
			},
			ErrorResponsePlaceholder: function ( errorProps ) {
				var raw =
					( errorProps && errorProps.error ) ||
					( errorProps && errorProps.response );
				var message =
					typeof raw === 'string'
						? raw
						: raw && raw.message
							? raw.message
							: t( 'previewError', 'Preview could not be loaded.' );
				return el(
					'div',
					{ className: 'rsmspark-block-preview__error' },
					el( 'p', null, String( message ) )
				);
			},
			EmptyResponsePlaceholder: function () {
				return el(
					'div',
					{ className: 'rsmspark-block-preview__empty' },
					el(
						'p',
						null,
						t(
							'previewEmpty',
							'No preview output. Check block settings.'
						)
					)
				);
			},
		} );
	}

	function blockCanvasPreview( blockName, attributes, compact ) {
		return el(
			'div',
			{
				className:
					'rsmspark-block-preview' +
					( compact ? ' rsm-block-preview--compact' : '' ),
			},
			compact
				? null
				: el(
						'p',
						{ className: 'rsmspark-block-preview__heading' },
						t( 'preview', 'Preview' )
				  ),
			el( DebouncedServerSideRender, {
				block: blockName,
				attributes: attributes,
				debounceMs: compact ? 200 : 450,
				urlQueryArgs: compact ? { rsm_inserter_preview: '1' } : undefined,
			} ),
			compact
				? null
				: el(
						'p',
						{
							className:
								'rsmspark-block-preview__hint description',
						},
						t(
							'previewFrontEndHint',
							'Save and use View / Preview on the front end if this looks wrong.'
						)
				  )
		);
	}

	function wrapInserterPreview( blockName, Edit ) {
		if ( ! Edit ) {
			return Edit;
		}
		return function ( props ) {
			var context =
				typeof useBlockEditContext === 'function'
					? useBlockEditContext()
					: {};
			if ( context.isBlockPreview ) {
				return blockCanvasPreview( blockName, props.attributes, true );
			}
			return el( Edit, props );
		};
	}

	function blockEditLayout( config ) {
		var previewState = useState( false );
		var isPreviewOnly = previewState[ 0 ];
		var setPreviewOnly = previewState[ 1 ];
		var clientId = config.clientId;
		var blockName = config.blockName;
		var attributes = config.attributes;
		var previewDisabled = config.previewDisabled;
		var previewDisabledMessage = config.previewDisabledMessage;
		var children = config.children;
		var className = config.className || '';

		var blockProps = useBlockProps
			? useBlockProps( {
					className:
						'rsmspark-block-editor-wrap' +
						( className ? ' ' + className : '' ) +
						( isPreviewOnly
							? ' rsm-block-editor-wrap--preview-only'
							: '' ),
			  } )
			: {
					className:
						'rsmspark-block-editor-wrap' +
						( className ? ' ' + className : '' ),
			  };

		var isSelected = useSelect(
			function ( select ) {
				if ( ! clientId || ! select ) {
					return true;
				}
				try {
					return !! select( 'core/block-editor' ).isBlockSelected(
						clientId
					);
				} catch ( e ) {
					return true;
				}
			},
			[ clientId ]
		);

		var wasSelectedRef = useRef( isSelected );

		useEffect(
			function () {
				if ( isSelected && ! wasSelectedRef.current ) {
					setPreviewOnly( false );
				}
				if ( ! isSelected && wasSelectedRef.current ) {
					setPreviewOnly( true );
				}
				wasSelectedRef.current = isSelected;
			},
			[ isSelected ]
		);

		function enterPreviewMode( event ) {
			if ( event ) {
				event.stopPropagation();
			}
			setPreviewOnly( true );
		}

		function returnToEditMode( event ) {
			if ( event ) {
				event.stopPropagation();
			}
			setPreviewOnly( false );
		}

		if ( isPreviewOnly && ! isSelected && blockName && ! previewDisabled ) {
			return el(
				'div',
				Object.assign( {}, blockProps, {
					onClick: returnToEditMode,
					onKeyDown: function ( event ) {
						if ( event.key === 'Enter' || event.key === ' ' ) {
							event.preventDefault();
							returnToEditMode( event );
						}
					},
					role: 'button',
					tabIndex: 0,
					'aria-label': t(
						'returnToBlockSettings',
						'Return to block settings'
					),
				} ),
				el(
					'p',
					{ className: 'rsmspark-block-editor-wrap__preview-only-hint' },
					t(
						'clickBlockToEdit',
						'Click the block to edit settings.'
					)
				),
				blockCanvasPreview( blockName, attributes, false )
			);
		}

		var childNodes = Array.isArray( children ) ? children : [ children ];

		return el.apply(
			el,
			[
				'div',
				blockProps,
			]
				.concat( childNodes )
				.concat(
					blockName && ! previewDisabled
						? [
								el(
									'div',
									{
										className:
											'rsmspark-block-editor-wrap__preview-actions',
									},
									el(
										Button || 'button',
										Button
											? {
													variant: 'primary',
													className: brandButtonClass(
														'primary',
														'rsmspark-block-editor-wrap__preview-button'
													),
													onClick: enterPreviewMode,
											  }
											: {
													type: 'button',
													className:
														'rsmspark-block-editor-wrap__preview-button button button-primary',
													onClick: enterPreviewMode,
											  },
										t( 'previewBlock', 'Preview' )
									)
								),
						  ]
						: previewDisabled
							? [
									el(
										'p',
										{
											className:
												'rsmspark-block-editor-wrap__preview-disabled',
										},
										previewDisabledMessage ||
											t(
												'previewUnavailableUntilConfigured',
												'Configure the block above to see a live preview.'
											)
									),
							  ]
							: []
				)
		);
	}

	function inspectorAndPreview( blockName, inspector, attributes, clientId ) {
		return el(
			Fragment,
			{},
			inspector,
			blockEditLayout( {
				blockName: blockName,
				attributes: attributes,
				clientId: clientId,
				children: blockCanvasPreview( blockName, attributes, false ),
			} )
		);
	}

	function stringifySelectOptions( options ) {
		return ( options || [] ).map( function ( opt ) {
			return {
				label: opt.label,
				value: String(
					opt.value !== undefined && opt.value !== null
						? opt.value
						: ''
				),
			};
		} );
	}

	function embedSourcePicker( config ) {
		var SelectControl = wp.components && wp.components.SelectControl;
		if ( ! SelectControl ) {
			return null;
		}
		var compact = !! config.compact;
		var pickerClass =
			'rsmspark-block-embed-picker' +
			( compact ? ' rsm-block-embed-picker--compact' : '' );
		var children = [];
		if ( ! compact && config.lead ) {
			children.push(
				el( 'p', { className: 'rsmspark-block-embed-picker__lead' }, config.lead )
			);
		}
		children.push(
			el( SelectControl, {
				label: config.label || '',
				help: config.help || '',
				value: String(
					config.value !== undefined && config.value !== null
						? config.value
						: 0
				),
				options: stringifySelectOptions( config.options || [] ),
				onChange: function ( next ) {
					if ( typeof config.onChange === 'function' ) {
						config.onChange( parseInt( next, 10 ) || 0 );
					}
				},
			} )
		);
		return el.apply( el, [ 'div', { className: pickerClass } ].concat( children ) );
	}

	function embedEditorShell( blockEditorApi, inspector, bodyChildren, layoutConfig ) {
		layoutConfig = layoutConfig || {};
		var body = Array.isArray( bodyChildren ) ? bodyChildren : [ bodyChildren ];

		return el(
			Fragment,
			{},
			inspector,
			blockEditLayout(
				Object.assign( {}, layoutConfig, {
					children: body,
				} )
			)
		);
	}

	window.RSMBlockPreview = {
		BRAND_ORANGE: BRAND_ORANGE,
		CATEGORY_SLUG: CATEGORY_SLUG,
		CATEGORY_TITLE: CATEGORY_TITLE,
		brandButtonClass: brandButtonClass,
		blockCanvasPreview: blockCanvasPreview,
		blockEditLayout: blockEditLayout,
		wrapInserterPreview: wrapInserterPreview,
		inspectorAndPreview: inspectorAndPreview,
		DebouncedServerSideRender: DebouncedServerSideRender,
		stringifySelectOptions: stringifySelectOptions,
		embedSourcePicker: embedSourcePicker,
		embedEditorShell: embedEditorShell,
	};
} )( window.wp );
