/**
 * 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.Stage;
import com.google.inject.TypeLiteral;
import com.google.inject.Scope;
import com.google.inject.spi.Dependency;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.lang.annotation.Annotation;

/**
 * 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;
    
    public InjectorOptions(Stage stage, boolean jitDisabled) {
      this.stage = stage;
      this.jitDisabled = jitDisabled;
    }
  }

  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
    Set<BindingImpl<?>> candidateBindings = ImmutableSet.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> 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 <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");
    }
  }
}
