/**
 * Copyright (C) 2006 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.Binding;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.MembersInjector;
import com.google.inject.Module;
import com.google.inject.Provider;
import com.google.inject.Scope;
import com.google.inject.Stage;
import com.google.inject.TypeLiteral;
import com.google.inject.internal.util.ImmutableList;
import com.google.inject.internal.util.Iterables;
import com.google.inject.internal.util.Stopwatch;
import com.google.inject.spi.Dependency;
import com.google.inject.spi.TypeConverterBinding;
import java.lang.annotation.Annotation;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Builds a tree of injectors. This is a primary injector, plus child injectors needed for each
 * {@code Binder.newPrivateBinder() private environment}. The primary injector is not necessarily a
 * top-level injector.
 *
 * <p>Injector construction happens in two phases.
 * <ol>
 *   <li>Static building. In this phase, we interpret commands, create bindings, and inspect 
 *     dependencies. During this phase, we hold a lock to ensure consistency with parent injectors.
 *     No user code is executed in this phase.</li>
 *   <li>Dynamic injection. In this phase, we call user code. We inject members that requested
 *     injection. This may require user's objects be created and their providers be called. And we
 *     create eager singletons. In this phase, user code may have started other threads. This phase
 *     is not executed for injectors created using {@link Stage#TOOL the tool stage}</li>
 * </ol>
 *
 * @author crazybob@google.com (Bob Lee)
 * @author jessewilson@google.com (Jesse Wilson)
 */
public final class InternalInjectorCreator {

  private final Stopwatch stopwatch = new Stopwatch();
  private final Errors errors = new Errors();

  private final Initializer initializer = new Initializer();
  private final BindingProcessor bindingProcesor;
  private final InjectionRequestProcessor injectionRequestProcessor;

  private final InjectorShell.Builder shellBuilder = new InjectorShell.Builder();
  private List<InjectorShell> shells;
  
  public static class InjectorOptions {
    final Stage stage;
    final boolean jitDisabled;
    final boolean allowCircularProxy;
    
    public InjectorOptions(Stage stage, boolean jitDisabled, boolean allowCircularProxy) {
      this.stage = stage;
      this.jitDisabled = jitDisabled;
      this.allowCircularProxy = allowCircularProxy;
    }
  }

  public InternalInjectorCreator() {
    injectionRequestProcessor = new InjectionRequestProcessor(errors, initializer);
    bindingProcesor = new BindingProcessor(errors, initializer);
  }
  
  public InternalInjectorCreator injectorOptions(InjectorOptions options) {
    shellBuilder.setInjectorOptions(options);
    return this;
  }  

  /**
   * Sets the parent of the injector to-be-constructed.As a side effect, this sets this injector's
   * stage to the stage of {@code parent} and sets {@link #requireExplicitBindings()} if the parent
   * injector also required them.
   */
  public InternalInjectorCreator parentInjector(InjectorImpl parent) {
    shellBuilder.parent(parent);
    shellBuilder.setInjectorOptions(parent.options);
    return this;
  }

  public InternalInjectorCreator addModules(Iterable<? extends Module> modules) {
    shellBuilder.addModules(modules);
    return this;
  }

  public Injector build() {
    if (shellBuilder == null) {
      throw new AssertionError("Already built, builders are not reusable.");
    }

    // Synchronize while we're building up the bindings and other injector state. This ensures that
    // the JIT bindings in the parent injector don't change while we're being built
    synchronized (shellBuilder.lock()) {
      shells = shellBuilder.build(bindingProcesor, stopwatch, errors);
      stopwatch.resetAndLog("Injector construction");

      initializeStatically();
    }

    injectDynamically();

    if (shellBuilder.getInjectorOptions().stage == Stage.TOOL) {
      // wrap the primaryInjector in a ToolStageInjector
      // to prevent non-tool-friendy methods from being called.
      return new ToolStageInjector(primaryInjector());
    } else {
      return primaryInjector();
    }
  }

  /** Initialize and validate everything. */
  private void initializeStatically() {
    bindingProcesor.initializeBindings();
    stopwatch.resetAndLog("Binding initialization");

    for (InjectorShell shell : shells) {
      shell.getInjector().index();
    }
    stopwatch.resetAndLog("Binding indexing");

    injectionRequestProcessor.process(shells);
    stopwatch.resetAndLog("Collecting injection requests");

    bindingProcesor.runCreationListeners();
    stopwatch.resetAndLog("Binding validation");

    injectionRequestProcessor.validate();
    stopwatch.resetAndLog("Static validation");

    initializer.validateOustandingInjections(errors);
    stopwatch.resetAndLog("Instance member validation");

    new LookupProcessor(errors).process(shells);
    for (InjectorShell shell : shells) {
      ((DeferredLookups) shell.getInjector().lookups).initialize(errors);
    }
    stopwatch.resetAndLog("Provider verification");

    for (InjectorShell shell : shells) {
      if (!shell.getElements().isEmpty()) {
        throw new AssertionError("Failed to execute " + shell.getElements());
      }
    }

    errors.throwCreationExceptionIfErrorsExist();
  }

  /**
   * Returns the injector being constructed. This is not necessarily the root injector.
   */
  private Injector primaryInjector() {
    return shells.get(0).getInjector();
  }

  /**
   * Inject everything that can be injected. This method is intentionally not synchronized. If we
   * locked while injecting members (ie. running user code), things would deadlock should the user
   * code build a just-in-time binding from another thread.
   */
  private void injectDynamically() {
    injectionRequestProcessor.injectMembers();
    stopwatch.resetAndLog("Static member injection");

    initializer.injectAll(errors);
    stopwatch.resetAndLog("Instance injection");
    errors.throwCreationExceptionIfErrorsExist();

    if(shellBuilder.getInjectorOptions().stage != Stage.TOOL) {
      for (InjectorShell shell : shells) {
        loadEagerSingletons(shell.getInjector(), shellBuilder.getInjectorOptions().stage, errors);
      }
      stopwatch.resetAndLog("Preloading singletons");
    }
    errors.throwCreationExceptionIfErrorsExist();
  }

  /**
   * Loads eager singletons, or all singletons if we're in Stage.PRODUCTION. Bindings discovered
   * while we're binding these singletons are not be eager.
   */
  void loadEagerSingletons(InjectorImpl injector, Stage stage, final Errors errors) {
    @SuppressWarnings("unchecked") // casting Collection<Binding> to Collection<BindingImpl> is safe
    Iterable<BindingImpl<?>> candidateBindings = ImmutableList.copyOf(Iterables.concat(
        (Collection) injector.state.getExplicitBindingsThisLevel().values(),
        injector.jitBindings.values()));
    for (final BindingImpl<?> binding : candidateBindings) {
      if (isEagerSingleton(injector, binding, stage)) {
        try {
          injector.callInContext(new ContextualCallable<Void>() {
            Dependency<?> dependency = Dependency.get(binding.getKey());
            public Void call(InternalContext context) {
              Dependency previous = context.setDependency(dependency);
              Errors errorsForBinding = errors.withSource(dependency);
              try {
                binding.getInternalFactory().get(errorsForBinding, context, dependency, false);
              } catch (ErrorsException e) {
                errorsForBinding.merge(e.getErrors());
              } finally {
                context.setDependency(previous);
              }

              return null;
            }
          });
        } catch (ErrorsException e) {
          throw new AssertionError();
        }
      }
    }
  }

  private boolean isEagerSingleton(InjectorImpl injector, BindingImpl<?> binding, Stage stage) {
    if (binding.getScoping().isEagerSingleton(stage)) {
      return true;
    }

    // handle a corner case where a child injector links to a binding in a parent injector, and
    // that binding is singleton. We won't catch this otherwise because we only iterate the child's
    // bindings.
    if (binding instanceof LinkedBindingImpl) {
      Key<?> linkedBinding = ((LinkedBindingImpl<?>) binding).getLinkedKey();
      return isEagerSingleton(injector, injector.getBinding(linkedBinding), stage);
    }

    return false;
  }

  /** {@link Injector} exposed to users in {@link Stage#TOOL}. */
  static class ToolStageInjector implements Injector {
    private final Injector delegateInjector;
    
    ToolStageInjector(Injector delegateInjector) {
      this.delegateInjector = delegateInjector;
    }
    public void injectMembers(Object o) {
      throw new UnsupportedOperationException(
        "Injector.injectMembers(Object) is not supported in Stage.TOOL");
    }
    public Map<Key<?>, Binding<?>> getBindings() {
      return this.delegateInjector.getBindings();
    }
    public Map<Key<?>, Binding<?>> getAllBindings() {
      return this.delegateInjector.getAllBindings();
    }
    public <T> Binding<T> getBinding(Key<T> key) {
      return this.delegateInjector.getBinding(key);
    }
    public <T> Binding<T> getBinding(Class<T> type) {
      return this.delegateInjector.getBinding(type);
    }
    public <T> Binding<T> getExistingBinding(Key<T> key) {
      return this.delegateInjector.getExistingBinding(key);
    }
    public <T> List<Binding<T>> findBindingsByType(TypeLiteral<T> type) {
      return this.delegateInjector.findBindingsByType(type);
    }
    public Injector getParent() {
      return delegateInjector.getParent();
    }
    public Injector createChildInjector(Iterable<? extends Module> modules) {
      return delegateInjector.createChildInjector(modules);
    }
    public Injector createChildInjector(Module... modules) {
      return delegateInjector.createChildInjector(modules);
    }
    public Map<Class<? extends Annotation>, Scope> getScopeBindings() {
      return delegateInjector.getScopeBindings();
    }
    public Set<TypeConverterBinding> getTypeConverterBindings() {
      return delegateInjector.getTypeConverterBindings();
    }
    public <T> Provider<T> getProvider(Key<T> key) {
      throw new UnsupportedOperationException(
        "Injector.getProvider(Key<T>) is not supported in Stage.TOOL");
    }
    public <T> Provider<T> getProvider(Class<T> type) {
      throw new UnsupportedOperationException(
        "Injector.getProvider(Class<T>) is not supported in Stage.TOOL");
    }
    public <T> MembersInjector<T> getMembersInjector(TypeLiteral<T> typeLiteral) {
      throw new UnsupportedOperationException(
        "Injector.getMembersInjector(TypeLiteral<T>) is not supported in Stage.TOOL");
    }
    public <T> MembersInjector<T> getMembersInjector(Class<T> type) {
      throw new UnsupportedOperationException(
        "Injector.getMembersInjector(Class<T>) is not supported in Stage.TOOL");
    }
    public <T> T getInstance(Key<T> key) {
      throw new UnsupportedOperationException(
        "Injector.getInstance(Key<T>) is not supported in Stage.TOOL");
    }
    public <T> T getInstance(Class<T> type) {
      throw new UnsupportedOperationException(
        "Injector.getInstance(Class<T>) is not supported in Stage.TOOL");
    }
  }
}
