package org.checkerframework.framework.type;

import java.util.Objects;
import org.checkerframework.checker.nullness.qual.Nullable;

/** Represents upper and lower bounds, each an AnnotatedTypeMirror. */
public class AnnotatedTypeParameterBounds {
  private final AnnotatedTypeMirror upper;
  private final AnnotatedTypeMirror lower;

  public AnnotatedTypeParameterBounds(AnnotatedTypeMirror upper, AnnotatedTypeMirror lower) {
    this.upper = upper;
    this.lower = lower;
  }

  public AnnotatedTypeMirror getUpperBound() {
    return upper;
  }

  public AnnotatedTypeMirror getLowerBound() {
    return lower;
  }

  @Override
  public String toString() {
    return "[extends " + upper + " super " + lower + "]";
  }

  /**
   * Return a possibly-verbose string representation of this.
   *
   * @param verbose if true, returned representation is verbose
   * @return a possibly-verbose string representation of this
   */
  public String toString(boolean verbose) {
    return "[extends " + upper.toString(verbose) + " super " + lower.toString(verbose) + "]";
  }

  @Override
  public int hashCode() {
    return Objects.hash(upper, lower);
  }

  @Override
  public boolean equals(@Nullable Object obj) {
    if (!(obj instanceof AnnotatedTypeParameterBounds)) {
      return false;
    }
    AnnotatedTypeParameterBounds other = (AnnotatedTypeParameterBounds) obj;
    return this.upper == null
        ? other.upper == null
        : (this.upper.equals(other.upper) && this.lower == null)
            ? other.lower == null
            : this.lower.equals(other.lower);
  }
}
