/**
 * WordPress dependencies
 */
import ServerSideRender from '@wordpress/server-side-render';

import {
	Disabled,
	PanelBody,
	PanelRow,
	RangeControl,
	SelectControl,
	TextControl,
	TextareaControl,
	ToggleControl
} from '@wordpress/components';

import { InspectorControls,	PanelColorSettings,	useBlockProps } from '@wordpress/block-editor';

import { useEffect,	useMemo, useRef } from '@wordpress/element';

import { applyFilters } from '@wordpress/hooks';

import { useSelect } from '@wordpress/data';

/**
 * Describes the structure of the block in the context of the editor.
 * This represents what the editor will render when the block is used.
 *
 * @return {WPElement} Element to render.
 */
function Edit( { attributes, setAttributes } ) {	

	const episodes = aiopod_blocks.episodes;	

	const podcastItems = useSelect( ( select ) => {
		return select( 'core' ).getEntityRecords( 'postType', 'aiopod_podcasts', {
				per_page: -1,
				status: 'publish'
			}
		);
	});

	const tagItems = useSelect( ( select ) => {
		return select( 'core' ).getEntityRecords( 'taxonomy', 'aiopod_tags', {
			'per_page': -1
		});
	});

	const participantItems = useSelect( ( select ) => {
		return select( 'core' ).getEntityRecords( 'taxonomy', 'aiopod_participants', {
			'per_page': -1
		});	
	});

	const podcastList = useMemo( () => {
		let options = [{ 
			label: '— ' + aiopod_blocks.i18n.select_podcast + ' —', 
			value: 0
		}];

		if ( podcastItems && podcastItems.length > 0 ) {
			for ( let i = 0; i < podcastItems.length; i += 1 ) {
				options.push( {
					label: podcastItems[ i ].title.rendered,
					value: podcastItems[ i ].id,
				} );
			}
		}

		return options;
	}, [ podcastItems ] );

	const tagList = useMemo( () => {
		let options = [];

		if ( tagItems && tagItems.length > 0 ) {
			for ( let i = 0; i < tagItems.length; i += 1 ) {
				options.push({
					label: tagItems[ i ].name,
					value: tagItems[ i ].id,
				});	
			}			
		}

		return options;
	}, [ tagItems ] );

	const participantList = useMemo( () => {
		let options = [];

		if ( participantItems && participantItems.length > 0 ) {
			for ( let i = 0; i < participantItems.length; i += 1 ) {
				options.push({
					label: participantItems[ i ].name,
					value: participantItems[ i ].id,
				});
			}
		}

		return options;
	}, [ participantItems ] );

	const getControl = ( field, index ) => {
		if ( ! canShowControl( field.name ) ) {
			return '';
		}

		const placeholder = field.placeholder ? field.placeholder : '';
		const description = field.description ? field.description : '';

		switch ( field.type ) {
			case 'header':
				return <PanelRow key={ index }>
						<h3 className="aiopod-no-margin">{ field.label }</h3>
					</PanelRow>	
			case 'podcasts':
				return <PanelRow key={ index }>
					<SelectControl
						label={ field.label }
						help={ description }						
						options={ podcastList }
						value={ attributes[ field.name ] }
						onChange={ onChange( field.name ) }
            			__nextHasNoMarginBottom={ true }
            			__next40pxDefaultSize={ true }
					/>
				</PanelRow>	
			case 'tags':
				return <PanelRow key={ index } className="aiopod-block-multiselect">
					<SelectControl
						multiple
						label={ field.label }
						help={ description }						
						options={ tagList }
						value={ attributes[ field.name ] }
						onChange={ onChange( field.name ) }
            			__nextHasNoMarginBottom={ true }
            			__next40pxDefaultSize={ true }
					/>
				</PanelRow>	
			case 'participants':
				return <PanelRow key={ index } className="aiopod-block-multiselect">
					<SelectControl
						multiple
						label={ field.label }
						help={ description }						
						options={ participantList }
						value={ attributes[ field.name ] }
						onChange={ onChange( field.name ) }
            			__nextHasNoMarginBottom={ true }
            			__next40pxDefaultSize={ true }
					/>
				</PanelRow>		
			case 'number':
				return <PanelRow key={ index }>
					<RangeControl	
						label={ field.label }
						help={ description }
						placeholder={ placeholder }
						value={ attributes[ field.name ] }
						min={ field.min }
						max={ field.max }
						onChange={ onChange( field.name ) }
            			__nextHasNoMarginBottom={ true }
            			__next40pxDefaultSize={ true }
					/>
				</PanelRow>
			case 'textarea':
				return <PanelRow key={ index }>
					<TextareaControl
						label={ field.label }
						help={ description }
						placeholder={ placeholder }
						value={ attributes[ field.name ] }
						onChange={ onChange( field.name ) }
						__nextHasNoMarginBottom={ true }
					/>
				</PanelRow>
			case 'select':
			case 'radio':
				let options = [];

				for ( let key in field.options ) {
					options.push({
						label: field.options[ key ],
						value: key
					});
				};

				return <PanelRow key={ index }>
					<SelectControl
						label={ field.label }
						help={ description }						
						options={ options }
						value={ attributes[ field.name ] }
						onChange={ onChange( field.name ) }
            			__nextHasNoMarginBottom={ true }
            			__next40pxDefaultSize={ true }
					/>
				</PanelRow>
			case 'checkbox':
				return <PanelRow key={ index }>
					<ToggleControl
						label={ field.label }
						help={ description }
						checked={ attributes[ field.name ] }
						onChange={ toggleAttribute( field.name ) }
						__nextHasNoMarginBottom={ true }
					/>
				</PanelRow>
			case 'color':
				return <PanelRow key={ index }>
					<PanelColorSettings						
						title={ field.label }
						colorSettings={ [
							{
								label: aiopod_blocks.i18n.select_color,
								value: attributes[ field.name ],
								onChange: onChange( field.name )					
							}
						] }
					>							
					</PanelColorSettings>
				</PanelRow>
			default:
				return <PanelRow key={ index }>
					<TextControl	
						label={ field.label }
						help={ description }
						placeholder={ placeholder }
						value={ attributes[ field.name ] }
						onChange={ onChange( field.name ) }
            			__nextHasNoMarginBottom={ true }
            			__next40pxDefaultSize={ true }
					/>
				</PanelRow>
		}		
	}

	const canShowPanel = ( panel ) => {
		return applyFilters( 'aiopod_block_toggle_panels', true, panel, attributes );
	}

	const canShowControl = ( control ) => {
		let value = true;
		
		switch ( control ) {
			case 'columns':
				if ( attributes.layout != 'grid' ) {
					value = false;
				}			
				break;

			case 'show_episode_title':
			case 'show_episode_excerpt':
			case 'show_episode_date':
			case 'show_podcast_title':
			case 'show_episode_tags':
			case 'show_season_number':
			case 'show_episode_number':
			case 'show_episode_file_size':
			case 'show_episode_duration':
			case 'show_explicit_badge':
			case 'show_downloads_count':
			case 'show_plays_count':
			case 'excerpt_length':
				if ( attributes.layout == 'compact' ) {
					value = false;
				}			
				break;

			case 'max_height':
				if ( attributes.layout != 'compact' ) {
					value = false;
				}			
				break;

			case 'slides_per_view':
			case 'space_between':
			case 'show_dots':
			case 'show_arrows':
				if ( attributes.layout != 'slider' ) {
					value = false;
				}			
				break;

			case 'pagination':
				if ( attributes.layout == 'slider' ) {
					value = false;
				}			
				break;

			case 'player_width':
			case 'player_ratio':
			case 'player_autoplay':
			case 'player_autoadvance':
			case 'player_loop':
			case 'player_muted':
			case 'player_preload':
			case 'player_playsinline':
			case 'player_controls':
			case 'player_control_rewind':
			case 'player_control_play':
			case 'player_control_fastforward':
			case 'player_control_progress':
			case 'player_control_currenttime':
			case 'player_control_duration':
			case 'player_control_volume':
			case 'player_control_speed':
			case 'player_control_chapters':
			case 'player_control_pip':
			case 'player_control_download':
			case 'player_control_fullscreen':
			case 'player_episode_details':
			case 'show_player_episode_title':
			case 'show_player_episode_date':
			case 'show_player_podcast_title':
			case 'show_player_episode_tags':
			case 'show_player_episode_type':
			case 'show_player_season_number':
			case 'show_player_episode_number':
			case 'show_player_episode_file_size':
			case 'show_player_episode_duration':
			case 'show_player_explicit_badge':
			case 'show_player_downloads_count':
			case 'show_player_plays_count':
			case 'player_social_buttons':
			case 'show_player_subscribe_buttons':
			case 'show_player_follow_buttons':
			case 'show_player_share_buttons':
				value = attributes.enable_player;
				break;

			case 'filters_keyword':	
			case 'filters_tags':
			case 'filters_season':	
			case 'filters_sort':
			case 'filters_reset':
			case 'filters_layout':
			case 'filters_mode':			
				value = attributes.enable_filters;
				break;
		}

		return applyFilters( 'aiopod_block_toggle_controls', value, control, attributes );
	}

	const onChange = ( attribute ) => {
		return ( newValue ) => {
			setAttributes( { [ attribute ]: newValue } );		
		};
	}

	const toggleAttribute = ( attribute ) => {
		return ( newValue ) => {
			setAttributes( { [ attribute ]: newValue } );
		};
	}	

	const mounted = useRef();	
	useEffect( () => {
		if ( ! mounted.current ) {
			// Do componentDidMount logic
			mounted.current = true;
		} else {
			// Do componentDidUpdate logic
			applyFilters( 'aiopod_block_init', attributes );
		}
	} );

	return (
		<>
			<InspectorControls>
				{Object.keys( episodes ).map(( key, index ) => {
					return (
						canShowPanel( key ) && <PanelBody 
							key={ 'aiopod-block-panel-' + index } 
							title={ episodes[ key ].title }
							initialOpen={ 0 == index ? true : false }
							className="aiopod-block-panel">
								
							{Object.keys( episodes[ key ].fields ).map(( _key, _index ) => {
								return getControl( episodes[ key ].fields[ _key ], 'aiopod-block-control-' + _index );
							})}

						</PanelBody>
					)
				})}
			</InspectorControls>

			<div { ...useBlockProps() }>
				<Disabled>
					<ServerSideRender
						block="aiopod/episodes"
						attributes={ attributes }
					/>
				</Disabled>
			</div>
		</>
	);
}

export default Edit;