/**
 * WordPress dependencies
 */
import { InspectorControls } from '@wordpress/block-editor';
import { Spinner, PanelBody, withFilters} from '@wordpress/components';
import { useEntityRecord } from '@wordpress/core-data';
import { applyFilters } from "@wordpress/hooks";
import { __ } from '@wordpress/i18n';

/**
 * Internal dependencies
 */
import { isEmpty } from './../../admin/js/editor/utils/index';

// Duplicate what Base does to include all the PWP panels
const AllControls = withFilters(
	'personalizeWP.addInspectorControls'
)( ( props ) => <></> ); // eslint-disable-line

/**
 * Duplicating what PersonalizeWP would normally display, but using a different attribute.
 */
export default function Inspector( props ) {

	const {
		attributes,
		setAttributes,
	} = props;

	const settingsData = useEntityRecord( 'personalizewp/v1', 'settings' );

	// Display a default panel with spinner when settings are loading.
	if ( settingsData.isResolving ) {
		return (
			<InspectorControls group="settings">
				<PanelBody title={ __( 'Loading', 'personalizewp' ) }>
					<Spinner />
				</PanelBody>
			</InspectorControls>
		);
	}
	// Pass the settings onto each PersonalizeWP control panel.
	const settings = settingsData.record;

	// Set defaults.
	let blockAtts = attributes?.['display-conditions'] ?? {};

	/**
	 * Wrapper for setAttributes, validating and sanitising fields before saving.
	 * Similar to Bases' setPersonalizeWPAtts, but without setting required fields.
	 * @param {array} displayConditions
	 */
	function setVariationAtts( displayConditions ) {

		// Loop through all incoming conditions, individually validating each for their stucture.
		Object.entries(displayConditions).forEach(([ key, value ]) => {
			// Re-use Bases' required fields filter.
			const isValidated = applyFilters(
				'personalizeWP.hasRequiredFields',
				false, // Assume not validated
				{ [key]: value } // Filter requires object structure.
			);
			// Any conditions that don't validate should be deleted from incoming data and
			// what is already there. Ensures no empty arrays being set on the conditions.
			if ( ! isValidated ) {
				delete displayConditions[key];
				delete blockAtts[key];
			}
		} );

		// Uses let to allow undefining the object later.
		let updatedAttributes = Object.assign(
			// Merge any existing attributes.
			{ ...blockAtts },
			// Merge the incoming changes.
			{ ...displayConditions }
		);

		// Finally check for empty, so as to remove the attribute upon saving, invalidating the Variation.
		if ( isEmpty( updatedAttributes ) ) {
			updatedAttributes = undefined;
		}

		// Finally save the attributes
		setAttributes( {
			'display-conditions': updatedAttributes
		} );
	}

	return (
		<InspectorControls>
			<PanelBody title={ __( 'Variation Settings', 'personalizewp' ) } >

				<p>{ __( 'Choose one of the options below. The content variation will show if the criteria is met.', 'personalizewp' ) }</p>

				<AllControls
					blockAtts={ blockAtts }
					setPersonalizeWPAtts={ setVariationAtts }
					settings={ settings }
					{ ...props }
				/>

			</PanelBody>
		</InspectorControls>
	);
}
