/*
 * Copyright (C) 2007 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.internal;

import com.google.inject.Binder;
import com.google.inject.ConfigurationException;
import com.google.inject.Key;
import com.google.inject.TypeLiteral;
import static com.google.inject.internal.Annotations.findScopeAnnotation;
import static com.google.inject.internal.Preconditions.checkState;
import com.google.inject.spi.BindingTargetVisitor;
import com.google.inject.spi.ConstructorBinding;
import com.google.inject.spi.Dependency;
import com.google.inject.spi.InjectionPoint;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.List;
import java.util.Map;
import java.util.Set;

final class ConstructorBindingImpl<T> extends BindingImpl<T> implements ConstructorBinding<T> {

  private final Factory<T> factory;
  private final InjectionPoint constructorInjectionPoint;

  private ConstructorBindingImpl(InjectorImpl injector, Key<T> key, Object source,
      InternalFactory<? extends T> scopedFactory, Scoping scoping, Factory<T> factory,
      InjectionPoint constructorInjectionPoint) {
    super(injector, key, source, scopedFactory, scoping);
    this.factory = factory;
    this.constructorInjectionPoint = constructorInjectionPoint;
  }

  public ConstructorBindingImpl(Key<T> key, Object source, Scoping scoping,
      InjectionPoint constructorInjectionPoint, Set<InjectionPoint> injectionPoints) {
    super(source, key, scoping);
    this.factory = new Factory<T>(false, key);
    ConstructionProxy<T> constructionProxy
        = new DefaultConstructionProxyFactory<T>(constructorInjectionPoint).create();
    this.constructorInjectionPoint = constructorInjectionPoint;
    factory.constructorInjector = new ConstructorInjector<T>(
        injectionPoints, constructionProxy, null, null);
  }

  /**
   * @param constructorInjector the constructor to use, or {@code null} to use the default.
   * @param failIfNotLinked true if this ConstructorBindingImpl's InternalFactory should
   *                             only succeed if retrieved from a linked binding
   */
  static <T> ConstructorBindingImpl<T> create(InjectorImpl injector, Key<T> key, 
      InjectionPoint constructorInjector, Object source, Scoping scoping, Errors errors,
      boolean failIfNotLinked)
      throws ErrorsException {
    int numErrors = errors.size();

    @SuppressWarnings("unchecked") // constructorBinding guarantees type is consistent
    Class<? super T> rawType = constructorInjector == null 
        ? key.getTypeLiteral().getRawType()
        : (Class) constructorInjector.getDeclaringType().getRawType();

    // We can't inject abstract classes.
    if (Modifier.isAbstract(rawType.getModifiers())) {
      errors.missingImplementation(key);
    }

    // Error: Inner class.
    if (Classes.isInnerClass(rawType)) {
      errors.cannotInjectInnerClass(rawType);
    }

    errors.throwIfNewErrors(numErrors);

    // Find a constructor annotated @Inject
    if (constructorInjector == null) {
      try {
        constructorInjector = InjectionPoint.forConstructorOf(key.getTypeLiteral());
      } catch (ConfigurationException e) {
        throw errors.merge(e.getErrorMessages()).toException();
      }
    }

    // if no scope is specified, look for a scoping annotation on the concrete class
    if (!scoping.isExplicitlyScoped()) {
      Class<?> annotatedType = constructorInjector.getMember().getDeclaringClass();
      Class<? extends Annotation> scopeAnnotation = findScopeAnnotation(errors, annotatedType);
      if (scopeAnnotation != null) {
        scoping = Scoping.makeInjectable(Scoping.forAnnotation(scopeAnnotation),
            injector, errors.withSource(rawType));
      }
    }

    errors.throwIfNewErrors(numErrors);

    Factory<T> factoryFactory = new Factory<T>(failIfNotLinked, key);
    InternalFactory<? extends T> scopedFactory
        = Scoping.scope(key, injector, factoryFactory, source, scoping);

    return new ConstructorBindingImpl<T>(
        injector, key, source, scopedFactory, scoping, factoryFactory, constructorInjector);
  }

  @SuppressWarnings("unchecked") // the result type always agrees with the ConstructorInjector type
  public void initialize(InjectorImpl injector, Errors errors) throws ErrorsException {
    factory.constructorInjector
        = (ConstructorInjector<T>) injector.constructors.get(constructorInjectionPoint, errors);
  }

  public <V> V acceptTargetVisitor(BindingTargetVisitor<? super T, V> visitor) {
    checkState(factory.constructorInjector != null, "not initialized");
    return visitor.visit(this);
  }

  public InjectionPoint getConstructor() {
    checkState(factory.constructorInjector != null, "Binding is not ready");
    return factory.constructorInjector.getConstructionProxy().getInjectionPoint();
  }

  public Set<InjectionPoint> getInjectableMembers() {
    checkState(factory.constructorInjector != null, "Binding is not ready");
    return factory.constructorInjector.getInjectableMembers();
  }

  /*if[AOP]*/
  public Map<Method, List<org.aopalliance.intercept.MethodInterceptor>> getMethodInterceptors() {
    checkState(factory.constructorInjector != null, "Binding is not ready");
    return factory.constructorInjector.getConstructionProxy().getMethodInterceptors();
  }
  /*end[AOP]*/

  public Set<Dependency<?>> getDependencies() {
    return Dependency.forInjectionPoints(new ImmutableSet.Builder<InjectionPoint>()
        .add(getConstructor())
        .addAll(getInjectableMembers())
        .build());
  }

  @Override protected BindingImpl<T> withScoping(Scoping scoping) {
    return new ConstructorBindingImpl<T>(
        null, getKey(), getSource(), factory, scoping, factory, constructorInjectionPoint);
  }

  @Override protected BindingImpl<T> withKey(Key<T> key) {
    return new ConstructorBindingImpl<T>(
        null, key, getSource(), factory, getScoping(), factory, constructorInjectionPoint);
  }

  public void applyTo(Binder binder) {
    InjectionPoint constructor = getConstructor();
    getScoping().applyTo(binder.withSource(getSource()).bind(getKey()).toConstructor(
        (Constructor) getConstructor().getMember(), (TypeLiteral) constructor.getDeclaringType()));
  }

  @Override public String toString() {
    return new ToStringBuilder(ConstructorBinding.class)
        .add("key", getKey())
        .add("source", getSource())
        .add("scope", getScoping())
        .toString();
  }

  private static class Factory<T> implements InternalFactory<T> {
    private final boolean failIfNotLinked;
    private final Key<?> key;
    private ConstructorInjector<T> constructorInjector;
    
    Factory(boolean failIfNotLinked, Key<?> key) {
      this.failIfNotLinked = failIfNotLinked;
      this.key = key;
    }

    @SuppressWarnings("unchecked")
    public T get(Errors errors, InternalContext context, Dependency<?> dependency, boolean linked)
        throws ErrorsException {
      checkState(constructorInjector != null, "Constructor not ready");
      
      if(failIfNotLinked && !linked) {
        throw errors.jitDisabled(key).toException();
      }

      // This may not actually be safe because it could return a super type of T (if that's all the
      // client needs), but it should be OK in practice thanks to the wonders of erasure.
      return (T) constructorInjector.construct(errors, context,
          dependency.getKey().getTypeLiteral().getRawType());
    }
  }
}
