package org.checkerframework.framework.util.defaults;

import java.util.Objects;
import javax.lang.model.element.AnnotationMirror;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.checkerframework.framework.qual.TypeUseLocation;
import org.checkerframework.javacutil.AnnotationUtils;

/**
 * Represents a mapping from an Annotation to a TypeUseLocation it should be applied to during
 * defaulting. The Comparable ordering of this class first tests location then tests annotation
 * ordering (via {@link org.checkerframework.javacutil.AnnotationUtils}).
 *
 * <p>It also has a handy toString method that is useful for debugging.
 */
public class Default implements Comparable<Default> {
  // please remember to add any fields to the hashcode calculation
  public final AnnotationMirror anno;
  public final TypeUseLocation location;

  public Default(final AnnotationMirror anno, final TypeUseLocation location) {
    this.anno = anno;
    this.location = location;
  }

  @Override
  public int compareTo(Default other) {
    int locationOrder = location.compareTo(other.location);
    if (locationOrder == 0) {
      return AnnotationUtils.compareAnnotationMirrors(anno, other.anno);
    } else {
      return locationOrder;
    }
  }

  @Override
  public boolean equals(@Nullable Object thatObj) {
    if (thatObj == this) {
      return true;
    }

    if (thatObj == null || thatObj.getClass() != Default.class) {
      return false;
    }

    return compareTo((Default) thatObj) == 0;
  }

  @Override
  public int hashCode() {
    return Objects.hash(anno, location);
  }

  @Override
  public String toString() {
    return "( " + location.name() + " => " + anno + " )";
  }
}
