( function( wp ) {

	const {
		createElement: el,
		useState
	} = wp.element;

	const { __ } = wp.i18n;

	const {
		PanelBody,
		ToggleControl,
		Button
	} = wp.components;

	const {
		RichText,
		InnerBlocks,
		InspectorControls
	} = wp.blockEditor;

	/**
	 * Register the accordion wrapper.
	 */
	wp.blocks.registerBlockType( 'greyd/accordion', {
		title: __("Accordion", 'greyd_hub'),
		description: __("Displays collapsible content. You can insert other blocks into it.", 'greyd_hub'),
		icon: greyd.tools.getBlockIcon('accordion'),
		category: 'greyd-blocks',
		keywords: [ 'trigger', 'toggle', 'tabs', 'accordion' ],
		supports: {
			anchor: true,
			align: true,
			spacing: {
				margin: true,
				padding: true
			}
		},
		example: {
			attributes: {
			},
			innerBlocks: [
				{
					name: 'greyd/accordion-item',
					attributes: {
						title: __("Accordion section", 'greyd_hub'),
					},
					innerBlocks: [
						{
							name: 'core/paragraph',
							attributes: {
								content: __("Displays collapsible content. You can insert other blocks into it.", 'greyd_hub')
							}
						},
					]
				},
				{
					name: 'greyd/accordion-item',
					attributes: {
						title: __("Accordion section", 'greyd_hub'),
					}
				},
			]
		},
		attributes: {
			iconNormal: { type: 'string', default: 'arrow_triangle-down' },
			iconActive: { type: 'string', default: 'arrow_triangle-up' },
			iconPosition: { type: 'string', default: '' },
			autoClose: { type: 'boolean', default: false },
			openFirst: { type: 'boolean', default: true },
			greydClass: { type: 'string', default: '' },
			greydStyles: { type: 'object', default: {} },
			titleStyles: { type: 'object', default: {} },
			contentStyles: { type: 'object', default: {} }
		},
		providesContext: {
			'greyd/accordion-iconNormal': 'iconNormal',
			'greyd/accordion-iconActive': 'iconActive',
		},

		edit: function( props ) {

			props.attributes.greydClass = greyd.tools.getGreydClass(props)

			const {
				className,
				setAttributes,
				attributes: atts
			} = props;

			const [ mode, setMode ] = useState("");
			if ( !props.isSelected && mode != "" ) setMode("");

			return [
				
				//  sidebar - settings
				el( InspectorControls, { group: 'settings' }, [

						// icon
						el( PanelBody, {
							title: __('Icon', 'greyd_hub'),
							initialOpen: true
						}, [
							el( greyd.components.IconPicker, {
								label: __("Normal icon", 'greyd_hub'),
								value: atts.iconNormal,
								onChange: value => setAttributes({ iconNormal: value })
							} ),
							el( greyd.components.IconPicker, {
								label: __("Active icon", 'greyd_hub'),
								value: atts.iconActive,
								onChange: value => setAttributes({ iconActive: value })
							} ),
							el( greyd.components.ButtonGroupControl, {
								label: __('Position', 'greyd_hub'),
								value: atts.iconPosition,
								onChange: value => setAttributes({ iconPosition: value }),
								options: [
									{ label: __("left", 'greyd_hub'), value: 'hasiconleft' },
									{ label: __("right", 'greyd_hub'), value: '' },
								]
							} ),
						] ),
						
						// behaviour
						el( PanelBody, {
							title: __("Behavior", 'greyd_hub'),
							initialOpen: false
						}, [
							el( ToggleControl, {
								label: __("Only one section at a time", 'greyd_hub'),
								checked: atts.autoClose,
								onChange: value => setAttributes({ autoClose: value }),
								help: __("This change only affects the frontend.", 'greyd_hub'),
							} ),
							el( ToggleControl, {
								label: __("First section open", 'greyd_hub'),
								checked: atts.openFirst,
								onChange: value => setAttributes({ openFirst: value }),
								help: __("This change only affects the frontend.", 'greyd_hub'),
							} ),
						] ),

						// layout
						el( StylingControlPanel, {
							title: __('Layout', 'greyd_hub'),
							initialOpen: false,
							supportsResponsive: true,
							blockProps: props,
							controls: [
								{
									label: __("Width", 'greyd_hub'),
									attribute: "--accord-width",
									control: greyd.components.RangeUnitControl,
									max: 1400
								},
								{
									label: __("Alignment", 'greyd_hub'),
									attribute: "--accord-align-items",
									control: greyd.components.ButtonGroupControl,
									options: [
										{ label: __("left", 'greyd_hub'), icon: greyd.tools.getCoreIcon('alignLeft'), value: 'flex-start' },
										{ label: __("center", 'greyd_hub'), icon: greyd.tools.getCoreIcon('alignCenter'), value: 'center' },
										{ label: __("right", 'greyd_hub'), icon: greyd.tools.getCoreIcon('alignRight'), value: 'flex-end' },
									]
								},
								{
									label: __("Space between", 'greyd_hub'),
									attribute: "--accord-content-margin-bottom",
									control: greyd.components.RangeUnitControl,
								}
							]
						})
				] ),

				//  sidebar - styles
				el( InspectorControls, { group: 'styles' }, [

					// general
					mode == "" ? [

						// elements
						el( PanelBody, { title: __("Elements", 'greyd_hub'), initialOpen: true }, [

							el ( greyd.components.SectionControl, {
								title: __("Title", 'greyd_hub'),
								onClick: () => setMode("title")
							} ),
							el ( greyd.components.SectionControl, {
								title: __("Content", 'greyd_hub'),
								onClick: () => setMode("content")
							} ),
	
						]),

						// border
						el( StylingControlPanel, {
							title: __("Border", 'greyd_hub'),
							initialOpen: false,
							supportsResponsive: false,
							blockProps: props,
							controls: [
								{
									label: __("Border", 'greyd_hub'),
									attribute: "border",
									control: greyd.components.BorderControl
								}
							]
						}),
						// radius
						el( StylingControlPanel, {
							title: __("Border radius", 'greyd_hub'),
							initialOpen: false,
							supportsResponsive: false,
							blockProps: props,
							controls: [
								{
									label: __("Border radius", 'greyd_hub'),
									attribute: "border-radius",
									control: greyd.components.RangeUnitControl,
									max: 50,
									labels: {
										"all": __("all corners", "greyd_hub"),
									},
									sides: [ "topLeft", "topRight", "bottomRight", "bottomLeft" ]
								}
							]
						}),
						
					] : null,

					// title
					mode == "title" ? [
						el ( 'span', {
							style: { display: 'block', paddingTop: '1rem', borderTop: '1px solid #e0e0e0' },
						}),
						el ( greyd.components.SectionControl, {
							title: __("Title", 'greyd_hub'),
							icon: 'arrow-left-alt',
							buttonText: __("back", 'greyd_hub'),
							onClick: () => setMode(""),
							isHeader: true
						} ),
						el( StylingControlPanel, {
							title: __("Alignment", 'greyd_hub'),
							initialOpen: true,
							supportsResponsive: true,
							blockProps: props,
							controls: [
								{
									label: __("Alignment", 'greyd_hub'),
									attribute: "--accord-title-align",
									control: greyd.components.ButtonGroupControl,
									options: [
										{ label: __("left", 'greyd_hub'), icon: greyd.tools.getCoreIcon('alignLeft'), value: 'left' },
										{ label: __("center", 'greyd_hub'), icon: greyd.tools.getCoreIcon('alignCenter'), value: 'center' },
										{ label: __("right", 'greyd_hub'), icon: greyd.tools.getCoreIcon('alignRight'), value: 'right' },
									]
								},
							]
						}),
						el( StylingControlPanel, {
							title: __("Colors", 'greyd_hub'),
							initialOpen: false,
							supportsHover: true,
							supportsActive: true,
							blockProps: props,
							controls: [
								{
									label: __("Text color", 'greyd_hub'),
									attribute: "--accord-title-text-color",
									control: greyd.components.ColorGradientPopupControl,
									mode: 'color'
								},
								{
									label: __("Background", 'greyd_hub'),
									attribute: "--accord-title-bg-color",
									control: greyd.components.ColorGradientPopupControl,
									// mode: 'color',
									preventConvertGradient: true,
									contrast: {
										default: has(atts.greydStyles, '--accord-title-text-color') ? atts.greydStyles['--accord-title-text-color'] : '',
										hover: has(atts.greydStyles, 'hover.--accord-title-text-color') ? atts.greydStyles.hover['--accord-title-text-color'] : ''
									}
								}
							]
						} ),
						el( StylingControlPanel, {
							title: __("Size", 'greyd_hub'),
							initialOpen: true,
							supportsResponsive: true,
							blockProps: props,
							controls: [
								{
									label: __("Font size", 'greyd_hub'),
									attribute: "--accord-title-font-size",
									control: greyd.components.RangeUnitControl,
									units: [ 'em', 'px', 'rem' ],
									max: {
										em: 4,
										px: 100,
										rem: 4
									}
								},
								{
									label: __("Icon size", 'greyd_hub'),
									attribute: "--accord-icon-font-size",
									control: greyd.components.RangeUnitControl,
									units: [ 'em', 'px', 'rem' ],
									max: {
										em: 4,
										px: 100,
										rem: 4
									}
								}
							]
						} ),
						el( StylingControlPanel, {
							title: __("Border", 'greyd_hub'),
							initialOpen: false,
							supportsHover: true,
							supportsActive: true,
							blockProps: props,
							parentAttr: 'titleStyles',
							controls: [
								{
									label: __("Border", 'greyd_hub'),
									attribute: "border",
									control: greyd.components.BorderControl
								}
							]
						} ),
						el( StylingControlPanel, {
							title: __("Border radius", 'greyd_hub'),
							initialOpen: false,
							supportsHover: true,
							supportsActive: true,
							blockProps: props,
							controls: [
								{
									label: __("Border radius", 'greyd_hub'),
									attribute: "--accord-title-radius",
									control: greyd.components.DimensionControl,
									type: "string"
								}
							]
						} ),
						el( StylingControlPanel, {
							title: __("Spaces", 'greyd_hub'),
							initialOpen: false,
							supportsResponsive: true,
							blockProps: props,
							controls: [
								{
									label: __("Inside", 'greyd_hub'),
									attribute: "--accord-padding",
									control: greyd.components.DimensionControl,
									type: 'string',
								}
							]
						} )

					] : null,

					// content
					mode == "content" ? [
						el ( 'span', {
							style: { display: 'block', paddingTop: '1rem', borderTop: '1px solid #e0e0e0' },
						}),
						el ( greyd.components.SectionControl, {
							title: __("Content", 'greyd_hub'),
							icon: 'arrow-left-alt',
							buttonText: __("back", 'greyd_hub'),
							onClick: () => setMode(""),
							isHeader: true
						} ),

						el( StylingControlPanel, {
							title: __("Colors", 'greyd_hub'),
							initialOpen: true,
							blockProps: props,
							controls: [
								{
									label: __("Text color", 'greyd_hub'),
									attribute: "--accord-text-color",
									control: greyd.components.ColorGradientPopupControl,
									mode: 'color'
								},
								{
									label: __("Background", 'greyd_hub'),
									attribute: "--accord-bg-color",
									control: greyd.components.ColorGradientPopupControl,
									// mode: 'color',
									preventConvertGradient: true,
									contrast: {
										default: has(atts.greydStyles, '--accord-text-color') ? atts.greydStyles['--accord-text-color'] : '',
									}
								}
							]
						} ),
						el( StylingControlPanel, {
							title: __("Border", 'greyd_hub'),
							initialOpen: false,
							blockProps: props,
							parentAttr: 'contentStyles',
							controls: [
								{
									label: __("Border", 'greyd_hub'),
									attribute: "border",
									control: greyd.components.BorderControl
								}
							]
						} ),
						el( StylingControlPanel, {
							title: __("Border radius", 'greyd_hub'),
							initialOpen: false,
							blockProps: props,
							parentAttr: 'contentStyles',
							controls: [
								{
									label: __("Border radius", 'greyd_hub'),
									attribute: "borderRadius",
									control: greyd.components.DimensionControl,
									type: "string"
								}
							]
						} ),
						el( StylingControlPanel, {
							title: __("Spaces", 'greyd_hub'),
							initialOpen: false,
							supportsResponsive: true,
							blockProps: props,
							controls: [
								{
									label: __("Inside", 'greyd_hub'),
									attribute: "--accord-content-padding",
									control: greyd.components.DimensionControl,
									type: 'string',
								}
							]
						} ),

					] : null,
				] ),

				// preview
				el( 'div', {
					id: atts.anchor,
					className: [ className, atts.greydClass, atts.iconPosition ].join(' ')
				}, [
					el( InnerBlocks, {
						template: [ [ 'greyd/accordion-item', {} ] ],
						allowedBlocks: [ 'greyd/accordion-item' ],
						renderAppender: InnerBlocks.ButtonBlockAppender
					} )
				] ),

				// styles
				el( greyd.components.RenderPreviewStyles, {
					selector: atts.greydClass + ' .wp-block-greyd-accordion-item',
					styles: {
						'': atts.greydStyles,
						' .wp-block-greyd-accordion__title': atts.titleStyles,
						' .wp-block-greyd-accordion__content': atts.contentStyles,
					}
				}),

				// active styles
				el( greyd.components.RenderPreviewStyles, {
					activeSelector: atts.greydClass + ' .wp-block-greyd-accordion__title[aria-expanded="true"]',
					styles: {
						'': atts.greydStyles,
						' ': atts.titleStyles,
						' .wp-block-greyd-accordion__content': atts.contentStyles,
					}
				}),
			];

			
		},

		save: function( props ) {

			const {
				attributes: atts
			} = props;

			return el( 'div', {
				id: atts.anchor,
				className: [ atts.greydClass, atts.iconPosition ].join(' '),
				'data-autoclose': atts.autoClose,
				'data-openfirst': atts.openFirst,
			}, [
				el( InnerBlocks.Content, {} ),
				el( greyd.components.RenderSavedStyles, {
					selector: atts.greydClass + ' .wp-block-greyd-accordion-item',
					styles: {
						'': atts.greydStyles,
						' .wp-block-greyd-accordion__title': atts.titleStyles,
						' .wp-block-greyd-accordion__content': atts.contentStyles,
					}
				} ),
				el( greyd.components.RenderSavedStyles, {
					activeSelector: atts.greydClass + ' .wp-block-greyd-accordion__title[aria-expanded="true"]',
					styles: {
						'': atts.greydStyles,
						' ': atts.titleStyles,
						' .wp-block-greyd-accordion__content': atts.contentStyles,
					}
				} )
			] );
		},

		deprecated: [
			/**
			 * Accordion active state selector.
			 */
			{
				supports: {
					anchor: true,
				},
				attributes: {
					iconNormal: { type: 'string', default: 'arrow_triangle-down' },
					iconActive: { type: 'string', default: 'arrow_triangle-up' },
					iconPosition: { type: 'string', default: '' },
					autoClose: { type: 'boolean', default: false },
					openFirst: { type: 'boolean', default: true },
					greydClass: { type: 'string', default: '' },
					greydStyles: { type: 'object', default: {} },
					titleStyles: { type: 'object', default: {} },
					contentStyles: { type: 'object', default: {} }
				},
				providesContext: {
					'greyd/accordion-iconNormal': 'iconNormal',
					'greyd/accordion-iconActive': 'iconActive',
				},
				save: function( props ) {
		
					const {
						attributes: atts
					} = props;
		
					return el( 'div', {
						id: atts.anchor,
						className: [ atts.greydClass, atts.iconPosition ].join(' '),
						'data-autoclose': atts.autoClose,
						'data-openfirst': atts.openFirst,
					}, [
						el( InnerBlocks.Content, {} ),
						el( greyd.components.RenderSavedStyles, {
							selector: atts.greydClass+" .wp-block-greyd-accordion-item",
							styles: {
								"": atts.greydStyles,
								" .wp-block-greyd-accordion__title": atts.titleStyles,
								" .wp-block-greyd-accordion__content": atts.contentStyles,
							}
						} )
					] );
				}
			},

			/**
			 * Bug in Accordion active state selector.
			 */
			{
				supports: {
					anchor: true,
					align: true,
					spacing: {
						margin: true,
						padding: true
					}
				},
				attributes: {
					iconNormal: { type: 'string', default: 'arrow_triangle-down' },
					iconActive: { type: 'string', default: 'arrow_triangle-up' },
					iconPosition: { type: 'string', default: '' },
					autoClose: { type: 'boolean', default: false },
					openFirst: { type: 'boolean', default: true },
					greydClass: { type: 'string', default: '' },
					greydStyles: { type: 'object', default: {} },
					titleStyles: { type: 'object', default: {} },
					contentStyles: { type: 'object', default: {} }
				},
				providesContext: {
					'greyd/accordion-iconNormal': 'iconNormal',
					'greyd/accordion-iconActive': 'iconActive',
				},
				save: function( props ) {
		
					const {
						attributes: atts
					} = props;

					return el( 'div', {
						id: atts.anchor,
						className: [ atts.greydClass, atts.iconPosition ].join(' '),
						'data-autoclose': atts.autoClose,
						'data-openfirst': atts.openFirst,
					}, [
						el( InnerBlocks.Content, {} ),
						el( greyd.components.RenderSavedStyles, {
							selector: atts.greydClass + ' .wp-block-greyd-accordion-item',
							activeSelector: atts.greydClass + ' .wp-block-greyd-accordion__title[aria-expanded="true"]',
							styles: {
								'': atts.greydStyles,
								' .wp-block-greyd-accordion__title': atts.titleStyles,
								' .wp-block-greyd-accordion__content': atts.contentStyles,
							}
						} )
					] );
				}
			}
		]
	} );


	/**
	 * Register the accordion child items.
	 */
	wp.blocks.registerBlockType( 'greyd/accordion-item', {
		title: __("Accordion section", 'greyd_hub'),
		description: __("Collapsible section with title, icon and contents", 'greyd_hub'),
		icon: greyd.tools.getBlockIcon('accordion'),
		category: 'greyd-blocks',
		parent: [ 'greyd/accordion' ],
		supports: {
			anchor: true,
			className: true
		},
		example: {
			attributes: {
				title: __("Accordion section", 'greyd_hub'),
			},
			innerBlocks: [
				{
					name: 'core/paragraph',
					attributes: {
						content: __("Displays collapsible content. You can insert other blocks into it.", 'greyd_hub')
					}
				},
			]
		},
		attributes: {
			title: {
				type: 'string',
				source: 'html',
				selector: 'span',
				default: ''
			},
			iconNormal: { type: 'string', default: 'arrow_triangle-down' },
			iconActive: { type: 'string', default: 'arrow_triangle-up' },
			uniqueId: { type: 'string', default: '' },
		},
		usesContext: [
			'greyd/accordion-iconNormal',
			'greyd/accordion-iconActive'
		],

		edit: function( props ) {

			const {
				className,
				setAttributes,
				attributes: atts,
				context
			} = props;

			const iconNormal = context['greyd/accordion-iconNormal'];
			const iconActive = context['greyd/accordion-iconActive'];
			const newAtts = {};

			if ( typeof iconNormal !== 'undefined' && iconNormal !== atts.iconNormal ) {
				newAtts.iconNormal = iconNormal;
			}
			if ( typeof iconActive !== 'undefined' && iconActive !== atts.iconActive ) {
				newAtts.iconActive = iconActive;
			}
			if ( _.isEmpty(atts.uniqueId) ) {
				newAtts.uniqueId = greyd.tools.generateRandomID();
			}

			if ( !_.isEmpty(newAtts) ) {
				setAttributes(newAtts);
			}

			const [ mode, setMode ] = useState("is-active");

			return [

				el( InspectorControls, {}, [

					el( PanelBody, { }, [
						el( 'p', { className: "greyd-inspector-help" }, __("You can customize the design of this section in the parent accordion block.", 'greyd_hub') ),
						el( Button, {
							variant: 'secondary',
							icon: 'visibility',
							onClick: () => {
								wp.data.dispatch('core/block-editor').selectBlock(
									wp.data.select('core/block-editor').getBlockParents(props.clientId).slice(-1).pop()
								)
							}
						}, __("Focus accordion", 'greyd_hub') )
					] )
				] ),

				// preview
				el( 'div', { 
					id: atts.anchor, 
					className: [ 'wp-block-greyd-accordion-item', className ].join(' ')
				}, [
					el( 'div', {
						className: 'wp-block-greyd-accordion__title',
						'aria-expanded': mode ? 'true' : 'false'
					}, [
						el( RichText, {
							tagName: 'span',
							className: 'title',
							value: atts.title,
							onChange: value => setAttributes({ title: value }),
							placeholder: __("Title", 'greyd_hub'),
							style: { flexGrow: '1' }
						} ),
						el( 'span', {
							className: mode === 'is-active' ? iconActive : iconNormal,
							'aria-hidden': 'true',
							onClick: () => setMode( mode === 'is-active' ? '' : 'is-active' ),
							style: {
								cursor: 'pointer',
								padding: 'var(--accord-padding)',
								margin: 'calc( -1 * var(--accord-padding) )',
								'font-size': 'var(--accord-icon-font-size)'
							}
						} )
					] ),
					el( 'div', {
						className: 'wp-block-greyd-accordion__content'/*+( mode === 'is-active' ? '' : ' hidden' )*/
					}, [
						el( InnerBlocks, {
							template: [[ 'core/paragraph', {} ]],
						} )
					] ),
				] )
			];
		},
		save: function( props ) {
			
			const {
				className,
				attributes: atts,
			} = props;

			return el( 'div', {
				id: atts.anchor,
				className: 'wp-block-greyd-accordion-item'
			}, [
				el( 'button', {
					className: 'wp-block-greyd-accordion__title',
					role: 'button',
					'aria-expanded': 'false',
					'aria-controls': 'sect-' + atts.uniqueId,
					id: 'title-' + atts.uniqueId
				}, [

					el( wp.blockEditor.RichText.Content, {
						tagName: 'span',
						value: atts.title
					} ),
					el( 'span', {
						className: 'icon icon-normal '+( atts.iconNormal ?? 'arrow_triangle-down' ),
						'aria-hidden': 'true'
					} ),
					el( 'span', {
						className: 'icon icon-active '+( atts.iconActive ?? 'arrow_triangle-up' ),
						'aria-hidden': 'true'
					} )
				] ),
				el( 'div', {
					className: 'wp-block-greyd-accordion__content',
					role: 'region',
					id: 'sect-' + atts.uniqueId,
					'aria-labelledby': 'title-' + atts.uniqueId
				}, [
					el( InnerBlocks.Content, {} )
				] ),
			] );
		},


		deprecated: [
			/**
			 * Improved accordion accessibility.
			 * @see https://www.w3.org/WAI/ARIA/apg/patterns/accordion/
			 * 
			 * @deprecated since 1.3.0
			 */
			{
				attributes: {
					title: { type: 'string', default: '' },
					iconNormal: { type: 'string', default: 'arrow_triangle-down' },
					iconActive: { type: 'string', default: 'arrow_triangle-up' },
				},
				save: function( props ) {
					const {
						attributes: atts,
					} = props;

					return el( 'div', {
						id: atts.anchor,
						className: 'wp-block-greyd-accordion-item'
					}, [
						el( 'div', {
							className: 'wp-block-greyd-accordion__title'
						}, [

							el( wp.blockEditor.RichText.Content, {
								tagName: 'span',
								value: atts.title
							} ),
							el( 'span', {
								className: 'icon icon-normal '+atts.iconNormal,
								'aria-hidden': 'true'
							} ),
							el( 'span', {
								className: 'icon icon-active '+atts.iconActive,
								'aria-hidden': 'true'
							} )
						] ),
						el( 'div', {
							className: 'wp-block-greyd-accordion__content'
						}, [
							el( InnerBlocks.Content, {} )
						] ),
					] );
				}
			}
		],
	} );


} )( 
	window.wp
);