class ParboiledAutoComplete {

  @VisibleForTesting
  Set<ParboiledAutoCompleteSuggestion> autoCompletePotentialMatch(PotentialMatch pm) {
    switch (pm.getAnchorType()) {
      case ADDRESS_GROUP_NAME:
        return autoCompleteReferenceBookEntity(pm);
      case ONE_APP_ICMP:
      case ONE_APP_ICMP_TYPE:
      case APP_ICMP_TYPE:
      case APP_ICMP_TYPE_CODE:
        // don't help with numbers
        return ImmutableSet.of();
      case APP_NAME:
        return autoCompleteAppName(pm);
      case APP_PORT:
      case APP_PORT_RANGE:
        // don't help with numbers
        return ImmutableSet.of();
      case CHAR_LITERAL:
        return autoCompleteLiteral(pm);
      case EOI:
        return ImmutableSet.of();
      case ENUM_SET_VALUE:
        return autoCompleteEnumSetValue(pm);
      case FILTER_INTERFACE_IN:
      case FILTER_INTERFACE_OUT:
        // Should delegate to interface spec
        throw new IllegalStateException(String.format("Unexpected auto completion for %s", pm));
      case FILTER_NAME:
        return autoCompleteGeneric(pm, _grammar);
      case FILTER_NAME_REGEX:
        return ImmutableSet.of(
            new ParboiledAutoCompleteSuggestion(
                "", pm.getMatchPrefix().length() + pm.getMatchStartIndex(), FILTER_NAME_REGEX));
      case FILTER_PARENS:
        // Other filter rules appear later in the path
        throw new IllegalStateException(String.format("Unexpected auto completion for %s", pm));
      case INTERFACE_GROUP_NAME:
        return autoCompleteReferenceBookEntity(pm);
      case INTERFACE_NAME:
        return autoCompleteInterfaceName(pm);
      case INTERFACE_NAME_REGEX:
        return ImmutableSet.of(
            new ParboiledAutoCompleteSuggestion(
                "", pm.getMatchPrefix().length() + pm.getMatchStartIndex(), INTERFACE_NAME_REGEX));
      case INTERFACE_PARENS:
        // Other interface rules appear later in the path
        throw new IllegalStateException(String.format("Unexpected auto completion for %s", pm));
      case INTERFACE_TYPE:
      case INTERFACE_VRF:
      case INTERFACE_ZONE:
        // These rely on type, vrf, or zone completion that appear later in the path
        throw new IllegalStateException(String.format("Unexpected auto completion for %s", pm));
      case IP_ADDRESS:
        return autoCompleteGeneric(pm, _grammar);
      case IP_ADDRESS_MASK:
        // can't help with masks
        return ImmutableSet.of();
      case IP_PROTOCOL_NAME:
        return autoCompleteIpProtocolName(pm);
      case IP_PROTOCOL_NUMBER:
        // don't help with numbers
        return ImmutableSet.of();
      case IP_PREFIX:
        return autoCompleteGeneric(pm, _grammar);
      case IP_RANGE:
        // Relies on IP_ADDRESS completion as it appears later in the path
        throw new IllegalStateException(String.format("Unexpected auto completion for %s", pm));
      case IP_WILDCARD:
        // Relies on IP_ADDRESS and IP_ADDRESS_MASK completions as they appear later in the path
        throw new IllegalStateException(String.format("Unexpected auto completion for %s", pm));
      case LOCATION_PARENS:
        // Other location rules appear later in the path
        throw new IllegalStateException(String.format("Unexpected auto completion for %s", pm));
      case NAME_SET_NAME:
        return autoCompleteGeneric(pm, _grammar);
      case NODE_AND_INTERFACE:
        // Node or Interface based anchors should appear later in the path
        throw new IllegalStateException(String.format("Unexpected auto completion for %s", pm));
      case NODE_NAME:
        return autoCompleteGeneric(pm, _grammar);
      case NODE_NAME_REGEX:
        return ImmutableSet.of(
            new ParboiledAutoCompleteSuggestion(
                "", pm.getMatchPrefix().length() + pm.getMatchStartIndex(), NODE_NAME_REGEX));
      case NODE_PARENS:
        // Other node rules appear later in the path
        throw new IllegalStateException(String.format("Unexpected auto completion for %s", pm));
      case NODE_ROLE_AND_DIMENSION:
        // Role and dimension name rules appear later in the path
        throw new IllegalStateException(String.format("Unexpected auto completion for %s", pm));
      case NODE_ROLE_DIMENSION_NAME:
        return autoCompleteGeneric(pm, _grammar);
      case NODE_ROLE_NAME:
        return autoCompleteNodeRoleName(pm);
      case NODE_TYPE:
        // Relies on STRING_LITERAL completion as it appears later in the path
        throw new IllegalStateException(String.format("Unexpected auto completion for %s", pm));
      case REFERENCE_BOOK_AND_ADDRESS_GROUP:
      case REFERENCE_BOOK_AND_INTERFACE_GROUP:
        // Reference book name and address/interface group name should appear later in the path
        throw new IllegalStateException(String.format("Unexpected auto completion for %s", pm));
      case REFERENCE_BOOK_NAME:
        return autoCompleteGeneric(pm, _grammar);
      case ROUTING_POLICY_NAME:
        return autoCompleteGeneric(pm, _grammar);
      case ROUTING_POLICY_NAME_REGEX:
        return ImmutableSet.of(
            new ParboiledAutoCompleteSuggestion(
                "",
                pm.getMatchPrefix().length() + pm.getMatchStartIndex(),
                ROUTING_POLICY_NAME_REGEX));
      case ROUTING_POLICY_PARENS:
        // Other routing policy rules appear later in the path
        throw new IllegalStateException(String.format("Unexpected auto completion for %s", pm));
      case STRING_LITERAL:
        return autoCompleteLiteral(pm);
      case VRF_NAME:
        return autoCompleteGeneric(pm, _grammar);
      case WHITESPACE:
        // nothing useful to suggest for these completion types
        return ImmutableSet.of();
      case ZONE_NAME:
        return autoCompleteGeneric(pm, _grammar);
      default:
        throw new IllegalArgumentException("Unhandled completion type " + pm.getAnchorType());
    }
  }

    ParboiledAutoComplete(
      CommonParser parser,
      Grammar grammar,
      Map<String, Anchor.Type> completionTypes,
      String network,
      String snapshot,
      String query,
      int maxSuggestions,
      CompletionMetadata completionMetadata,
      NodeRolesData nodeRolesData,
      ReferenceLibrary referenceLibrary);
    ParboiledAutoComplete(
      Grammar grammar,
      Rule inputRule,
      Map<String, Anchor.Type> completionTypes,
      String network,
      String snapshot,
      String query,
      int maxSuggestions,
      CompletionMetadata completionMetadata,
      NodeRolesData nodeRolesData,
      ReferenceLibrary referenceLibrary);

}