( function( wp ) {

	const __ = wp.i18n.__;
	const createHigherOrderComponent = wp.compose.createHigherOrderComponent;
	const Fragment = wp.element.Fragment;
	const InspectorControls = wp.blockEditor.InspectorControls;
	const PanelBody = wp.components.PanelBody;
	const ToggleControl = wp.components.ToggleControl;
	const SelectControl = wp.components.SelectControl;
	const RangeControl = wp.components.RangeControl;
	const Button = wp.components.Button;
	const addFilter = wp.hooks.addFilter;
	const createElement = wp.element.createElement;
	const animationAllowedBlocks = [
		'core/group',
		'core/heading',
		'core/paragraph',
		'core/buttons',
		'core/button',
		'core/image',
		'core/list',
		'core/media-text',
		'core/navigation',
		'core/navigation-link',
		'core/post-author',
		'core/post-content',
		'core/post-date',
		'core/post-excerpt',
		'core/post-featured-image',
		'core/post-terms',
		'core/post-title',
		'core/query-title',
		'core/site-logo',
		'core/site-tagline',
		'core/site-title',
		'core/social-link',
		'core/term-description',
		'core/column',
		'core/columns',
		'core/list-item',
		'core/pullquote',
		'core/quote',
		'core/table',
		'core/video',
		'woocommerce/product-button',
		'woocommerce/product-image',
		'woocommerce/product-price',
		'woocommerce/product-rating',
		'woocommerce/product-sku',
		'woocommerce/product-stock-indicator',
		'woocommerce/product-summary',
		'woocommerce/product-details'
	];
	const animationAttrs = {
		acaiAnimationType: {
			type: 'string',
			default: 'none'
		},
		acaiAnimationDuration: {
			type: 'number',
			default: 1.4,
			minimum: 0.5,
			maximum: 3
		},
		acaiAnimationDelay: {
			type: 'number',
			default: 0,
			minimum: 0,
			maximum: 2
		},
		acaiAnimationOffset: {
			type: 'number',
			default: 10,
			minimum: 1,
			maximum: 20
		},
		acaiAnimationScale: {
			type: 'number',
			default: 0.1,
			minimum: 0.1,
			maximum: 0.9
		}
	};
	const balancedTextAllowedBlocks = [
		'core/heading',
		'core/paragraph',
		'core/list',
		'core/post-title',
		'core/query-title',
		'core/site-tagline',
		'core/term-description',
		'core/list-item',
		'core/pullquote',
		'core/quote',
		'woocommerce/product-summary',
		'woocommerce/product-details'
	];
	const balancedTextAttrs = {
		acaiBalancedText: {
			type: 'boolean',
			default: false
		}
	};
	const prodImgAttrs = {
		acaiExtraProductImg: {
			type: 'boolean',
			default: false
		}
	};
	const groupOverlapAttrs = {
		acaiOverlap: {
			type: 'number',
			default: 0,
			minimum: -20,
			maximum: 20
		},
		acaiOverlapMobileOff: {
			type: 'boolean',
			default: false
		}
	};
	const groupStackOrderAttrs = {
		acaiZindex: {
			type: 'number',
			default: 0,
			minimum: 0,
			maximum: 10
		}
	};
	const imgScrollAllowedBlocks = [
		'core/image',
		'core/post-featured-image',
		'core/cover',
		'woocommerce/product-image'
	];
	const imgScrollAttrs = {
		acaiImgScroll: {
			type: 'boolean',
			default: false
		}
	};

	addFilter( 'blocks.registerBlockType', 'acai-animation/add-attributes',
		function( settings ) {
			if ( !animationAllowedBlocks.includes( settings.name ) ) {
				return settings;
			}
			settings.attributes = Object.assign( settings.attributes, animationAttrs );
			return settings;
		}
	);

	addFilter( 'blocks.registerBlockType', 'acai-balanced-text/add-attributes',
		function( settings ) {
			if ( !balancedTextAllowedBlocks.includes( settings.name ) ) {
				return settings;
			}
			settings.attributes = Object.assign( settings.attributes, balancedTextAttrs );
			return settings;
		}
	);

	addFilter( 'blocks.registerBlockType', 'acai-product-image/add-attributes',
		function( settings ) {
			if ( settings.name === 'woocommerce/product-image' ) {
				settings.attributes = Object.assign( settings.attributes, prodImgAttrs );
			}
			return settings;
		}
	);

	addFilter( 'blocks.registerBlockType', 'acai-group-overlap/add-attributes',
		function( settings ) {
			if ( settings.name === 'core/group' ) {
				settings.attributes = Object.assign( settings.attributes, groupOverlapAttrs );
			}
			return settings;
		}
	);

	addFilter( 'blocks.registerBlockType', 'acai-group-zindex/add-attributes',
		function( settings ) {
			if ( settings.name === 'core/group' ) {
				settings.attributes = Object.assign( settings.attributes, groupStackOrderAttrs );
			}
			return settings;
		}
	);

	addFilter( 'blocks.registerBlockType', 'acai-image-scroll/add-attributes',
		function( settings ) {
			if ( imgScrollAllowedBlocks.includes( settings.name ) ) {
				settings.attributes = Object.assign( settings.attributes, imgScrollAttrs );
			}
			return settings;
		}
	);

	const withInspectorControlsBalancedText = createHigherOrderComponent( ( BlockEdit ) => {
		return (props) => {
			const acaiBalancedText = props.attributes.acaiBalancedText || 0;
			let panelOpen = acaiBalancedText === 0 ? false : true;
			return createElement( Fragment,
				{},
				createElement( BlockEdit, props ),
				balancedTextAllowedBlocks.includes( props.name ) && props.isSelected && createElement( InspectorControls,
					{
						group: 'styles'
					},
					createElement(
						PanelBody,
						{
							title: __( 'Balanced Text', 'acai' ),
							initialOpen: panelOpen,
							className: 'acai-balanced-text-panel'
						},
						createElement(
							ToggleControl,
							{
								label: __( 'Enable', 'acai' ),
								help: __( 'Helps improve the appearance of multi-line text by distributing words more evenly across lines. Instead of allowing one line to be much longer or shorter than the others, the browser attempts to "balance" line lengths to create a more visually pleasing and readable block of text. Especially useful for headlines and centered text. Only works with up to six wrapped lines of text.', 'acai' ),
								checked: acaiBalancedText,
								onChange: function( value ) {
									let currentClass = typeof props.attributes.className === 'undefined' ? '' : props.attributes.className;
									if ( value ) {
										var updateClass = acaiRemoveDuplicates(currentClass,'acai-balanced-text') + ' acai-balanced-text';
									} else {
										var updateClass = acaiRemoveDuplicates(currentClass,'acai-balanced-text');
									}
									updateClass = updateClass.trim();
									props.setAttributes(
										{
											acaiBalancedText: value,
											className: updateClass
										}
									);
								}
							}
						)
					)
				)
			);
		};
	}, 'withInspectorControlsBalancedText' );

	addFilter( 'editor.BlockEdit', 'acai-balanced-text/with-inspector-controls', withInspectorControlsBalancedText );

	const withInspectorControlsImgScroll = createHigherOrderComponent( ( BlockEdit ) => {
		return (props) => {
			const acaiImgHover = props.attributes.acaiImgScroll || false;
			let placeGroup = props.name === 'core/image' ? 'settings' : 'styles';
			let helpText = props.name === 'core/cover' ? __( 'The image will scroll top to bottom full height on hover. Requires an "Aspect Ratio" to be selected. Cannot be used with "Fixed background" or "Repeated background".', 'acai' ) : ( props.name === 'woocommerce/product-image' ? __( 'The image will scroll top to bottom full height on hover. Requires an "Aspect Ratio" to be selected.', 'acai' ) : __( 'The image will scroll top to bottom full height on hover. Requires an "Aspect Ratio" to be selected, and "Scale: Cover".', 'acai' ) );
			return createElement( Fragment,
				{},
				createElement( BlockEdit, props ),
				imgScrollAllowedBlocks.includes( props.name ) && props.attributes.scale !== 'contain' && props.attributes.scale !== 'fill' && !props.attributes.hasParallax && !props.attributes.isRepeated && props.isSelected && createElement( InspectorControls,
					{
						group: placeGroup
					},
					createElement(
						PanelBody,
						{
							title: __( 'Scroll Full Height', 'acai' ),
							initialOpen: true,
							className: 'acai-image-scroll-panel'
						},
						createElement(
							ToggleControl,
							{
								label: __( 'Enable on Hover', 'acai' ),
								help: helpText,
								checked: acaiImgHover,
								onChange: function( value ) {
									let currentClass = typeof props.attributes.className === 'undefined' ? '' : props.attributes.className;
									if ( value ) {
										var updateClass = acaiRemoveDuplicates(currentClass,'acai-hover-scroll') + ' acai-hover-scroll';
									} else {
										var updateClass = acaiRemoveDuplicates(currentClass,'acai-hover-scroll');
									}
									updateClass = updateClass.trim();
									props.setAttributes(
										{
											acaiImgScroll: value,
											className: updateClass
										}
									);
								}
							}
						)
					)
				)
			);
		};
	}, 'withInspectorControlsImgScroll' );

	addFilter( 'editor.BlockEdit', 'acai-image-scroll/with-inspector-controls', withInspectorControlsImgScroll );

	const withInspectorControlsProdImg = createHigherOrderComponent( ( BlockEdit ) => {
		return (props) => {
			const acaiImgHover = props.attributes.acaiExtraProductImg || false;
			return createElement( Fragment,
				{},
				createElement( BlockEdit, props ),
				props.name === 'woocommerce/product-image' && props.isSelected && createElement( InspectorControls,
					{
						group: 'settings'
					},
					createElement(
						PanelBody,
						{
							title: __( 'Gallery Image', 'acai' ),
							initialOpen: true,
							className: 'acai-product-image-panel'
						},
						createElement(
							ToggleControl,
							{
								label: __( 'Display Gallery Image on Hover', 'acai' ),
								help: __( 'The 1st gallery image will display when hovering over the product image.', 'acai' ),
								checked: acaiImgHover,
								onChange: function( value ) {
									props.setAttributes(
										{
											acaiExtraProductImg: value
										}
									);
								}
							}
						)
					)
				)
			);
		};
	}, 'withInspectorControlsProdImg' );

	addFilter( 'editor.BlockEdit', 'acai-product-image/with-inspector-controls', withInspectorControlsProdImg );

	const withInspectorControlsGroup = createHigherOrderComponent( ( BlockEdit ) => {
		return (props) => {
			const acaiOverlap = props.attributes.acaiOverlap || 0;
			const acaiOverlapMobileOff = props.attributes.acaiOverlapMobileOff || false;
			let panelOpen = acaiOverlap === 0 ? false : true;
			return createElement( Fragment,
				{},
				createElement( BlockEdit, props ),
				props.name === 'core/group' && props.attributes.acaiAnimationType === 'none' && props.isSelected && createElement( InspectorControls,
					{
						group: 'styles'
					},
					createElement(
						PanelBody,
						{
							title: __( 'Overlap', 'acai' ),
							initialOpen: panelOpen,
							className: 'acai-overlap-panel'
						},
						createElement(
							RangeControl,
							{
								label: __( 'Horizontal', 'acai' ),
								value: acaiOverlap,
								onChange: function( value ) {
									let currentClass = typeof props.attributes.className === 'undefined' ? '' : props.attributes.className;
									let updateClassValue = ' acai-overlap' + value;
									if ( updateClassValue === ' acai-overlap0' ) {
										var updateClass = acaiRemoveDuplicates(currentClass,'acai-overlap');
									} else {
										var updateClass = acaiRemoveDuplicates(currentClass,'acai-overlap') + updateClassValue;
									}
									updateClass = updateClass.trim();
									props.setAttributes(
										{
											acaiOverlap: value,
											className: updateClass
										}
									);
								},
								min: -20,
								max: 20,
								step: 1,
								marks: [
									{
										value: -20,
										label: __( '-20', 'acai' )
									},
									{
										value: -10,
										label: __( '-10', 'acai' )
									},
									{
										value: 0,
										label: __( '0', 'acai' )
									},
									{
										value: 10,
										label: __( '10', 'acai' )
									},
									{
										value: 20,
										label: __( '20', 'acai' )
									},
								]
							}
						),
						createElement(
							ToggleControl,
							{
								label: __( 'Disable on Mobile', 'acai' ),
								checked: acaiOverlapMobileOff,
								onChange: function( value ) {
									let currentClass = typeof props.attributes.className === 'undefined' ? '' : props.attributes.className;
									if ( value ) {
										var updateClass = acaiRemoveDuplicates(currentClass,'acia-mobile-overlap') + ' acia-mobile-overlap-off';
									} else {
										var updateClass = acaiRemoveDuplicates(currentClass,'acia-mobile-overlap');
									}
									updateClass = updateClass.trim();
									props.setAttributes(
										{
											acaiOverlapMobileOff: value,
											className: updateClass
										}
									);
								}
							}
						)
					)
				)
			);
		};
	}, 'withInspectorControlsGroup' );

	addFilter( 'editor.BlockEdit', 'acai-group-overlap/with-inspector-controls', withInspectorControlsGroup );

	const withInspectorControlsStackOrder = createHigherOrderComponent( ( BlockEdit ) => {
		return (props) => {
			const acaiZindex = props.attributes.acaiZindex || 0;
			let panelOpen = acaiZindex === 0 ? false : true;
			return createElement( Fragment,
				{},
				createElement( BlockEdit, props ),
				props.name === 'core/group' && props.isSelected && createElement( InspectorControls,
					{
						group: 'settings'
					},
					createElement(
						PanelBody,
						{
							title: __( 'Stack Order', 'acai' ),
							initialOpen: panelOpen,
							className: 'acai-stack-order-panel'
						},
						createElement(
							RangeControl,
							{
								label: __( 'Z-Index', 'acai' ),
								value: acaiZindex,
								onChange: function( value ) {
									let currentClass = typeof props.attributes.className === 'undefined' ? '' : props.attributes.className;
									let updateClassValue = ' acai-zindex' + value;
									if ( updateClassValue === ' acai-zindex0' ) {
										var updateClass = acaiRemoveDuplicates(currentClass,'acai-zindex');
									} else {
										var updateClass = acaiRemoveDuplicates(currentClass,'acai-zindex') + updateClassValue;
									}
									updateClass = updateClass.trim();
									props.setAttributes(
										{
											acaiZindex: value,
											className: updateClass
										}
									);
								},
								min: 0,
								max: 10,
								step: 1,
								marks: [
									{
										value: 0,
										label: __( '0', 'acai' )
									},
									{
										value: 5,
										label: __( '5', 'acai' )
									},
									{
										value: 10,
										label: __( '10', 'acai' )
									},
								]
							}
						)
					)
				)
			);
		};
	}, 'withInspectorControlsStackOrder' );

	addFilter( 'editor.BlockEdit', 'acai-group-zindex/with-inspector-controls', withInspectorControlsStackOrder );

	const withInspectorControls = createHigherOrderComponent( ( BlockEdit ) => {
		return (props) => {
			const acaiAnimationType = props.attributes.acaiAnimationType || 'none';
			const acaiAnimationDuration = props.attributes.acaiAnimationDuration || 1.4;
			const acaiAnimationDelay = props.attributes.acaiAnimationDelay || 0;
			const acaiAnimationOffset = props.attributes.acaiAnimationOffset || 10;
			const acaiAnimationScale = props.attributes.acaiAnimationScale || 0;
			let panelOpen = acaiAnimationType === 'none' ? false : true;
			if ( props.name === 'core/group' && props.attributes.acaiOverlap ) {
				var hasOverlap = true;
			} else {
				var hasOverlap = false;
			}
			return createElement( Fragment,
				{},
				createElement( BlockEdit, props ),
				animationAllowedBlocks.includes( props.name ) && !hasOverlap && props.isSelected && createElement( InspectorControls,
					{
						group: 'styles'
					},
					createElement(
						PanelBody,
						{
							title: __( 'Animation', 'acai' ),
							initialOpen: panelOpen,
							className: 'acai-animation-panel'
						},
						createElement(
							SelectControl,
							{
								label: __( 'Type', 'acai' ),
								value: acaiAnimationType,
								onChange: function( value ) {
									if ( value === 'none' ) {
										props.setAttributes(
											{
												acaiAnimationType: value,
												acaiAnimationDuration: 1.4,
												acaiAnimationDelay: 0,
												acaiAnimationOffset: 10,
												acaiAnimationScale: 0.1
											}
										);
									} else {
										props.setAttributes(
											{
												acaiAnimationType: value
											}
										);
									}
								},
								options: [
									{
										label: __( 'None', 'acai' ),
										value: 'none'
									},
									{
										label: __( 'Up', 'acai' ),
										value: 'fade-in-up'
									},
									{
										label: __( 'Down', 'acai' ),
										value: 'fade-in-down'
									},
									{
										label: __( 'From Left', 'acai' ),
										value: 'fade-in-left'
									},
									{
										label: __( 'From Right', 'acai' ),
										value: 'fade-in-right'
									},
									{
										label: __( 'Up from Left', 'acai' ),
										value: 'fade-in-up-left'
									},
									{
										label: __( 'Up from Right', 'acai' ),
										value: 'fade-in-up-right'
									},
									{
										label: __( 'Down from Left', 'acai' ),
										value: 'fade-in-down-left'
									},
									{
										label: __( 'Down from Right', 'acai' ),
										value: 'fade-in-down-right'
									},
									{
										label: __( 'Fade In', 'acai' ),
										value: 'fade-in'
									},
									{
										label: __( 'Scale In', 'acai' ),
										value: 'scale-in'
									}
								]
							}
						),
						acaiAnimationType !== 'none' && createElement(
							RangeControl,
							{
								label: __( 'Duration (seconds)', 'acai' ),
								value: acaiAnimationDuration,
								onChange: function( value ) {
									props.setAttributes(
										{
											acaiAnimationDuration: value
										}
									);
								},
								min: 0.5,
								max: 3,
								step: 0.1,
								marks: [
									{
										value: 0.5,
										label: __( '0.5', 'acai' )
									},
									{
										value: 1.0,
										label: __( '1.0', 'acai' )
									},
									{
										value: 1.5,
										label: __( '1.5', 'acai' )
									},
									{
										value: 2.0,
										label: __( '2.0', 'acai' )
									},
									{
										value: 2.5,
										label: __( '2.5', 'acai' )
									},
									{
										value: 3.0,
										label: __( '3.0', 'acai' )
									},
								]
							}
						),
						acaiAnimationType !== 'none' && createElement(
							RangeControl,
							{
								label: __( 'Delay (seconds)', 'acai' ),
								value: acaiAnimationDelay,
								onChange: function( value ) {
									props.setAttributes(
										{
											acaiAnimationDelay: value
										}
									);
								},
								min: 0,
								max: 2,
								step: 0.1,
								marks: [
									{
										value: 0,
										label: __( '0', 'acai' )
									},
									{
										value: 0.5,
										label: __( '0.5', 'acai' )
									},
									{
										value: 1.0,
										label: __( '1.0', 'acai' )
									},
									{
										value: 1.5,
										label: __( '1.5', 'acai' )
									},
									{
										value: 2.0,
										label: __( '2.0', 'acai' )
									},
								]
							}
						),
						acaiAnimationType !== 'none' && acaiAnimationType !== 'fade-in' && acaiAnimationType !== 'scale-in' && createElement(
							RangeControl,
							{
								label: __( 'Offset (rem)', 'acai' ),
								value: acaiAnimationOffset,
								onChange: function( value ) {
									props.setAttributes(
										{
											acaiAnimationOffset: value
										}
									);
								},
								min: 1,
								max: 20,
								step: 1,
								marks: [
									{
										value: 1,
										label: __( '1', 'acai' )
									},
									{
										value: 5,
										label: __( '5', 'acai' )
									},
									{
										value: 10,
										label: __( '10', 'acai' )
									},
									{
										value: 15,
										label: __( '15', 'acai' )
									},
									{
										value: 20,
										label: __( '20', 'acai' )
									},
								]
							}
						),
						acaiAnimationType === 'scale-in' && createElement(
							RangeControl,
							{
								label: __( 'Scale Start Size', 'acai' ),
								value: acaiAnimationScale,
								onChange: function( value ) {
									props.setAttributes(
										{
											acaiAnimationScale: value
										}
									);
								},
								min: 0.1,
								max: 0.9,
								step: 0.1,
								marks: [
									{
										value: 0.1,
										label: __( '0.1', 'acai' )
									},
									{
										value: 0.3,
										label: __( '0.3', 'acai' )
									},
									{
										value: 0.5,
										label: __( '0.5', 'acai' )
									},
									{
										value: 0.7,
										label: __( '0.7', 'acai' )
									},
									{
										value: 0.9,
										label: __( '0.9', 'acai' )
									},
								]
							}
						),
						acaiAnimationType !== 'none' && createElement(
							Button,
							{
								text: __( 'Reset All', 'acai' ),
								variant: 'secondary',
								onClick: function() {
									props.setAttributes(
										{
											acaiAnimationType: 'none',
											acaiAnimationDuration: 1.4,
											acaiAnimationDelay: 0,
											acaiAnimationOffset: 10,
											acaiAnimationScale: 0.1
										}
									);
								}
							}
						)
					)
				)
			);
		};
	}, 'withInspectorControls' );

	addFilter( 'editor.BlockEdit', 'acai-animation/with-inspector-controls', withInspectorControls );

	function acaiRemoveDuplicates(str, strStartsWith) {
		let array = str.split(' ');
		array = array.filter(item => !item.startsWith(strStartsWith));
		let newArray = [...new Set(array)];
		return newArray.join(' ');
	}

} ) ( window.wp );
