/**
 * Permission Validator
 *
 * This method is used for validaing user and role permissions.  This method is given a single or and array
 * of permission nodes that the user has and it is also given the permission node that is required for whatever
 * query they are trying to execute, and this will determine if any of the permission nodes match or will
 * verify the given permission node.
 *
 * Special token types:
 * - Asterisk (*): verifies it's token and all following tokens.
 * - Question Mark (?): verifies it's token and only it's token.
 * - Inclusive List ([a,b,c]): verifies only the tokens in the list.
 * - Exclusive List (<a,b,c>): verifies all tokens except for the ones in the list.
 *
 * @param permission - The required permission
 * @param permissionExpressions - The owned permission(s)
 * @returns {boolean} Does the user have the permission?
 */
export function permissionValidator(
  permission: string,
  permissionExpressions: string | string[]
): boolean {
  if (typeof permissionExpressions === "string") {
    // If the second parameter is a string, treat it as a single expression
    permissionExpressions = [permissionExpressions];
  }

  // Iterate over each expression in the array and check if any of them match the permission
  for (const expression of permissionExpressions) {
    const rx = expression
      .replace(/\./g, "\\.")
      .replace(/\*/g, ".*")
      .replace(/\?/g, ".")
      .replace(/\[([^\]\[]*)\]/g, "($1)")
      .replace(/<([^<>]+)>/g, "(?:(?!$1)[^.])*")
      .replace(/,/g, "|");

    if (new RegExp(`^${rx}$`).test(permission)) {
      return true;
    }
  }

  return false;
}

/**
 * @TODO It's okay, you can't always get everything done and that is fine.
 * Just take a breath and move on, come back if you feel upto it.
 * What you make is good and whilst you can always do more,
 * you can't do everything. Nothing will ever be perfect,
 * so stop trying to be perfect and allow your self to move on
 * even if you know there is more you can do.
 */
