import { C as toFullOption, S as toFlatOptionArray, b as isFlexibleOptionArray, g as processMatchMode, w as toFullOptionList, x as isFlexibleOptionGroupArray } from "./utils-nQU7WCM9.mjs";
import { a as lc, t as isRuleGroup } from "./isRuleGroup-DztIOOKa.mjs";
import { produce } from "immer";

//#region src/utils/filterFieldsByComparator.ts
const filterByComparator = (field, operator, fieldToCompare) => {
	const fullField = toFullOption(field);
	const fullFieldToCompare = toFullOption(fieldToCompare);
	if (fullField.value === fullFieldToCompare.value) return false;
	if (typeof fullField.comparator === "string") return fullField[fullField.comparator] === fullFieldToCompare[fullField.comparator];
	return fullField.comparator?.(fullFieldToCompare, operator) ?? false;
};
/**
* For a given {@link FullField}, returns the `fields` list filtered for
* other fields that match by `comparator`. Only fields *other than the
* one in question* will ever be included, even if `comparator` is `null`
* or `undefined`. If `comparator` is a string, fields with the same value
* for that property will be included. If `comparator` is a function, each
* field will be passed to the function along with the `operator` and fields
* for which the function returns `true` will be included.
*
* @group Option Lists
*/
const filterFieldsByComparator = (field, fields, operator) => {
	if (!field.comparator) {
		const filterOutSameField = (f) => (f.value ?? f.name) !== (field.value ?? field.name);
		if (isFlexibleOptionGroupArray(fields)) return fields.map((og) => ({
			...og,
			options: og.options.filter((v) => filterOutSameField(v))
		}));
		return fields.filter((v) => filterOutSameField(v));
	}
	if (isFlexibleOptionGroupArray(fields)) return fields.map((og) => ({
		...og,
		options: og.options.filter((f) => filterByComparator(field, operator, f))
	})).filter((og) => og.options.length > 0);
	return fields.filter((f) => filterByComparator(field, operator, f));
};

//#endregion
//#region src/utils/getValueSourcesUtil.ts
const defaultValueSourcesArray = [{
	name: "value",
	value: "value",
	label: "value"
}];
const dummyFD = {
	name: "name",
	value: "name",
	valueSources: null,
	label: "label"
};
/**
* Utility function to get the value sources array for the given
* field and operator. If the field definition does not define a
* `valueSources` property, the `getValueSources` prop is used.
* Returns `[FullOption<"value">]` by default.
*/
const getValueSourcesUtil = (fieldData, operator, getValueSources) => {
	const fd = fieldData ? toFullOption(fieldData) : dummyFD;
	let valueSourcesNEW = fd.valueSources ?? false;
	if (typeof valueSourcesNEW === "function") valueSourcesNEW = valueSourcesNEW(operator);
	if (!valueSourcesNEW && getValueSources) valueSourcesNEW = getValueSources(fd.value, operator, { fieldData: fd });
	if (!valueSourcesNEW) return defaultValueSourcesArray;
	if (isFlexibleOptionArray(valueSourcesNEW)) return toFullOptionList(valueSourcesNEW);
	return valueSourcesNEW.map((vs) => defaultValueSourcesArray.find((dmm) => dmm.value === lc(vs)) ?? {
		name: vs,
		value: vs,
		label: vs
	});
};

//#endregion
//#region src/utils/parserUtils.ts
const getFieldsArray = (fields) => {
	return toFlatOptionArray(fields ? Array.isArray(fields) ? fields : Object.keys(fields).map((fld) => Object.assign({}, fields[fld], { name: fld })).sort((a, b) => a.label.localeCompare(b.label)) : []);
};
function fieldIsValidUtil(params) {
	const { fieldsFlat, fieldName, operator, subordinateFieldName, getValueSources } = params;
	const vsIncludes = (vs) => {
		const vss = getValueSourcesUtil(primaryField, operator, getValueSources);
		return isFlexibleOptionArray(vss) && vss.some((vso) => vso.value === vs || vso.name === vs);
	};
	if (fieldsFlat.length === 0) return true;
	let valid = false;
	const primaryField = toFullOption(fieldsFlat.find((ff) => ff.name === fieldName));
	if (primaryField) {
		valid = !(!subordinateFieldName && operator !== "notNull" && operator !== "null" && !vsIncludes("value"));
		if (valid && !!subordinateFieldName) if (vsIncludes("field") && fieldName !== subordinateFieldName) {
			if (!filterFieldsByComparator(primaryField, fieldsFlat, operator).some((vsf) => vsf.name === subordinateFieldName)) valid = false;
		} else valid = false;
	}
	return valid;
}

//#endregion
//#region src/utils/generateID.ts
const cryptoModule = globalThis.crypto;
/**
* Default `id` generator. Generates a valid v4 UUID. Uses `crypto.randomUUID()`
* when available, otherwise uses an alternate method based on `getRandomValues`.
* The returned string is guaranteed to match this regex:
* ```
* /^[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i
* ```
* @returns Valid v4 UUID
*/
// istanbul ignore next
let generateID = () => "00-0-4-2-000".replaceAll(/[^-]/g, (s) => ((Math.random() + Math.trunc(s)) * 65536 >> Number.parseInt(s)).toString(16).padStart(4, "0"));
// istanbul ignore else
if (cryptoModule) {
	// istanbul ignore else
	if (typeof cryptoModule.randomUUID === "function") generateID = () => cryptoModule.randomUUID();
	else if (typeof cryptoModule.getRandomValues === "function") {
		const position19vals = "89ab";
		const container = new Uint32Array(32);
		generateID = () => {
			cryptoModule.getRandomValues(container);
			let id = (container[0] % 16).toString(16);
			for (let i = 1; i < 32; i++) {
				if (i === 12) id = `${id}4`;
				else if (i === 16) id = `${id}${position19vals[container[17] % 4]}`;
				else id = `${id}${(container[i] % 16).toString(16)}`;
				if (i === 7 || i === 11 || i === 15 || i === 19) id = `${id}-`;
			}
			return id;
		};
	}
}

//#endregion
//#region src/utils/prepareQueryObjects.ts
/**
* Ensures that a rule is valid by adding an `id` property if it does not already exist.
*/
const prepareRule = (rule, { idGenerator = generateID } = {}) => produce(rule, (draft) => {
	if (!draft.id) draft.id = idGenerator();
	if (processMatchMode(draft)) draft.value = prepareRuleGroup(draft.value, { idGenerator });
});
/**
* Ensures that a rule group is valid by recursively adding an `id` property to the group itself
* and all its rules and subgroups where one does not already exist.
*/
const prepareRuleGroup = (queryObject, { idGenerator = generateID } = {}) => produce(queryObject, (draft) => {
	if (!draft.id) draft.id = idGenerator();
	draft.rules = draft.rules.map((r) => typeof r === "string" ? r : isRuleGroup(r) ? prepareRuleGroup(r, { idGenerator }) : prepareRule(r, { idGenerator }));
});

//#endregion
export { fieldIsValidUtil as n, getFieldsArray as r, prepareRuleGroup as t };
//# sourceMappingURL=prepareQueryObjects-BBayjIn2.mjs.map