class GroupingRequiredFilterFunctions {

    public static Collection<?> matchesInGroup(Object... args) {
        // this is either '0', or it is the integer value of the last argument
        // when the argumentCount is odd
        int positionFromRight = 0;
        if (args.length % 2 != 0) { // it's odd
            Object lastArgument = args[args.length - 1];
            positionFromRight = Integer.parseInt(lastArgument.toString());
        }
        Collection<ValueTuple> leftSideMatches;
        Collection<ValueTuple> allMatches = new HashSet<>();
        Object fieldValue1 = args[0];
        String regex = args[1].toString();
        if (fieldValue1 instanceof Iterable) {
            // cast as Iterable in order to call the right getAllMatches method
            leftSideMatches = EvaluationPhaseFilterFunctions.getAllMatches((Iterable) fieldValue1, regex);
        } else {
            leftSideMatches = EvaluationPhaseFilterFunctions.getAllMatches(fieldValue1, regex);
        }
        for (ValueTuple currentMatch : leftSideMatches) {
            String matchFieldName = ValueTuple.getFieldName(currentMatch);
            // my fieldValue2 will be a collection that looks like [ AGE.FOO.7.1:1, GENDER.BAZ.7.2:2, NAME.FO.7.3:1 ]
            // I am only interested in a match on the one that ends with the 'tail' (.2) that I found above
            String context = EvaluationPhaseFilterFunctions.getMatchToRightOfPeriod(matchFieldName, positionFromRight);
            
            for (int i = 2; i < args.length; i += 2) {
                
                if (args[i] instanceof Iterable) {
                    for (Object fv : (Iterable) args[i]) {
                        manageMatchesInGroupRemainingArgs(fv, args[i + 1].toString(), context, allMatches, currentMatch);
                    }
                } else if (args[i] instanceof ValueTuple) {
                    manageMatchesInGroupRemainingArgs(args[i], args[i + 1].toString(), context, allMatches, currentMatch);
                }
            }
        }
        // if there was a match found at all levels, then the matches.size will be equal to the
        // number of field/regex pairs
        if (allMatches.size() < args.length / 2) { // truncated in case args.length was odd
            allMatches.clear();
        }
        return Collections.unmodifiableCollection(allMatches);
        
    }

}