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

// Divi dependencies.
import {
	StyleContainer,
	StylesProps,
} from '@divi/module';

// Local dependencies.
import { SearchAttrs } from './types';
import {
	createBorderStyles,
	createSpacingStyles,
	createTypographyStyles,
	extractBorderAttrs,
	extractSpasingAttrs,
	extractTypographyAttrs,
} from '../../utils';

/**
 * Dynamic Module's style components.
 *
 * @since ??
 */
const ModuleStyles = ({
	settings,
	mode,
	state,
	noStyleTag,
	elements,
	attrs,
	orderClass,
}: StylesProps<SearchAttrs>): ReactElement => {
	const selectors = {
		filterWrapper: `${orderClass} .jet-search-filter`,
		input: `${orderClass} .jet-search-filter__input`,
		inputWrapper: `${orderClass} .jet-search-filter__input-wrapper`,
		inputClear: `${orderClass} .jet-search-filter__input-clear`,
		inputLoading: `${orderClass} .jet-search-filter__input-loading`,
		applyButton: `${orderClass} .jet-search-filter__submit`,
		applyButtonHover: `${orderClass} .jet-search-filter__submit:hover`,
		label: `${orderClass} .jet-filter-label`,
	};

	const normalizeFlexAlignmentAttr = ( attr: any ) => {
		if ( ! attr ) {
			return attr;
		}

		const mapValue = ( value: string ) => {
			if ( 'left' === value ) {
				return 'flex-start';
			}

			if ( 'right' === value ) {
				return 'flex-end';
			}

			return value;
		};

		if ( undefined !== attr?.desktop || undefined !== attr?.tablet || undefined !== attr?.phone ) {
			const next = { ...attr };

			[ 'desktop', 'tablet', 'phone' ].forEach( ( bp ) => {
				if ( ! next?.[ bp ] ) {
					return;
				}

				const current = next[ bp ]?.value ?? next[ bp ]?.default;

				if ( undefined === current ) {
					return;
				}

				next[ bp ] = {
					...next[ bp ],
					value: mapValue( current ),
					default: mapValue( current ),
				};
			} );

			return next;
		}

		const current = attr?.value ?? attr?.default;

		if ( undefined === current ) {
			return attr;
		}

		return {
			...attr,
			value: mapValue( current ),
			default: mapValue( current ),
		};
	};

	const inputTypography = extractTypographyAttrs(attrs?.module?.decoration?.inputTypography);
	const inputTypographyStyles = createTypographyStyles(selectors.input, inputTypography);

	const inputBorder = extractBorderAttrs(attrs?.module?.decoration?.inputBorder);
	const inputBorderStyles = createBorderStyles(selectors.input, inputBorder);

	const inputSpacing = extractSpasingAttrs(attrs?.module?.decoration?.inputSpacing);
	const inputPaddingLegacy = extractSpasingAttrs(attrs?.module?.decoration?.inputPadding);
	const inputMarginLegacy = extractSpasingAttrs(attrs?.module?.decoration?.inputMargin);
	const inputSpacingStyles = createSpacingStyles(selectors.input, {
		padding: inputSpacing?.padding || inputPaddingLegacy?.padding,
		margin: inputSpacing?.margin || inputMarginLegacy?.margin,
	});

	const labelTypography = extractTypographyAttrs(attrs?.module?.decoration?.labelTypography);
	const labelTypographyStyles = createTypographyStyles(selectors.label, labelTypography);


	const labelSpacing = extractSpasingAttrs(attrs?.module?.decoration?.labelSpacing);
	const labelPaddingLegacy = extractSpasingAttrs(attrs?.module?.decoration?.labelPadding);
	const labelMarginLegacy = extractSpasingAttrs(attrs?.module?.decoration?.labelMargin);
	const labelSpacingStyles = createSpacingStyles(selectors.label, {
		padding: labelSpacing?.padding || labelPaddingLegacy?.padding,
		margin: labelSpacing?.margin || labelMarginLegacy?.margin,
	});

	const buttonBorder = extractBorderAttrs(attrs?.module?.decoration?.buttonBorder);
	const buttonBorderStyles = createBorderStyles(selectors.applyButton, buttonBorder);

	const buttonSpacing = extractSpasingAttrs(attrs?.module?.decoration?.buttonSpacing);
	const buttonPaddingLegacy = extractSpasingAttrs(attrs?.module?.decoration?.buttonPadding);
	const buttonMarginLegacy = extractSpasingAttrs(attrs?.module?.decoration?.buttonMargin);
	const buttonSpacingStyles = createSpacingStyles(selectors.applyButton, {
		padding: buttonSpacing?.padding || buttonPaddingLegacy?.padding,
		margin: buttonSpacing?.margin || buttonMarginLegacy?.margin,
	});

	const inputColorSelectors = `${selectors.input}, ${selectors.input}::placeholder, ${selectors.input}:-ms-input-placeholder, ${selectors.input}::-ms-input-placeholder, ${selectors.inputClear}, ${selectors.inputLoading}`;

	return (
		<StyleContainer mode={mode} state={state} noStyleTag={noStyleTag}>
			{elements.style({
				attrName: 'module',
				styleProps: {
					disabledOn: {
						disabledModuleVisibility: settings?.disabledModuleVisibility,
					},
					advancedStyles: [
						...inputTypographyStyles,
						...inputBorderStyles,
						...inputSpacingStyles,
						...labelTypographyStyles,
						...labelSpacingStyles,
						...buttonBorderStyles,
						...buttonSpacingStyles,
						{
							componentName: 'divi/common',
							props: {
								property: 'max-width',
								selector: selectors.inputWrapper,
								attr: attrs?.module?.decoration?.contentInputWidth,
							},
						},
						{
							componentName: 'divi/common',
							props: {
								property: 'justify-content',
								selector: selectors.filterWrapper,
								attr: attrs?.module?.decoration?.contentLineHorizontalAlignment,
							},
						},
						{
							componentName: 'divi/common',
							props: {
								property: 'align-items',
								selector: selectors.filterWrapper,
								attr: attrs?.module?.decoration?.contentLineVerticalAlignment,
							},
						},
						{
							componentName: 'divi/common',
							props: {
								property: 'color',
								selector: inputColorSelectors,
								attr: attrs?.module?.decoration?.inputColor,
							},
						},
						{
							componentName: 'divi/common',
							props: {
								property: 'background-color',
								selector: selectors.input,
								attr: attrs?.module?.decoration?.inputBackgroundColor,
							},
						},
						{
							componentName: 'divi/common',
							props: {
								property: 'text-align',
								selector: selectors.label,
								attr: attrs?.module?.decoration?.labelAlignment,
							},
						},
						{
							componentName: 'divi/common',
							props: {
								property: 'color',
								selector: selectors.label,
								attr: attrs?.module?.decoration?.labelColor,
							},
						},
						{
							componentName: 'divi/common',
							props: {
								property: 'color',
								selector: selectors.applyButton,
								attr: attrs?.module?.decoration?.buttonNormalColor,
							},
						},
						{
							componentName: 'divi/common',
							props: {
								property: 'background-color',
								selector: selectors.applyButton,
								attr: attrs?.module?.decoration?.buttonNormalBgColor,
							},
						},
						{
							componentName: 'divi/common',
							props: {
								property: 'color',
								selector: selectors.applyButtonHover,
								attr: attrs?.module?.decoration?.buttonHoverColor,
							},
						},
						{
							componentName: 'divi/common',
							props: {
								property: 'background-color',
								selector: selectors.applyButtonHover,
								attr: attrs?.module?.decoration?.buttonHoverBgColor,
							},
						},
						{
							componentName: 'divi/common',
							props: {
								property: 'border-color',
								selector: selectors.applyButtonHover,
								attr: attrs?.module?.decoration?.buttonHoverBorderColor,
							},
						},
						{
							componentName: 'divi/common',
							props: {
								property: 'align-self',
								selector: selectors.applyButton,
								attr: normalizeFlexAlignmentAttr( attrs?.module?.decoration?.buttonAlignment ),
							},
						},
					],
				},
			})}
		</StyleContainer>
	);
}

export {
	ModuleStyles,
};
