/**
 * @since Last modified: 2024-07-10 16:24:40
 * @function arrSearch
 * @description Retrieve array data from an array based on multiple keywords and obtain the weight of each keyword in each item.
 * @param  {string|string[]} keys - Keywords to search for.
 * @param  {string|string[]} [props='label'] - Properties to search for.
 * @param  {object[]} source - Data to search for.
 * @param  {boolean} [fuzzy=true] - Whether to perform a fuzzy search.
 * @param  {number} [limit=0] - Whether to limit the number of search results.
 * @param  {boolean} [order=''|'desc'|'asc'] - Whether to sort the search result array by relevance.
 * @param  {boolean} [ignore=true] - Whether to ignore case sensitivity.
 * @param  {string} [hyphen=','] - Separator of keys or props.
 * @returns {boolean} Return new array with weight property.
 * @see {@link https://codepen.io/axui/pen/MWdGvbL|demo @ codepen}
 * @example
 * ax.arrSearch({keys:'a',props:'x',source:[{x:'abca',y:''},{x:'are',y:''}...]});
 * <!--return [{source:{x:'abca',y:''},keys:['a'],weight:2},{source:{x:'are',y:''},keys:['a'],weight:1}]-->
 */
'use strict';
import ax from "../ax";
import arrSort from "./arrSort";
import clearRegx from "./clearRegx";
import getDataType from "./getDataType";
import isEmpty from "./isEmpty";
import valToArr from "./valToArr";
const arrSearch = ({ keys, props = 'label', source = [], fuzzy = true, limit = 0, order = '', ignore = true, hyphen = ax.config.splitHyphen }) => {
    if (isEmpty(keys) || isEmpty(props) || isEmpty(source)) {
        return [];
    }
    let keysArr = valToArr(keys, hyphen).map((k) => clearRegx(k)).filter(Boolean), propsArr = valToArr(props, hyphen), crudeArr = [], regStr = '(' + keysArr.join('|') + ')', regExp = new RegExp(regStr, `${ignore ? 'i' : ''}g`), lowerSet = (arr) => [...new Set(arr.map((k) => k.toLowerCase()))];
    for (let v of source) {
        let valueStr = propsArr.map(k => v[k]).join('■'), valueMatch = valueStr.match(regExp), valueObj = {}, keysMatch = [];
        if (valueMatch) {
            keysMatch = [...new Set(valueMatch)];
            valueObj = { source: v, weight: valueMatch.length, keys: keysMatch };
            if (!fuzzy) {
                if (ignore) {
                    (lowerSet(keysArr).length === lowerSet(keysMatch).length) && crudeArr.push(valueObj);
                }
                else {
                    (keysArr.length === keysMatch.length) && crudeArr.push(valueObj);
                }
            }
            else {
                crudeArr.push(valueObj);
            }
        }
    }
    if (order) {
        let orderType = getDataType(order), basis;
        if (orderType === 'String') {
            basis = order === 'desc' ? { key: 'weight', dir: 'desc' } : order === 'asc' ? { key: 'weight', dir: 'asc' } : '';
        }
        else if (orderType === 'Boolean' && order === true) {
            basis = { key: 'weight', dir: 'desc' };
        }
        else {
            basis = order;
        }
        arrSort(crudeArr, basis);
    }
    (limit && crudeArr.length > limit) && crudeArr.splice(limit);
    return crudeArr;
};
export default arrSearch;
