package com.episode6.hackit.mockspresso.reflect;

import javax.annotation.Nullable;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;

/**
 * Key used to identify objects and dependencies
 */
public final class DependencyKey<V> {

  public static <T> DependencyKey<T> of(Class<T> clazz) {
    return of(TypeToken.of(clazz));
  }

  public static <T> DependencyKey<T> of(TypeToken<T> typeToken) {
    return new DependencyKey<T>(typeToken, null);
  }

  public static <T> DependencyKey<T> of(Class<T> clazz, Annotation identityAnnotation) {
    return of(TypeToken.of(clazz), identityAnnotation);
  }

  public static <T> DependencyKey<T> of(TypeToken<T> typeToken, Annotation identityAnnotation) {
    return new DependencyKey<T>(typeToken, identityAnnotation);
  }

  public static DependencyKey<?> fromField(Field field) {
    return new DependencyKey<>(TypeToken.of(field), ReflectUtil.findQualifierAnnotation(field));
  }

  public final TypeToken<V> typeToken;
  public final @Nullable Annotation identityAnnotation;

  private DependencyKey(TypeToken<V> typeToken, @Nullable Annotation identityAnnotation) {
    this.typeToken = typeToken;
    this.identityAnnotation = identityAnnotation;
  }

  @Override
  public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;

    DependencyKey<?> that = (DependencyKey<?>) o;

    if (!typeToken.equals(that.typeToken)) return false;
    return identityAnnotation != null ? identityAnnotation.equals(that.identityAnnotation) : that.identityAnnotation == null;
  }

  @Override
  public int hashCode() {
    int result = typeToken.hashCode();
    result = 31 * result + (identityAnnotation != null ? identityAnnotation.hashCode() : 0);
    return result;
  }

  @Override
  public String toString() {
    return String.format("Type: %s, Annotation: %s", typeToken, identityAnnotation);
  }
}

@@ -1842,86 +1842,270 @@
     
-return String.format(%22Type: %25s, Annotation: %25s%22, typeToken, identityAnnotation
+StringBuilder tsBuilder = new StringBuilder(%22DependencyKey%7BtypeToken=%22)%0A        .append(typeToken);%0A    if (identityAnnotation != null) %7B%0A      tsBuilder.append(%22, identityAnnotation=%22).append(identityAnnotation);%0A    %7D%0A    return tsBuilder.append(%22%7D%22).toString(
 );%0A 

refactor DependencyKey toString()