import {isArray} from '@ember/array';

/**
 * This util defines a single function `match`. It is used internally, expecially by the current user service
 * (in `currentUser.match()`), but there is no reason that this cannot also be imported by your app if it is
 * required. To import this function, use the following code:
 *
 * ```js
 * import match from '@bennerinformatics/ember-fw-gc/utils/match';
 * ```
 *
 * The function itself matches a permission array (`haystack`) to a flat list of
 * available items the user has (`needle`), and thus these are its two parameters:
 *
 * - `needle` - flat array of available roles/apps/depts (of the current user)
 * - `haystack` - array of roles/apps/depts to check against
 *
 * This function can be used to check for apps, roles or departments the user has access to.
 * How this function works: the roles/list of roles passed in via `haystack`
 * are matched using an 'and/or' setup. If `haystack` is an array, it treats each role
 * in `haystack` as an "OR" requirement. If roles is an array and one of the items in
 * that array is a sub-array of roles, that sub-array is treated with an "AND" rule.
 *
 * Example:
 * ```javascript
 * // say in this example that the needle of user roles is both 'admin' and 'base'
 * match(needle, ['admin', 'supervisor']); // needle must contain either 'admin' OR 'supervisor'. RETURNS true
 * match(needle, [['admin', 'supervisor']]); // needle must contain both 'admin' AND 'supervisor'. RETURNS false
 * match(needle, [['stats', 'supervisor'], 'admin']); // needle must contain both 'supervisor' AND 'stats' OR 'admin'. RETURNS true
 *  ```
 * @class MatchUtil
 * @module Utils
*/
/**
 * See description above
 * @public
 * @method match
 * @param {Array} needle flat array of available roles
 * @param {Array|String} haystack array of role rules to check
 */
export default function (needle, haystack) {
    if (!isArray(needle)) {
        needle = [needle];
    }

    // if given a single item, flat match
    if (!isArray(haystack)) {
        return needle.includes(haystack);
    }
    // if given an array, any must match
    return haystack.some((hay) => {
        // if the element is a single item, it must match
        if (!isArray(hay)) {
            return needle.includes(hay);
        }
        // if given an array, all must match
        return hay.every((straw) => needle.includes(straw));
    });
}