package org.batfish.datamodel.answers;

import static com.google.common.base.MoreObjects.toStringHelper;
import static org.apache.commons.lang3.ObjectUtils.firstNonNull;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.Objects;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.annotation.ParametersAreNonnullByDefault;

@ParametersAreNonnullByDefault
public final class AutocompleteSuggestion {

  public enum CompletionType {
    BGP_PEER_PROPERTY,
    BGP_PROCESS_PROPERTY,
    INTERFACE_PROPERTY,
    NAMED_STRUCTURE,
    NODE,
    NODE_PROPERTY,
    OSPF_PROPERTY
  }

  private static final String PROP_DESCRIPTION = "description";
  private static final String PROP_INSERTION_INDEX = "insertionIndex";
  private static final String PROP_IS_PARTIAL = "isPartial";
  private static final String PROP_RANK = "rank";
  private static final String PROP_TEXT = "text";

  public static final int DEFAULT_RANK = Integer.MAX_VALUE;

  @Nullable private final String _description;
  private final int _insertionIndex;
  private final boolean _isPartial;
  private int _rank;
  @Nonnull private final String _text;

  @JsonCreator
  private static @Nonnull AutocompleteSuggestion create(
      @Nullable @JsonProperty(PROP_TEXT) String text,
      @JsonProperty(PROP_IS_PARTIAL) boolean isPartial,
      @Nullable @JsonProperty(PROP_DESCRIPTION) String description,
      @JsonProperty(PROP_RANK) int rank,
      @JsonProperty(PROP_INSERTION_INDEX) int insertionIndex) {
    return new AutocompleteSuggestion(
        firstNonNull(text, ""), isPartial, description, rank, insertionIndex);
  }

  public AutocompleteSuggestion(String text, boolean isPartial) {
    this(text, isPartial, null, DEFAULT_RANK);
  }

  public AutocompleteSuggestion(String text, boolean isPartial, @Nullable String description) {
    this(text, isPartial, description, DEFAULT_RANK);
  }

  public AutocompleteSuggestion(
      String text, boolean isPartial, @Nullable String description, int rank) {
    this(text, isPartial, description, rank, 0);
  }

  public AutocompleteSuggestion(
      String text, boolean isPartial, @Nullable String description, int rank, int insertionIndex) {
    _text = text;
    _isPartial = isPartial;
    _description = description;
    _rank = rank;
    _insertionIndex = insertionIndex;
  }

  @Override
  public boolean equals(Object o) {
    if (!(o instanceof AutocompleteSuggestion)) {
      return false;
    }
    // ignore rank and description
    return Objects.equals(_isPartial, ((AutocompleteSuggestion) o)._isPartial)
        && Objects.equals(_text, ((AutocompleteSuggestion) o)._text)
        && Objects.equals(_insertionIndex, ((AutocompleteSuggestion) o)._insertionIndex);
  }

  @JsonProperty(PROP_DESCRIPTION)
  @Nullable
  public String getDescription() {
    return _description;
  }

  @JsonProperty(PROP_INSERTION_INDEX)
  public int getInsertionIndex() {
    return _insertionIndex;
  }

  @JsonProperty(PROP_IS_PARTIAL)
  public boolean getIsPartial() {
    return _isPartial;
  }

  @JsonProperty(PROP_RANK)
  public int getRank() {
    return _rank;
  }

  @JsonProperty(PROP_TEXT)
  @Nonnull
  public String getText() {
    return _text;
  }

  @Override
  public int hashCode() {
    // ignore rank and description
    return Objects.hash(_isPartial, _text, _insertionIndex);
  }

  public void setRank(int rank) {
    _rank = rank;
  }

  @Override
  public String toString() {
    return toStringHelper(getClass())
        .add(PROP_DESCRIPTION, _description)
        .add(PROP_INSERTION_INDEX, _insertionIndex)
        .add(PROP_IS_PARTIAL, _isPartial)
        .add(PROP_RANK, _rank)
        .add(PROP_TEXT, _text)
        .toString();
  }
}

@@ -737,16 +737,66 @@
 ption%22;%0A
+  private static final String PROP_HINT = %22hint%22;%0A
   privat
@@ -1087,146 +1087,703 @@
 %0A%0A  
-@Nullable private final String _description;%0A  private final int _insertionIndex;%0A  private final boolean _isPartial;%0A  private int _rank;
+/** Some helpful text about what the suggestion specifies */%0A  @Nullable private final String _description;%0A%0A  /**%0A   * Short text to show the user how to complete a partial suggestion. Should be provided for every%0A   * partial suggestion.%0A   */%0A  @Nullable private final String _hint;%0A%0A  /** Index in the input query string where the suggestion text should be inserted */%0A  private final int _insertionIndex;%0A%0A  /**%0A   * True if the suggestion text is only partially valid and requires additional input to become%0A   * valid%0A   */%0A  private final boolean _isPartial;%0A%0A  /** Relevance of the suggestion relative to other suggestions */%0A  private int _rank;%0A%0A  /** Actual text of the suggestion */
 %0A  @
@@ -2162,32 +2162,86 @@
 t insertionIndex
+,%0A      @Nullable @JsonProperty(PROP_HINT) String hint
 ) %7B%0A    return n
@@ -2335,32 +2335,38 @@
 , insertionIndex
+, hint
 );%0A  %7D%0A%0A  public
@@ -2926,24 +2926,283 @@
 ionIndex) %7B%0A
+    this(text, isPartial, description, rank, insertionIndex, null);%0A  %7D%0A%0A  public AutocompleteSuggestion(%0A      String text,%0A      boolean isPartial,%0A      @Nullable String description,%0A      int rank,%0A      int insertionIndex,%0A      @Nullable String hint) %7B%0A
     _text = 
@@ -3315,32 +3315,50 @@
 insertionIndex;%0A
+    _hint = hint;%0A
   %7D%0A%0A  @Override
@@ -3733,32 +3733,101 @@
 _insertionIndex)
+%0A        && Objects.equals(_hint, ((AutocompleteSuggestion) o)._hint)
 ;%0A  %7D%0A%0A  @JsonPr
@@ -3924,24 +3924,114 @@
 ption;%0A  %7D%0A%0A
+  @JsonProperty(PROP_HINT)%0A  @Nullable%0A  public String getHint() %7B%0A    return _hint;%0A  %7D%0A%0A
   @JsonPrope
@@ -4703,16 +4703,47 @@
 iption)%0A
+        .add(PROP_HINT, _hint)%0A
         

add hint field to AutocompleteSuggestion (#3716)