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

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

// Local dependencies.
import { RangeFilterAttrs } 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<RangeFilterAttrs>): ReactElement => {
	const selectors = {
		sliderTrack: `${orderClass} .jet-range__slider .jet-range__slider__track`,
		sliderRange: `${orderClass} .jet-range__slider .jet-range__slider__track__range`,
		sliderInput: `${orderClass} .jet-range__slider .jet-range__slider__input`,
		sliderInputThumbWebkit: `${orderClass} .jet-range__slider .jet-range__slider__input::-webkit-slider-thumb`,
		sliderInputThumbMoz: `${orderClass} .jet-range__slider .jet-range__slider__input::-moz-range-thumb`,
		sliderInputThumbMs: `${orderClass} .jet-range__slider .jet-range__slider__input::-ms-thumb`,
		rangeValues: `${orderClass} .jet-range__values`,
		inputs: `${orderClass} .jet-range__inputs`,
		inputsContainer: `${orderClass} .jet-range__inputs__container`,
		inputGroup: `${orderClass} .jet-range__inputs__group`,
		inputGroupFirst: `${orderClass} .jet-range__inputs__group:first-child`,
		inputGroupLast: `${orderClass} .jet-range__inputs__group:last-child`,
		inputGroupFirstRtl: `.rtl ${orderClass} .jet-range__inputs__group:first-child`,
		inputGroupLastRtl: `.rtl ${orderClass} .jet-range__inputs__group:last-child`,
		input: `${orderClass} .jet-range__inputs__group input`,
		inputText: `${orderClass} .jet-range__inputs__group__text`,
		filterLabel: `${orderClass} .jet-filter-label`,
		applyButton: `${orderClass} .apply-filters__button`,
		applyButtonHover: `${orderClass} .apply-filters__button:hover`,
	};

	const sliderTrackBorder = extractBorderAttrs(attrs?.module?.decoration?.sliderTrackBorder);
	const sliderTrackBorderStyles = createBorderStyles(selectors.sliderTrack, sliderTrackBorder);

	const rangePointsBorder = extractBorderAttrs(attrs?.module?.decoration?.rangePointsBorder);
	const rangePointsBorderStyles = [
		...createBorderStyles(selectors.sliderInputThumbWebkit, rangePointsBorder),
		...createBorderStyles(selectors.sliderInputThumbMoz, rangePointsBorder),
		...createBorderStyles(selectors.sliderInputThumbMs, rangePointsBorder),
	];

	const valuesTypography = extractTypographyAttrs(attrs?.module?.decoration?.valuesTypography);
	const valuesTypographyStyles = createTypographyStyles(selectors.rangeValues, valuesTypography);

	const valuesSpacing = extractSpasingAttrs(attrs?.module?.decoration?.valuesSpacing);
	const valuesSpacingStyles = createSpacingStyles(selectors.rangeValues, valuesSpacing);

	const inputsMargin = extractSpasingAttrs(attrs?.module?.decoration?.inputsMargin);
	const inputsMarginStyles = createSpacingStyles(selectors.inputs, inputsMargin);

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

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

	const inputPadding = extractSpasingAttrs(attrs?.module?.decoration?.inputPadding);
	const inputPaddingStyles = createSpacingStyles(selectors.input, inputPadding);

	const inputTextTypography = extractTypographyAttrs(attrs?.module?.decoration?.inputTextTypography);
	const inputTextTypographyStyles = createTypographyStyles(selectors.inputText, inputTextTypography);

	const inputTextPadding = extractSpasingAttrs(attrs?.module?.decoration?.inputTextPadding);
	const inputTextPaddingStyles = createSpacingStyles(selectors.inputText, inputTextPadding);

	const labelTypography = extractTypographyAttrs(attrs?.module?.decoration?.labelTypography);
	const labelTypographyStyles = createTypographyStyles(selectors.filterLabel, 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.filterLabel, {
		padding: labelSpacing?.padding || labelPaddingLegacy?.padding,
		margin: labelSpacing?.margin || labelMarginLegacy?.margin,
	});


	const applySpacing = extractSpasingAttrs(attrs?.module?.decoration?.applySpacing);
	const applyPaddingLegacy = extractSpasingAttrs(attrs?.module?.decoration?.applyPadding);
	const applyMarginLegacy = extractSpasingAttrs(attrs?.module?.decoration?.applyMargin);
	const applySpacingStyles = createSpacingStyles(selectors.applyButton, {
		padding: applySpacing?.padding || applyPaddingLegacy?.padding,
		margin: applySpacing?.margin || applyMarginLegacy?.margin,
	});

	const applyBorder = extractBorderAttrs(attrs?.module?.decoration?.applyBorder);
	const applyBorderStyles = createBorderStyles(selectors.applyButton, applyBorder);

	return (
		<StyleContainer mode={mode} state={state} noStyleTag={noStyleTag}>
			{elements.style({
				attrName: 'module',
				styleProps: {
					disabledOn: {
						disabledModuleVisibility: settings?.disabledModuleVisibility,
					},
					advancedStyles: [
						...sliderTrackBorderStyles,
						...rangePointsBorderStyles,
						...valuesTypographyStyles,
						...valuesSpacingStyles,
						...inputsMarginStyles,
						...inputTypographyStyles,
						...inputBorderStyles,
						...inputPaddingStyles,
						...inputTextTypographyStyles,
						...inputTextPaddingStyles,
						...labelTypographyStyles,
						...labelSpacingStyles,
						...applySpacingStyles,
						...applyBorderStyles,
						{
							componentName: 'divi/common',
							props: {
								property: 'height',
								selector: selectors.sliderTrack,
								attr: attrs?.module?.decoration?.sliderStroke,
							},
						},
						{
							componentName: 'divi/common',
							props: {
								property: 'background-color',
								selector: selectors.sliderTrack,
								attr: attrs?.module?.decoration?.sliderDefaultColor,
							},
						},
						{
							componentName: 'divi/common',
							props: {
								property: 'color',
								selector: selectors.sliderRange,
								attr: attrs?.module?.decoration?.sliderRangeColor,
							},
						},
						{
							componentName: 'divi/common',
							props: {
								property: 'width',
								selector: selectors.sliderInputThumbWebkit,
								attr: attrs?.module?.decoration?.pointsWidth,
							},
						},
						{
							componentName: 'divi/common',
							props: {
								property: 'width',
								selector: selectors.sliderInputThumbMoz,
								attr: attrs?.module?.decoration?.pointsWidth,
							},
						},
						{
							componentName: 'divi/common',
							props: {
								property: 'width',
								selector: selectors.sliderInputThumbMs,
								attr: attrs?.module?.decoration?.pointsWidth,
							},
						},
						{
							componentName: 'divi/common',
							props: {
								property: 'height',
								selector: selectors.sliderInput,
								attr: attrs?.module?.decoration?.pointsHeight,
							},
						},
						{
							componentName: 'divi/common',
							props: {
								property: 'height',
								selector: selectors.sliderInputThumbWebkit,
								attr: attrs?.module?.decoration?.pointsHeight,
							},
						},
						{
							componentName: 'divi/common',
							props: {
								property: 'height',
								selector: selectors.sliderInputThumbMoz,
								attr: attrs?.module?.decoration?.pointsHeight,
							},
						},
						{
							componentName: 'divi/common',
							props: {
								property: 'height',
								selector: selectors.sliderInputThumbMs,
								attr: attrs?.module?.decoration?.pointsHeight,
							},
						},
						{
							componentName: 'divi/common',
							props: {
								property: 'background-color',
								selector: selectors.sliderInputThumbWebkit,
								attr: attrs?.module?.decoration?.pointsColor,
							},
						},
						{
							componentName: 'divi/common',
							props: {
								property: 'background-color',
								selector: selectors.sliderInputThumbMoz,
								attr: attrs?.module?.decoration?.pointsColor,
							},
						},
						{
							componentName: 'divi/common',
							props: {
								property: 'background-color',
								selector: selectors.sliderInputThumbMs,
								attr: attrs?.module?.decoration?.pointsColor,
							},
						},
						{
							componentName: 'divi/common',
							props: {
								property: 'color',
								selector: selectors.rangeValues,
								attr: attrs?.module?.decoration?.valuesColor,
							},
						},
						{
							componentName: 'divi/common',
							props: {
								property: 'text-align',
								selector: selectors.rangeValues,
								attr: attrs?.module?.decoration?.valuesAlign,
							},
						},
						{
							componentName: 'divi/common',
							props: {
								property: 'max-width',
								selector: selectors.inputsContainer,
								attr: attrs?.module?.decoration?.inputsWidth,
							},
						},
						{
							componentName: 'divi/common',
							props: {
								property: 'margin-right',
								selector: selectors.inputGroupFirst,
								attr: attrs?.module?.decoration?.inputsOffset,
								declarationFunction: ({ attrValue }) =>
									attrValue ? `calc(${attrValue} / 2)` : '',
							},
						},
						{
							componentName: 'divi/common',
							props: {
								property: 'margin-left',
								selector: selectors.inputGroupLast,
								attr: attrs?.module?.decoration?.inputsOffset,
								declarationFunction: ({ attrValue }) =>
									attrValue ? `calc(${attrValue} / 2)` : '',
							},
						},
						{
							componentName: 'divi/common',
							props: {
								property: 'margin-left',
								selector: selectors.inputGroupFirstRtl,
								attr: attrs?.module?.decoration?.inputsOffset,
								declarationFunction: ({ attrValue }) =>
									attrValue ? `calc(${attrValue} / 2)` : '',
							},
						},
						{
							componentName: 'divi/common',
							props: {
								property: 'margin-right',
								selector: selectors.inputGroupLastRtl,
								attr: attrs?.module?.decoration?.inputsOffset,
								declarationFunction: ({ attrValue }) =>
									attrValue ? `calc(${attrValue} / 2)` : '',
							},
						},
						{
							componentName: 'divi/common',
							props: {
								property: 'margin-left',
								selector: selectors.inputsContainer,
								attr: attrs?.module?.decoration?.inputsAlignment,
								declarationFunction: ({ attrValue }) => {
									switch (attrValue) {
										case 'left':
											return '0';
										case 'right':
											return 'auto';
										case 'center':
										default:
											return 'auto';
									}
								},
							},
						},
						{
							componentName: 'divi/common',
							props: {
								property: 'margin-right',
								selector: selectors.inputsContainer,
								attr: attrs?.module?.decoration?.inputsAlignment,
								declarationFunction: ({ attrValue }) => {
									switch (attrValue) {
										case 'left':
											return 'auto';
										case 'right':
											return '0';
										case 'center':
										default:
											return 'auto';
									}
								},
							},
						},
						{
							componentName: 'divi/common',
							props: {
								property: 'color',
								selector: selectors.inputGroup,
								attr: attrs?.module?.decoration?.inputColor,
							},
						},
						{
							componentName: 'divi/common',
							props: {
								property: 'background-color',
								selector: selectors.inputGroup,
								attr: attrs?.module?.decoration?.inputBackgroundColor,
							},
						},
						{
							componentName: 'divi/common',
							props: {
								property: 'color',
								selector: selectors.inputText,
								attr: attrs?.module?.decoration?.inputTextColor,
							},
						},
						{
							componentName: 'divi/common',
							props: {
								property: 'background-color',
								selector: selectors.inputText,
								attr: attrs?.module?.decoration?.inputTextBackgroundColor,
							},
						},
						{
							componentName: 'divi/common',
							props: {
								property: 'text-align',
								selector: selectors.filterLabel,
								attr: attrs?.module?.decoration?.labelAlignment,
							},
						},
						{
							componentName: 'divi/common',
							props: {
								property: 'color',
								selector: selectors.filterLabel,
								attr: attrs?.module?.decoration?.labelColor,
							},
						},
						{
							componentName: 'divi/common',
							props: {
								property: 'color',
								selector: selectors.applyButton,
								attr: attrs?.module?.decoration?.applyNormalColor,
							},
						},
						{
							componentName: 'divi/common',
							props: {
								property: 'background-color',
								selector: selectors.applyButton,
								attr: attrs?.module?.decoration?.applyNormalBgColor,
							},
						},
						{
							componentName: 'divi/common',
							props: {
								property: 'color',
								selector: selectors.applyButtonHover,
								attr: attrs?.module?.decoration?.applyHoverColor,
							},
						},
						{
							componentName: 'divi/common',
							props: {
								property: 'background-color',
								selector: selectors.applyButtonHover,
								attr: attrs?.module?.decoration?.applyHoverBgColor,
							},
						},
						{
							componentName: 'divi/common',
							props: {
								property: 'border-color',
								selector: selectors.applyButtonHover,
								attr: attrs?.module?.decoration?.applyHoverBorderColor,
							},
						},
						{
							componentName: 'divi/common',
							props: {
								property: 'align-self',
								selector: selectors.applyButton,
								attr: attrs?.module?.decoration?.applyAlignment,
							},
						},
					],
				},
			})}
		</StyleContainer>
	);
}

export {
	ModuleStyles,
};
