// External dependencies.
import React, { ReactElement, useEffect } from 'react';

// WordPress dependencies
import { __ } from '@wordpress/i18n';

// Divi dependencies.
import {
	AdminLabelGroup,
	BackgroundGroup,
	FieldContainer,
	LinkGroup,
} from '@divi/module';
import { GroupContainer } from '@divi/modal';
import {
	TextContainer,
	TextAreaContainer,
	ToggleContainer,
	SelectContainer,
	UploadContainer,
} from '@divi/field-library';
import {
	type Module,
} from '@divi/types';
import { DynamicFieldAttrs } from './types';
import {
	convertSimpleOptions,
	convertGroupedOptions,
	buildDefaultInnerContent,
	buildDefaultAttrsPatch,
	getBlockDefaultsFromSchema,
	isToggleEnabled as isToggleEnabledValue,
} from '../../utils';
import CustomControl from '../../custom-control';

declare global {
	interface Window {
		JetEngineDiviViews: any;
	}
}

const DYNAMIC_FIELD_DEFAULTS_FALLBACK: Record<string, any> = {
	dynamic_field_source: 'object',
	dynamic_field_post_object: 'post_title',
	dynamic_field_relation_type: 'grandparents',
	dynamic_field_relation_post_type: '',
	dynamic_field_post_meta: '',
	dynamic_field_option: '',
	dynamic_field_var_name: '',
	dynamic_field_post_meta_custom: '',
	dynamic_field_wp_excerpt: false,
	dynamic_excerpt_more: '...',
	dynamic_excerpt_length: '',
	selected_field_icon_url: '',
	field_tag: 'div',
	hide_if_empty: false,
	field_fallback: '',
	dynamic_field_filter: false,
	filter_callback: '',
	dynamic_field_custom: false,
	dynamic_field_format: '%s',
	field_display: 'inline',
	object_context: 'default_object',
	related_list_is_linked: true,
	related_list_is_single: false,
};

const DYNAMIC_FIELD_SELECT_ATTRS = new Set( [
	'dynamic_field_source',
	'dynamic_field_post_object',
	'dynamic_field_relation_type',
	'dynamic_field_relation_post_type',
	'dynamic_field_post_meta',
	'acf_field_key',
	'dynamic_field_relation_meta',
	'dynamic_field_option',
	'field_display',
	'field_tag',
	'filter_callback',
	'object_context',
] );

const DYNAMIC_FIELD_TOGGLE_ATTRS = new Set( [
	'dynamic_field_wp_excerpt',
	'hide_if_empty',
	'dynamic_field_filter',
	'dynamic_field_custom',
	'related_list_is_linked',
	'related_list_is_single',
] );

export const SettingsContent = ( props: Module.Settings.Panel.Props<DynamicFieldAttrs> ): ReactElement => {

	const {
		defaultSettingsAttrs,
		attrs
	} = props;
	const setAttrs = ( ( props as unknown as {
		setAttrs?: ( next: Partial<DynamicFieldAttrs> ) => void;
		setAttributes?: ( next: Partial<DynamicFieldAttrs> ) => void;
	} ).setAttrs || ( props as unknown as {
		onChange?: ( next: Partial<DynamicFieldAttrs> ) => void;
		setAttributes?: ( next: Partial<DynamicFieldAttrs> ) => void;
	} ).setAttributes || ( props as unknown as {
		onChange?: ( next: Partial<DynamicFieldAttrs> ) => void;
	} ).onChange );

	const getCallbackArgs = ( arg: string ) => {

		if ( ! window.JetEngineDiviViews.filterCallbacksArgs ) {
			return [];
		}

		const result = [];

		for ( var i = 0; i < window.JetEngineDiviViews.filterCallbacksArgs.length; i++ ) {

			var control = window.JetEngineDiviViews.filterCallbacksArgs[ i ];

			if ( ! control.condition ) {
				continue;
			}

			if ( Array.isArray( control.condition ) && ! control.condition.includes( arg ) ) {
				continue;
			}

			if ( ! Array.isArray( control.condition ) && control.condition !== arg ) {
				continue;
			}

			control.name = control.prop;
			result.push( control );

		}

		return result;
	}

	useEffect( () => {
		if ( ! setAttrs ) {
			return;
		}

		const next = buildDefaultAttrsPatch( {
			attrs,
			defaults: getBlockDefaultsFromSchema( 'dynamicField', DYNAMIC_FIELD_DEFAULTS_FALLBACK ),
			toggleKeys: DYNAMIC_FIELD_TOGGLE_ATTRS,
			selectKeys: DYNAMIC_FIELD_SELECT_ATTRS,
		} );

		if ( Object.keys( next ).length ) {
			setAttrs( next );
		}
	}, [ attrs, setAttrs ] );

	const dynamicFieldDefaults = getBlockDefaultsFromSchema( 'dynamicField', DYNAMIC_FIELD_DEFAULTS_FALLBACK );
	const getToggleDefaultAttr = ( key: string ) => {
		return buildDefaultInnerContent( {
			key,
			value: dynamicFieldDefaults[ key ],
			toggleKeys: DYNAMIC_FIELD_TOGGLE_ATTRS,
			selectKeys: DYNAMIC_FIELD_SELECT_ATTRS,
		} );
	};

	return <React.Fragment>
		<GroupContainer
			id="general"
			title={__('General', 'jet-engine-divi-views')}
		>
			<FieldContainer
				attrName="dynamic_field_source.innerContent"
				label={__('Source', 'jet-engine-divi-views')}
				description={__('Dynamic Field Source.', 'jet-engine-divi-views')}
			>
				<SelectContainer
					options={ convertSimpleOptions( window.JetEngineDiviViews.fieldSources ) }
				/>
			</FieldContainer>
			{ 'object' === attrs?.dynamic_field_source?.innerContent?.desktop?.value && <FieldContainer
				attrName="dynamic_field_post_object.innerContent"
				label={__('Object field', 'jet-engine-divi-views')}
				description={__('Select object field get the data from', 'jet-engine-divi-views')}
			>
				<SelectContainer
					options={ convertGroupedOptions( window.JetEngineDiviViews.objectFields ) }
				/>
			</FieldContainer> }
			{ 'relations_hierarchy' === attrs?.dynamic_field_source?.innerContent?.desktop?.value &&
				<div>
					<FieldContainer
						attrName="dynamic_field_relation_type.innerContent"
						label={ __('Get', 'jet-engine-divi-views') }
						description={__('Get items from the relation', 'jet-engine-divi-views')}
					>
						<SelectContainer
							options={ convertSimpleOptions( window.JetEngineDiviViews.relationsTypes ) }
						/>
					</FieldContainer>
					<FieldContainer
						attrName="dynamic_field_relation_post_type.innerContent"
						label={ __('From Post Type', 'jet-engine-divi-views') }
						description={__('Get items from the post type of this relation', 'jet-engine-divi-views')}
					>
						<SelectContainer
							options={ convertSimpleOptions( window.JetEngineDiviViews.postTypes ) }
						/>
					</FieldContainer>
				</div>
			}

			{ 'meta' === attrs?.dynamic_field_source?.innerContent?.desktop?.value && <FieldContainer
					attrName="dynamic_field_post_meta.innerContent"
					label={__('Meta Key', 'jet-engine-divi-views')}
					description={__('Select meta field to get the value from', 'jet-engine-divi-views')}
				>
					<SelectContainer
						options={ convertGroupedOptions( window.JetEngineDiviViews.metaFields ) }
					/>
				</FieldContainer>
			}

			{ 'acf_field_groups' === attrs?.dynamic_field_source?.innerContent?.desktop?.value && undefined !== window.JetEngineDiviViews.acfFields &&

				<FieldContainer
					attrName="acf_field_key.innerContent"
					label={__('Meta Key', 'jet-engine-divi-views')}
					description={__('Select meta field to get the value from', 'jet-engine-divi-views')}
				>
					<SelectContainer
						options={ convertGroupedOptions( window.JetEngineDiviViews.acfFields ) }
					/>
				</FieldContainer>
			}

			{ 0 < window.JetEngineDiviViews.relationsMeta.length && 'relation_meta_data' === attrs?.dynamic_field_source?.innerContent?.desktop?.value &&
				<FieldContainer
					attrName="dynamic_field_relation_meta.innerContent"
					label={__('Meta Field', 'jet-engine-divi-views')}
					description={__('Select meta field to get the value from', 'jet-engine-divi-views')}
				>
					<SelectContainer
						options={ convertGroupedOptions( window.JetEngineDiviViews.relationsMeta ) }
					/>
				</FieldContainer>
			}

			{ 'options_page' === attrs?.dynamic_field_source?.innerContent?.desktop?.value &&
				<FieldContainer
					attrName="dynamic_field_option.innerContent"
					label={__('Option', 'jet-engine-divi-views')}
					description={__('Select option to get the value from', 'jet-engine-divi-views')}
				>
					<SelectContainer
						options={ convertGroupedOptions( window.JetEngineDiviViews.optionsFields ) }
					/>
				</FieldContainer>
			}

			<FieldContainer
				attrName="dynamic_field_post_meta_custom.innerContent"
				label={ __('Object field / Meta field / Repeater key / Component prop', 'jet-engine-divi-views') }
				description={ __('Note: this field will override Object field / Meta field value', 'jet-engine-divi-views') }
			>
				<TextContainer/>
			</FieldContainer>

			{ 'query_var' === attrs?.dynamic_field_source?.innerContent?.desktop?.value &&
				<FieldContainer
					attrName="dynamic_field_var_name.innerContent"
					label={ __('Variable Name', 'jet-engine-divi-views') }
					description={__('Set query variable name to get the data from', 'jet-engine-divi-views')}
				>
					<TextContainer/>
				</FieldContainer>
			}

			{ 'post_excerpt' === attrs?.dynamic_field_post_object?.innerContent?.desktop?.value &&
				<div>
					<FieldContainer
						attrName="dynamic_field_wp_excerpt.innerContent"
						label={ __('Use automatically generated excerpt', 'jet-engine-divi-views') }
						description={__('Get excerpt from the post content', 'jet-engine-divi-views')}
						defaultAttr={ getToggleDefaultAttr( 'dynamic_field_wp_excerpt' ) }
					>
						<ToggleContainer />
					</FieldContainer>
					{ isToggleEnabledValue( attrs?.dynamic_field_wp_excerpt?.innerContent?.desktop?.value ) &&
						<div>
							<FieldContainer
								attrName="dynamic_excerpt_more.innerContent"
								label={ __('More string', 'jet-engine-divi-views') }
								description={__('Text to add in the end of the excerpt', 'jet-engine-divi-views')}
							>
								<TextContainer/>
							</FieldContainer>
							<FieldContainer
								attrName="dynamic_excerpt_length.innerContent"
								label={ __('Custom length', 'jet-engine-divi-views') }
								description={__('Number of words in the excerpt', 'jet-engine-divi-views')}
							>
								<TextContainer/>
							</FieldContainer>
						</div>
					}
				</div>
			}
		</GroupContainer>

		<GroupContainer
			id="layout"
			title={__('Layout', 'jet-engine-divi-views')}
		>
			{ ! window.JetEngineDiviViews?.preventWrap && <FieldContainer
				attrName="field_display.innerContent"
				label={ __('Expected Display (inline/multiline)', 'jet-engine-divi-views') }
				description={__('Choose how the field is rendered', 'jet-engine-divi-views')}
			>
				<SelectContainer
					options={ convertSimpleOptions( [
						{ value: 'inline', label: __('Inline', 'jet-engine-divi-views') },
						{ value: 'multiline', label: __('Multiline', 'jet-engine-divi-views') },
					] ) }
				/>
			</FieldContainer> }
			<FieldContainer
				attrName="selected_field_icon_url.innerContent"
				label={__('Field Icon/Image', 'jet-engine-divi-views')}
				description={__('Image/icon to add before field value', 'jet-engine-divi-views')}
				features={{
					sticky: false,
				}}
			>
				<UploadContainer />
			</FieldContainer>
			<FieldContainer
				attrName="field_tag.innerContent"
				label={ __('Field tag', 'jet-engine-divi-views') }
				description={__('HTML tag to warp value into', 'jet-engine-divi-views')}
			>
				<SelectContainer
					options={ convertSimpleOptions( [
						{
							value: 'div',
							label: 'DIV',
						},
						{
							value: 'h1',
							label: 'H1',
						},
						{
							value: 'h2',
							label: 'H2',
						},
						{
							value: 'h3',
							label: 'H3',
						},
						{
							value: 'h4',
							label: 'H4',
						},
						{
							value: 'h5',
							label: 'H5',
						},
						{
							value: 'h6',
							label: 'H6',
						},
						{
							value: 'p',
							label: 'P',
						},
						{
							value: 'span',
							label: 'SPAN',
						},
					] ) }
				/>
			</FieldContainer>
			<FieldContainer
				attrName="hide_if_empty.innerContent"
				label={ __('Hide if value is empty', 'jet-engine-divi-views') }
				description={__('If value is empty - do not print the HTML wrappers', 'jet-engine-divi-views')}
				defaultAttr={ getToggleDefaultAttr( 'hide_if_empty' ) }
			>
				<ToggleContainer />
			</FieldContainer>
			{ ! isToggleEnabledValue( attrs?.hide_if_empty?.innerContent?.desktop?.value ) &&
				<FieldContainer
					attrName="field_fallback.innerContent"
					label={ __('Fallback', 'jet-engine-divi-views') }
					description={__('Set text to show if value is empty', 'jet-engine-divi-views')}
				>
					<TextContainer />
				</FieldContainer>
			}
			<FieldContainer
				attrName="dynamic_field_filter.innerContent"
				label={ __('Filter field output', 'jet-engine-divi-views') }
				description={__('Apply custom callback to the field value', 'jet-engine-divi-views')}
				defaultAttr={ getToggleDefaultAttr( 'dynamic_field_filter' ) }
			>
				<ToggleContainer />
			</FieldContainer>
			{ isToggleEnabledValue( attrs?.dynamic_field_filter?.innerContent?.desktop?.value ) &&
				<FieldContainer
					attrName="filter_callback.innerContent"
					label={ __('Callback', 'jet-engine-divi-views') }
					description={__('Callback to apply', 'jet-engine-divi-views')}
				>
					<SelectContainer
						options={ convertSimpleOptions( window.JetEngineDiviViews.filterCallbacks ) }
					/>
				</FieldContainer>
			}
			{ isToggleEnabledValue( attrs?.dynamic_field_filter?.innerContent?.desktop?.value ) && getCallbackArgs( attrs?.filter_callback?.innerContent?.desktop?.value ).map( ( control ) => {
					return <CustomControl
						control={ control }
						currentAttr={ control.name + '.innerContent' }
					/>
				} ) }
			<FieldContainer
				attrName="dynamic_field_custom.innerContent"
				label={ __('Customize field output', 'jet-engine-divi-views') }
				description={__('Change markup of the field output', 'jet-engine-divi-views')}
				defaultAttr={ getToggleDefaultAttr( 'dynamic_field_custom' ) }
			>
				<ToggleContainer />
			</FieldContainer>
			{ isToggleEnabledValue( attrs?.dynamic_field_custom?.innerContent?.desktop?.value ) &&
				<FieldContainer
					attrName="dynamic_field_format.innerContent"
					label={ __('Field format', 'jet-engine-divi-views') }
					description={ __( '%s will be replaced with field value. If you need use plain % sign, replace it with %% (for example for JetEngine macros wrappers)' ) }
				>
					<TextAreaContainer />
				</FieldContainer>
			}
			<FieldContainer
				attrName="object_context.innerContent"
				label={ __('Context', 'jet-engine-divi-views') }
				description={__('Select the context to get the value from', 'jet-engine-divi-views')}
			>
				<SelectContainer
					options={ convertSimpleOptions( window.JetEngineDiviViews.allowedContextList ) }
				/>
			</FieldContainer>
		</GroupContainer>
		<AdminLabelGroup
			defaultGroupAttr={defaultSettingsAttrs?.module?.meta?.adminLabel}
		/>
	</React.Fragment>
};
