/**
 * POST TYPE: Popup Builder - Helper - Display Condition Dropdowns
 */
import { useState, useEffect } from '@wordpress/element';
import { __ } from '@wordpress/i18n';
import Select from 'react-select';

// React Component to Render the Display Rules Dropdowns.
const DisplayRulesDropdown = ( props ) => {
	const { metaTag, meta, setMeta } = props;

	const metaTagName = 'spectra-popup-' + metaTag;
	const [ editRules, setEditRules ] = useState( { rule: meta[ metaTagName ].rule, specific: meta[ metaTagName ].specificText } );
	const [ specificText, setSpecificText ] = useState( meta[ metaTagName ].specificText );
	const [ searchOptions, setSearchOptions ] = useState( [] );
	const [ renderSpecificRules, setRenderSpecificRules ] = useState( false );

	// Set the Default State for Specific Rule Rendering.
	useEffect( () => {
		editRules.rule.find( ( option ) => {
			if ( 'specifics' === option.value ) {
				setRenderSpecificRules( true );
				return true;
			}
			return false;
		} );
	}, [] );

	// Early exit after all react hooks are called.
	if ( ! metaTag ) {
		return;
	}

	// Update the popup meta.
	const updatePopupMeta = ( value ) => {
		// Update the meta with the new values.
		setMeta( {
			...meta,
			[ metaTagName ]: {
				rule: value.rule,
				specific: value.specific,
				specificText: value.specificText
			},
		} );
	}

	// Styles for the React Select Component.
	const customSelectStyles = {
		container: ( provided ) => ( {
			...provided,
			width: '100%',
			boxSizing: 'content-box',
			padding: '0 1px',
			marginTop: '10px',
		} ),
		control: ( provided ) => ( {
			...provided,
			border: '1px solid #e6e7e9',
			boxShadow: 'none',
			minHeight: '30px',
			borderRadius: '3px',
			alignItems: 'flex-start', 
		} ),
		valueContainer: ( provided ) => ( {
			...provided,
			padding: '0px 8px',
		} ),
		input: ( provided ) => ( {
			...provided,
			height: '30px',
			padding: 0,
			margin: 0,
		} ),
		placeholder: ( provided ) => ( {
			...provided,
			color: '#50575e',
			fontSize: '14px',
			margin: 0,
		} ),
		singleValue: ( provided ) => ( {
			...provided,
			color: '#50575e',
			top: '50%',
			transform: 'translateY(-50%);',
		} ),
		multiValue: ( provided ) => ( {
			...provided,
			position: 'relative',
			left: '-6px',
		} ),
		multiValueLabel: ( provided ) => ( {
			...provided,
			backgroundColor: '#e6e7e9',
			color: '#50575e',
		} ),
		multiValueRemove: ( provided ) => ( {
			...provided,
			'cursor': 'pointer',
			'&:hover': {
				backgroundColor: '#e6e7e9',
				svg: {
					fill: '#dc2626',
				},
			},
		} ),
		indicatorsContainer: ( provided ) => ( {
			...provided,
			height: '30px',
		} ),
		indicatorSeparator: ( provided ) => ( {
			...provided,
			display: 'none',
		} ),
		dropdownIndicator: ( provided ) => ( {
			...provided,
			color: '#50575e',
			padding: '0 6px',
		} ),
		menu: ( provided ) => ( {
			...provided,
			color: '#50575e',
		} ),
		menuPortal: ( provided ) => ( {
			...provided,
			zIndex: 9999999,
		} ),

	}

	// Prepare display group rules.
	const displayRules = () => {
		const tempSearchOptions = [];
		const displayRulesObject = spectra_pro_blocks_info.display_rules;
		for ( const category in displayRulesObject ) {
			const ruleObject = displayRulesObject[ category ]
			const childOptions = [];
			for ( const ruleKey in ruleObject.value ) {
				const setDisable = editRules.rule.includes( ruleKey ) ? 'disabled' : '';
				childOptions.push( {
					label: ruleObject.value[ ruleKey ],
					value: ruleKey,
					disabled: setDisable,
				} );
			}
			tempSearchOptions.push( {
				label: ruleObject.label,
				options: childOptions,
			} );
		}
		return tempSearchOptions;
	};

	// Update the rules when the dropdown changes.
	const onSelectRule = ( options ) => {
		let specificsExist = false;
		options.find( ( option ) => {
			if ( 'specifics' === option.value ) {
				specificsExist = true;
				return true;
			}
			return false;
		} );
		setRenderSpecificRules( specificsExist );
		editRules.rule = options;
		setEditRules( { ...editRules } );
		prepareToSave( specificsExist );
	}

	// Update the search results based on what the user has typed.
	const onSpecificTyping = ( value ) => {
		if ( '' === value || value.length <= 1 ) {
			setSearchOptions( [] );
			return;
		}

		// Create the formData for the AJAX request, with the typed in value as the search query.
		const popupData = new FormData();
		popupData.append( 'action', 'spectra_popup_builder_get_posts_by_query' );
		popupData.append( 'nonce', spectra_pro_blocks_info.ajax_nonce );
		popupData.append( 'search', value );

		// Fetch the matching post|page|CPT titles
		fetch( spectra_pro_blocks_info.ajax_url, {
			method: 'POST',
			credentials: 'same-origin',
			body: popupData,
		} )
		.then( ( resp ) => resp.json() )
		.then( ( data ) => {
			if ( ! data.success ) {
				setSearchOptions( [] );
				return;
			}

			const tempSearchOptions = [];

			const specificRulesObject = data.data;
			// Push the options based on the data into the array to be returned.
			for ( const category in specificRulesObject ) {
				const childOptions = [];
				const specificObject = specificRulesObject[ category ];
				for ( const ruleKey in specificObject.children ) {
					childOptions.push( {
						value: specificObject.children[ ruleKey ].id,
						label: specificObject.children[ ruleKey ].title
					} );
				}
				const temp = {
					label: specificObject.title,
					options: childOptions,
				}
				tempSearchOptions.push( temp );
			}

			setSearchOptions( tempSearchOptions );
		} );
	}

	// Update the dropdown when specifics is added/removed.
	const onSpecificChange = ( values ) => {
		setSpecificText( values );
		editRules.specific = values;
		setEditRules( { ...editRules } );
		prepareToSave();
	}

	// Filter and clean the data to update the meta.
	const prepareToSave = ( isThereSpecifics = null ) => {
		// First check if this came from the rule change and not typing, then check if the Specifics rules are there or not.
		if ( false === isThereSpecifics && editRules.specific?.length ) {
			editRules.specific = [];
			setSpecificText( [] );
		}

		// Remove empty values from rules to prepare to save in the database.
		const filtered = editRules.rule.filter( ( el ) => ( el !== '' ) );

		// Remove duplicate values from rules to prepare to save in the database.
		const singularSpecifics = editRules.specific.map( val => val.value );

		// Create the updated meta rules.
		const saveValues = {
			rule: filtered,
			specific: singularSpecifics,
			specificText: editRules.specific,
		}
		// Update the editRules state and save the meta.
		setEditRules( { ...editRules } );
		updatePopupMeta( saveValues );
	}


	return (
		<div className='spectra-popup__modal-settings-content'>
			<div className='spectra-popup__modal-select-control-wrapper'>
				<Select
					styles={ customSelectStyles }
					value={ editRules.rule }
					options={ displayRules() }
					isMulti={ true }
					menuPortalTarget={ document.body }
					onChange={ ( event ) => onSelectRule( event ) }
					placeholder={ 'display-inclusions' === metaTag ? __( 'Entire Website', 'spectra-pro' ) :  __( '-- Select --', 'spectra-pro' ) }
					className='spectra-popup__control--meta-select'
					classNamePrefix='spectra'
				/>
				{ renderSpecificRules && (
					<Select
						styles={ customSelectStyles }
						value={ specificText }
						options={ searchOptions }
						onInputChange={ ( value ) => onSpecificTyping( value ) }
						isMulti={ true }
						menuPortalTarget={ document.body }
						onChange={ ( event ) => onSpecificChange( event ) }
						isSearchable={ true }
						placeholder={ __( 'Start typing to search…', 'spectra-pro' ) }
						className='spectra-popup__control--meta-select'
						classNamePrefix='spectra'
					/>
				) }
			</div>
		</div>
	);
}

export default DisplayRulesDropdown;