/** @license MIT | @cube-dev/ui-kit v0.0.0-canary-0d43332 | Cube Dev Team */
import { mergeProps } from "../../../utils/react/mergeProps.js";
import { useCombinedRefs } from "../../../utils/react/useCombinedRefs.js";
import { useEvent } from "../../../_internal/hooks/use-event.js";
import { Block } from "../../Block.js";
import { Space } from "../../layout/Space.js";
import { CloseIcon } from "../../../icons/CloseIcon.js";
import { PlusIcon } from "../../../icons/PlusIcon.js";
import { Button } from "../../actions/index.js";
import { Grid } from "../../layout/Grid.js";
import { Flow } from "../../layout/Flow.js";
import { useFormProps } from "../../form/Form/Form.js";
import { useFieldProps } from "../../form/Form/use-field/use-field-props.js";
import { wrapWithField } from "../../form/wrapper.js";
import { TextInput } from "../TextInput/TextInput.js";
import { _PasswordInput } from "../PasswordInput/PasswordInput.js";
import { _TextArea } from "../TextArea/TextArea.js";
import { ComboBox } from "../ComboBox/ComboBox.js";
import { forwardRef, useEffect, useMemo, useRef, useState } from "react";
import { jsx, jsxs } from "react/jsx-runtime";

//#region src/components/fields/TextInputMapper/TextInputMapper.tsx
const PROPS_GRID_HACK = { styles: { InputArea: { gridColumn: {
	"": "auto",
	"has-sider": "auto"
} } } };
function removeDuplicates(mappings) {
	const keys = /* @__PURE__ */ new Set();
	return mappings.filter(({ key }) => {
		if (keys.has(key)) return false;
		keys.add(key);
		return true;
	});
}
function TextInputMapper(props, ref) {
	ref = useCombinedRefs(ref);
	props = useFormProps(props);
	props = useFieldProps(props, {
		defaultValidationTrigger: "onChange",
		valuePropsMapper: ({ value, onChange }) => ({
			value: value != null ? value : {},
			onChange
		})
	});
	const counterRef = useRef(0);
	let { qa, isDisabled, actionLabel, value, onChange, keyProps, valueProps, KeyComponent, ValueComponent, size = "medium", form } = props;
	function extractLocalValues(value, localValues) {
		const valueKeys = Object.keys(value);
		localValues.map(({ key }) => key).forEach((key) => {
			if (!valueKeys.includes(key) && key !== "") localValues = localValues.filter(({ key: k }) => k !== key);
		});
		Object.entries(value ?? {}).forEach(([key, value]) => {
			const exist = localValues.find(({ key: k }) => k === key);
			if (exist) exist.value = value;
			else localValues.push({
				key,
				value,
				id: counterRef.current++
			});
		});
		return removeDuplicates(localValues);
	}
	const [mappings, setMappings] = useState(() => {
		return extractLocalValues(value ?? {}, []);
	});
	useEffect(() => {
		setMappings(extractLocalValues(value ?? {}, mappings));
	}, [JSON.stringify(value)]);
	const onMappingsChange = useEvent((newMappings) => {
		const newValue = newMappings.reduce((acc, { key, value }) => {
			acc[key.trim()] = value.trim();
			return acc;
		}, {});
		if (!Object.keys(newValue).length) onChange?.(void 0);
		else onChange?.(newValue);
		const updatedMappings = extractLocalValues(newValue ?? {}, newMappings);
		if (JSON.stringify(updatedMappings) !== JSON.stringify(mappings)) setMappings(updatedMappings);
	});
	const addNewMapping = useEvent(() => {
		setMappings((prev) => {
			return [...prev, {
				key: "",
				value: "",
				id: counterRef.current++
			}];
		});
	});
	const showNewButton = useMemo(() => {
		return !mappings.length || !mappings.some(({ key, value }) => !key || !value);
	}, [mappings]);
	KeyComponent = KeyComponent ?? TextInputMapperInput;
	ValueComponent = ValueComponent ?? TextInputMapperInput;
	const onKeyChange = useEvent((id, value) => {
		mappings.forEach((mapping) => {
			if (mapping.id === id) mapping.key = value;
		});
		setMappings([...mappings]);
	});
	const onValueChange = useEvent((id, value) => {
		mappings.forEach((mapping) => {
			if (mapping.id === id) mapping.value = value;
		});
		setMappings([...mappings]);
	});
	const onSubmit = useEvent(() => {
		onMappingsChange(mappings);
	});
	const onKeyDown = useEvent((e) => {
		if ((e.ctrlKey || e.metaKey) && e.key === "Enter" && showNewButton) addNewMapping();
	});
	const renderedMappings = useMemo(() => {
		return mappings.map((mapping, index) => {
			const { key, value, id } = mapping;
			return /* @__PURE__ */ jsxs(Grid, {
				qa: "Mapping",
				columns: "minmax(0, 1fr) minmax(0, 1fr) min-content",
				gap: "1x",
				children: [
					/* @__PURE__ */ jsx(KeyComponent, {
						autoFocus: index === mappings.length - 1,
						id,
						isDisabled,
						fieldType: "key",
						value: key,
						placeholder: "Key",
						size,
						onChange: onKeyChange,
						onSubmit,
						...keyProps
					}),
					/* @__PURE__ */ jsx(ValueComponent, {
						id,
						fieldType: "value",
						isDisabled: !key || isDisabled,
						value,
						placeholder: "Value",
						size,
						onChange: onValueChange,
						onSubmit,
						...valueProps
					}),
					/* @__PURE__ */ jsx(Button, {
						"aria-label": "Remove mapping",
						theme: "danger",
						type: "clear",
						size,
						icon: /* @__PURE__ */ jsx(CloseIcon, {}),
						onPress: () => {
							setMappings(mappings.filter((m) => m.id !== id));
							onMappingsChange(mappings.filter((m) => m.id !== id));
						}
					})
				]
			}, id);
		});
	}, [JSON.stringify(mappings)]);
	return wrapWithField(/* @__PURE__ */ jsxs(Flow, {
		ref,
		gap: "1x",
		"data-qa": qa || "TextInputMapper",
		"data-input-type": "textinputmapper",
		onKeyDown,
		children: [[...renderedMappings], showNewButton ? /* @__PURE__ */ jsxs(Space, {
			gap: 0,
			children: [/* @__PURE__ */ jsx(Block, {
				styles: {
					overflow: "clip",
					width: "max 0px"
				},
				children: "\xA0"
			}), /* @__PURE__ */ jsx(Button, {
				isDisabled,
				size,
				icon: /* @__PURE__ */ jsx(PlusIcon, {}),
				onPress: addNewMapping,
				children: actionLabel ? actionLabel : "Mapping"
			})]
		}) : null]
	}), ref, props);
}
function TextInputMapperInput(props) {
	const { id, fieldType, inputType = "input", options, value, size = "medium", placeholder, allowsCustomValue, ...rest } = props;
	const onChange = useEvent((newValue) => {
		props.onChange?.(id, newValue);
	});
	const onBlur = useEvent(() => {
		props.onSubmit?.(id);
	});
	const onSelectionChange = useEvent((newValue) => {
		if (!allowsCustomValue && !options?.includes(newValue)) props.onChange?.(id, "");
		else props.onChange?.(id, newValue);
		props.onSubmit?.(id);
	});
	const Component = {
		input: TextInput,
		textarea: _TextArea,
		password: _PasswordInput
	}[inputType];
	if (inputType === "combobox") return /* @__PURE__ */ jsx(ComboBox, {
		qa: "AddMapping",
		"data-type": fieldType,
		width: "auto",
		size,
		...mergeProps(rest, PROPS_GRID_HACK),
		id: void 0,
		inputValue: value,
		selectedKey: value,
		labelPosition: "top",
		"aria-label": placeholder,
		placeholder,
		allowsCustomValue,
		onInputChange: onChange,
		onSelectionChange: (val) => onSelectionChange(val ?? ""),
		children: (options ?? []).map((option) => /* @__PURE__ */ jsx(ComboBox.Item, { children: option }, option))
	});
	return /* @__PURE__ */ jsx(Component, {
		qa: "AddMapping",
		"data-type": fieldType,
		width: "auto",
		rows: 1,
		size,
		...mergeProps(rest, PROPS_GRID_HACK),
		id: void 0,
		value,
		labelPosition: "top",
		"aria-label": placeholder,
		placeholder,
		onChange,
		onBlur
	});
}
const _TextInputMapper = forwardRef(TextInputMapper);
_TextInputMapper.displayName = "TextInputMapper";

//#endregion
export { _TextInputMapper };
//# sourceMappingURL=TextInputMapper.js.map