class AutoCompleteUtils {

  @Nonnull
  public static ImmutableList<AutocompleteSuggestion> ipStringAutoComplete(
      @Nullable String query, Map<Ip, IpCompletionMetadata> ips) {

    String testQuery = query == null ? "" : query.toLowerCase();

    // when the query has multiple words, each of those words should match
    String[] subQueries = testQuery.split("\\s+");

    // find matching IPs
    Set<Ip> ipMatches =
        ips.keySet().stream()
            .filter(e -> Arrays.stream(subQueries).allMatch(sq -> e.toString().contains(sq)))
            .collect(ImmutableSet.toImmutableSet());

    // find relevance matches
    List<AutocompleteSuggestion> relevanceMatches =
        ips.entrySet().stream()
            .filter(e -> !ipMatches.contains(e.getKey()))
            .map(
                e ->
                    new SimpleEntry<>(
                        e.getKey(),
                        e.getValue().getRelevances().stream()
                            .filter(r -> r.matches(subQueries, e.getKey()))
                            .collect(ImmutableList.toImmutableList())))
            .filter(e -> !e.getValue().isEmpty())
            .map(
                e ->
                    AutocompleteSuggestion.builder()
                        .setText(e.getKey().toString())
                        .setDescription(toDescription(e.getValue()))
                        .setSuggestionType(SuggestionType.ADDRESS_LITERAL)
                        .build())
            .collect(ImmutableList.toImmutableList());

    return new ImmutableList.Builder<AutocompleteSuggestion>()
        .addAll(
            ipMatches.stream()
                .map(
                    ip ->
                        AutocompleteSuggestion.builder()
                            .setText(ip.toString())
                            .setDescription(toDescription(ips.get(ip)))
                            .setSuggestionType(SuggestionType.ADDRESS_LITERAL)
                            .build())
                .collect(ImmutableList.toImmutableList()))
        .addAll(relevanceMatches)
        .build();
  }

}