/*
 * Copyright (C) 2014 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.google.inject.testing.fieldbinder;

import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.inject.Binder;
import com.google.inject.BindingAnnotation;
import com.google.inject.Module;
import com.google.inject.Provider;
import com.google.inject.TypeLiteral;
import com.google.inject.binder.AnnotatedBindingBuilder;
import com.google.inject.binder.LinkedBindingBuilder;
import com.google.inject.internal.Annotations;
import com.google.inject.spi.Message;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

/**
 * Automatically creates Guice bindings for fields in an object annotated with {@link Bind}.
 *
 * <p>This module is intended for use in tests to reduce the code needed to bind local fields
 * (usually mocks) for injection.
 *
 * <p>The following rules are followed in determining how fields are bound using this module:
 *
 * <ul>
 * <li>
 * For each {@link Bind} annotated field of an object and its superclasses, this module will bind
 * that field's type to that field's value at injector creation time. This includes both instance
 * and static fields.
 * </li>
 * <li>
 * If {@link Bind#to} is specified, the field's value will be bound to the class specified by
 * {@link Bind#to} instead of the field's actual type.
 * </li>
 * <li>
 * If a {@link BindingAnnotation} or {@link javax.inject.Qualifier} is present on the field,
 * that field will be bound using that annotation via {@link AnnotatedBindingBuilder#annotatedWith}.
 * For example, {@code bind(Foo.class).annotatedWith(BarAnnotation.class).toInstance(theValue)}.
 * It is an error to supply more than one {@link BindingAnnotation} or
 * {@link javax.inject.Qualifier}.
 * </li>
 * <li>
 * If the field is of type {@link Provider}, the field's value will be bound as a {@link Provider}
 * using {@link LinkedBindingBuilder#toProvider} to the provider's parameterized type. For example,
 * {@code Provider<Integer>} binds to {@link Integer}. Attempting to bind a non-parameterized
 * {@link Provider} without a {@link Bind#to} clause is an error.
 * </li>
 * </ul>
 *
 * <p>Example use:
 * <pre><code>
 * public class TestFoo {
 *   // bind(new TypeLiteral{@code <List<Object>>}() {}).toInstance(listOfObjects);
 *   {@literal @}Bind private List{@code <Object>} listOfObjects = Lists.of();
 *
 *   // bind(SuperClass.class).toInstance(aSubClass);
 *   {@literal @}Bind(to = SuperClass.class) private SubClass aSubClass = new SubClass();
 *
 *   // bind(Object.class).annotatedWith(MyBindingAnnotation.class).toInstance(object2);
 *   {@literal @}Bind
 *   {@literal @}MyBindingAnnotation
 *   private String myString = "hello";
 *
 *   // bind(Object.class).toProvider(myProvider);
 *   {@literal @}Bind private Provider{@code <Object>} myProvider = getProvider();
 *
 *   {@literal @}Before public void setUp() {
 *     Guice.createInjector(BoundFieldModule.of(this)).injectMembers(this);
 *   }
 * }
 * </code></pre>
 *
 * @see Bind
 * @author eatnumber1@google.com (Russ Harmon)
 */
public final class BoundFieldModule implements Module {
  private final Object instance;

  // Note that binder is not initialized until configure() is called.
  private Binder binder;

  private BoundFieldModule(Object instance) {
    this.instance = instance;
  }

  /**
   * Create a BoundFieldModule which binds the {@link Bind} annotated fields of {@code instance}.
   *
   * @param instance the instance whose fields will be bound.
   * @return a module which will bind the {@link Bind} annotated fields of {@code instance}.
   */
  public static BoundFieldModule of(Object instance) {
    return new BoundFieldModule(instance);
  }

  private static class BoundFieldException extends RuntimeException {
    BoundFieldException(String message) {
      super(message);
    }
  }

  private class BoundFieldInfo {
    /** The field itself. */
    final Field field;

    /**
     * The actual type of the field.
     *
     * <p>For example, {@code @Bind(to = Object.class) Number one = new Integer(1);} will be
     * {@link Number}.
     */
    final TypeLiteral<?> type;

    /** The {@link Bind} annotation which is present on the field. */
    final Bind bindAnnotation;

    /**
     * The type this field will bind to.
     *
     * <p>For example, {@code @Bind(to = Object.class) Number one = new Integer(1);} will be
     * {@link Object} and {@code @Bind Number one = new Integer(1);} will be {@link Number}.
     */
    final TypeLiteral<?> boundType;

    /**
     * The "natural" type of this field.
     *
     * <p>For example, {@code @Bind(to = Object.class) Number one = new Integer(1);} will be
     * {@link Number}, and {@code @Bind(to = Object.class) Provider<Number> one = new Integer(1);}
     * will be {@link Number}.
     *
     * @see getNaturalFieldType
     */
    final Optional<TypeLiteral<?>> naturalType;

    BoundFieldInfo(
        Field field,
        Bind bindAnnotation,
        TypeLiteral<?> fieldType) {
      this.field = field;
      this.type = fieldType;
      this.bindAnnotation = bindAnnotation;

      field.setAccessible(true);

      this.naturalType = getNaturalFieldType();
      this.boundType = getBoundType();
    }

    private TypeLiteral<?> getBoundType() {
      Class<?> bindClass = bindAnnotation.to();
      // Bind#to's default value is Bind.class which is used to represent that no explicit binding
      // type is requested.
      if (bindClass == Bind.class) {
        Preconditions.checkState(naturalType != null);
        if (!this.naturalType.isPresent()) {
          addErrorAndThrow(
              field,
              "Non parameterized Provider fields must have an explicit "
              + "binding class via @Bind(to = Foo.class)");
        }
        return this.naturalType.get();
      } else {
        return TypeLiteral.get(bindClass);
      }
    }

    /**
     * Retrieves the type this field binds to naturally.
     *
     * <p>A field's "natural" type specifically ignores the to() method on the @Bind annotation, is
     * the parameterized type if the field's actual type is a parameterized {@link Provider}, is
     * {@link Optional#absent()} if this field is a non-parameterized {@link Provider} and otherwise
     * is the field's actual type.
     *
     * @return the type this field binds to naturally, or {@link Optional#absent()} if this field is
     * a non-parameterized {@link Provider}.
     */
    private Optional<TypeLiteral<?>> getNaturalFieldType() {
      if (isTransparentProvider(type.getRawType())) {
        Type providerType = type.getType();
        if (providerType instanceof Class) {
          return Optional.absent();
        }
        Preconditions.checkState(providerType instanceof ParameterizedType);
        Type[] providerTypeArguments = ((ParameterizedType) providerType).getActualTypeArguments();
        Preconditions.checkState(providerTypeArguments.length == 1);
        return Optional.<TypeLiteral<?>>of(TypeLiteral.get(providerTypeArguments[0]));
      } else {
        return Optional.<TypeLiteral<?>>of(type);
      }
    }

    Object getValue() {
      try {
        return field.get(instance);
      } catch (IllegalAccessException e) {
        // Since we called setAccessible(true) on this field in the constructor, this is a
        // programming error if it occurs.
        throw new AssertionError(e);
      }
    }
  }

  private static boolean hasInject(Field field) {
    return field.isAnnotationPresent(javax.inject.Inject.class)
        || field.isAnnotationPresent(com.google.inject.Inject.class);
  }

  /**
   * Retrieve a {@link BoundFieldInfo}.
   *
   * <p>This returns a {@link BoundFieldInfo} if the field has a {@link Bind} annotation.
   * Otherwise it returns {@link Optional#absent()}.
   */
  private Optional<BoundFieldInfo> getBoundFieldInfo(
      TypeLiteral<?> containingClassType,
      Field field) {
    Bind bindAnnotation = field.getAnnotation(Bind.class);
    if (bindAnnotation == null) {
      return Optional.absent();
    }
    if (hasInject(field)) {
      addErrorAndThrow(
          field,
          "Fields annotated with both @Bind and @Inject are illegal.");
    }
    return Optional.of(
        new BoundFieldInfo(
            field,
            bindAnnotation,
            containingClassType.getFieldType(field)));
  }

  private LinkedBindingBuilder<?> verifyBindingAnnotations(
      Field field,
      AnnotatedBindingBuilder<?> annotatedBinder) {
    LinkedBindingBuilder<?> binderRet = annotatedBinder;
    for (Annotation annotation : field.getAnnotations()) {
      Class<? extends Annotation> annotationType = annotation.annotationType();
      if (Annotations.isBindingAnnotation(annotationType)) {
        // not returning here ensures that annotatedWith will be called multiple times if this field
        // has multiple BindingAnnotations, relying on the binder to throw an error in this case.
        binderRet = annotatedBinder.annotatedWith(annotation);
      }
    }
    return binderRet;
  }

  /**
   * Determines if {@code clazz} is a "transparent provider".
   *
   * <p>A transparent provider is a {@link com.google.inject.Provider} or
   * {@link javax.inject.Provider} which binds to it's parameterized type when used as the argument
   * to {@link Binder#bind}.
   *
   * <p>A {@link Provider} is transparent if the base class of that object is {@link Provider}. In
   * other words, subclasses of {@link Provider} are not transparent. As a special case, if a
   * {@link Provider} has no parameterized type but is otherwise transparent, then it is considered
   * transparent.
   */
  private static boolean isTransparentProvider(Class<?> clazz) {
    return com.google.inject.Provider.class == clazz || javax.inject.Provider.class == clazz;
  }

  private void bindField(BoundFieldInfo fieldInfo) {
    if (fieldInfo.naturalType.isPresent()) {
      Class<?> naturalRawType = fieldInfo.naturalType.get().getRawType();
      Class<?> boundRawType = fieldInfo.boundType.getRawType();
      if (!boundRawType.isAssignableFrom(naturalRawType)) {
        addErrorAndThrow(
            fieldInfo.field,
            "Requested binding type \"%s\" is not assignable from field binding type \"%s\"",
            boundRawType.getName(),
            naturalRawType.getName());
      }
    }

    AnnotatedBindingBuilder<?> annotatedBinder = binder.bind(fieldInfo.boundType);
    LinkedBindingBuilder<?> binder = verifyBindingAnnotations(fieldInfo.field, annotatedBinder);

    // It's unfortunate that Field.get() just returns Object rather than the actual type (although
    // that would be impossible) because as a result calling binder.toInstance or binder.toProvider
    // is impossible to do without an unchecked cast. This is safe if fieldInfo.naturalType is
    // present because compatibility is checked explicitly above, but is _unsafe_ if
    // fieldInfo.naturalType is absent which occurrs when a non-parameterized Provider is used with
    // @Bind(to = ...)
    @SuppressWarnings("unchecked")
    AnnotatedBindingBuilder<Object> binderUnsafe = (AnnotatedBindingBuilder<Object>) binder;

    Object fieldValue = fieldInfo.getValue();

    if (fieldValue == null) {
      addErrorAndThrow(
          fieldInfo.field,
          "Binding to null values is not allowed. "
          + "Use Providers.of(null) if this is your intended behavior.",
          fieldInfo.field.getName());
    }

    if (isTransparentProvider(fieldInfo.type.getRawType())) {
      // This is safe because we checked that the field's type is Provider above.
      @SuppressWarnings("unchecked")
      Provider<?> fieldValueUnsafe = (Provider<?>) fieldValue;

      binderUnsafe.toProvider(fieldValueUnsafe);
    } else {
      binderUnsafe.toInstance(fieldValue);
    }
  }

  private void addErrorAndThrow(Field field, String format, Object... args) {
    Preconditions.checkNotNull(binder);
    String source = String.format(
        "%s field %s",
        field.getDeclaringClass().getName(),
        field.getName());
    Message messageObj = new Message(source, String.format(format, args));

    binder.addError(messageObj);
    throw new BoundFieldException(messageObj.getMessage());
  }

  @Override
  public void configure(Binder binder) {
    binder = binder.skipSources(BoundFieldModule.class);
    this.binder = binder;

    TypeLiteral<?> currentClassType = TypeLiteral.get(instance.getClass());
    while (currentClassType.getRawType() != Object.class) {
      for (Field field : currentClassType.getRawType().getDeclaredFields()) {
        try {
          Optional<BoundFieldInfo> fieldInfoOpt =
              getBoundFieldInfo(currentClassType, field);
          if (fieldInfoOpt.isPresent()) {
            bindField(fieldInfoOpt.get());
          }
        } catch (BoundFieldException e) {
          // addErrorAndThrow already called addError, so do nothing
        }
      }
      currentClassType =
          currentClassType.getSupertype(currentClassType.getRawType().getSuperclass());
    }
  }
}
