import { useMemo, useCallback } from 'react';
// eslint-disable-next-line you-dont-need-lodash-underscore/get
import get from 'lodash-es/get';
export const defaultFilter = (it, searchValue, searchFields) => !searchValue ||
// match all if no search value provided
searchFields.some(field => String(get(it, field)).toLowerCase().includes(searchValue.trim().toLowerCase()));

/**
 * Values that start with a search pattern, should come first in the list of filtered typeahead option
 */
export const prioritizeStartsWithValue = (optionA, optionB, searchFields, searchPattern) => {
  if (searchPattern.length < 3 ||
  // wait for the length to be meaningful
  searchFields.length !== 1 // multiple search fields might make the logic unnecessarily complex
  ) {
    return 0;
  }
  const optionAValue = String(get(optionA, searchFields[0]));
  const optionBValue = String(get(optionB, searchFields[0]));
  if (optionBValue.startsWith(searchPattern)) {
    return 1;
  }
  if (optionAValue.startsWith(searchPattern)) {
    return -1;
  }
  return 0;
};

/**
 * Filters a list of options with searchValue
 *
 * @param {array} options - An array of objects which should be filtered.
 * @param {string} searchValue - String value to match against, used as a search query.
 * @param {array} searchFields - An array of keys which should be checked on each options object.
 * @param {func} filterFunction - Custom predicate function for filtering
 * @returns {array} - Options array filtered by the search query.
 */
export default function useFilterOptions(options, searchValue, searchFields, filterFunction = defaultFilter) {
  const trimmedLowercaseValue = searchValue.trim().toLowerCase();
  const filterPredicate = useCallback(it => filterFunction(it, trimmedLowercaseValue, searchFields), [filterFunction, trimmedLowercaseValue, searchFields]);
  return useMemo(() => options.filter(filterPredicate).sort((a, b) => prioritizeStartsWithValue(a, b, searchFields, trimmedLowercaseValue)), [options, filterPredicate]);
}