/**
 * `Intl.Collator`-backed case/diacritics-insensitive filter used by the
 * combobox for client-side item filtering. Port of the runtime logic in
 * `packages/react/src/internals/filter.ts` + the `createCollatorItemFilter`
 * / `createSingleSelectionCollatorFilter` helpers from
 * `packages/react/src/combobox/root/utils/index.ts`. No framework-specific
 * shape — the React hook (`useCoreFilter`) collapses to a plain factory in
 * Solid since `getFilter` itself is already memoised via a module-level
 * cache.
 */

import { stringifyAsLabel } from "./resolve-value-label.jsx";
const filterCache = new Map();
function stringifyLocale(locale) {
  if (Array.isArray(locale)) {
    return locale.map(value => stringifyLocale(value)).join(",");
  }
  if (locale == null) return "";
  return String(locale);
}
export function getFilter(options = {}) {
  const mergedOptions = {
    usage: "search",
    sensitivity: "base",
    ignorePunctuation: true,
    ...options
  };
  const cacheKey = `${stringifyLocale(options.locale)}|${JSON.stringify(mergedOptions)}`;
  const cached = filterCache.get(cacheKey);
  if (cached) return cached;
  const collator = new Intl.Collator(options.locale, mergedOptions);
  const filter = {
    contains(item, query, itemToString) {
      if (!query) return true;
      const itemString = stringifyAsLabel(item, itemToString);
      for (let i = 0; i <= itemString.length - query.length; i += 1) {
        if (collator.compare(itemString.slice(i, i + query.length), query) === 0) {
          return true;
        }
      }
      return false;
    },
    startsWith(item, query, itemToString) {
      if (!query) return true;
      const itemString = stringifyAsLabel(item, itemToString);
      return collator.compare(itemString.slice(0, query.length), query) === 0;
    },
    endsWith(item, query, itemToString) {
      if (!query) return true;
      const itemString = stringifyAsLabel(item, itemToString);
      const queryLength = query.length;
      return itemString.length >= queryLength && collator.compare(itemString.slice(itemString.length - queryLength), query) === 0;
    }
  };
  filterCache.set(cacheKey, filter);
  return filter;
}

/**
 * Case-insensitive "item contains query" filter — matches the React
 * `createCollatorItemFilter` helper.
 */
export function createCollatorItemFilter(collatorFilter, itemToStringLabel) {
  return (item, query) => {
    if (item == null) return false;
    const itemString = stringifyAsLabel(item, itemToStringLabel);
    return collatorFilter.contains(itemString, query);
  };
}

/**
 * Single-select filter that shows all items when the query is empty or
 * matches the current selection. Mirrors React's
 * `createSingleSelectionCollatorFilter`.
 */
export function createSingleSelectionCollatorFilter(collatorFilter, itemToStringLabel, selectedValue) {
  return (item, query) => {
    if (item == null) return false;
    if (!query) return true;
    const itemString = stringifyAsLabel(item, itemToStringLabel);
    const selectedString = selectedValue != null ? stringifyAsLabel(selectedValue, itemToStringLabel) : "";
    if (selectedString && collatorFilter.contains(selectedString, query) && selectedString.length === query.length) {
      return true;
    }
    return collatorFilter.contains(itemString, query);
  };
}
//# sourceMappingURL=filter.jsx.map
