/**
 * Copyright (C) 2008 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.visitable.intercepting;

import com.google.inject.Binder;
import com.google.inject.BindingAnnotation;
import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.Module;
import com.google.inject.Provider;
import com.google.inject.visitable.*;
import com.google.inject.binder.LinkedBindingBuilder;
import com.google.inject.binder.ScopedBindingBuilder;
import static com.google.inject.internal.Objects.nonNull;
import java.lang.annotation.Annotation;
import java.lang.annotation.Retention;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * Constructs an {@link Injector} that can intercept object provision.
 *
 * @author jessewilson@google.com (Jesse Wilson)
 * @author jmourits@google.com (Jerome Mourits)
 */
public final class InterceptingInjectorBuilder {

  private static final Key<InjectionInterceptor> INJECTION_INTERCEPTOR_KEY
      = Key.get(InjectionInterceptor.class);

  final Collection<Module> modules = new ArrayList<Module>();
  final Set<Key<?>> interceptedKeys = new HashSet<Key<?>>();

  public InterceptingInjectorBuilder bindModules(Module... modules) {
    this.modules.addAll(Arrays.asList(modules));
    return this;
  }

  public InterceptingInjectorBuilder bindModules(Collection<Module> modules) {
    this.modules.addAll(modules);
    return this;
  }

  public InterceptingInjectorBuilder intercept(Key<?>... keys) {
    this.interceptedKeys.addAll(Arrays.asList(keys));
    return this;
  }

  public InterceptingInjectorBuilder intercept(Collection<Key<?>> keys) {
    interceptedKeys.addAll(keys);
    return this;
  }

  public InterceptingInjectorBuilder intercept(Class<?>... classes) {
    List<Key<?>> keysAsList = new ArrayList<Key<?>>(classes.length);
    for (Class<?> clas : classes) {
      keysAsList.add(Key.get(clas));
    }

    return intercept(keysAsList);
  }

  public Injector build() {
    if (interceptedKeys.contains(INJECTION_INTERCEPTOR_KEY)) {
      throw new IllegalArgumentException("Cannot intercept the interceptor!");
    }

    FutureInjector futureInjector = new FutureInjector();

    // record everything that's being done to a fake binder
    final VisitableBinder visitableBinder = new VisitableBinder(futureInjector);
    for (Module module : modules) {
      module.configure(visitableBinder);
    }

    // replay against a real binder, substituting interceptable wherever appropriate
    Module interceptingModule = new Module() {
      public void configure(final Binder binder) {
        Command.Visitor<Void> visitor = new ExecutingVisitor(binder) {
          @Override public <T> Void visitBinding(BindCommand<T> command) {
            Key<T> key = command.getKey();

            if (!interceptedKeys.contains(key)) {
              return super.visitBinding(command);
            }

            if (command.getTarget() == null) {
              throw new UnsupportedOperationException(
                  String.format("Cannot intercept bare binding of %s.", key));
            }

            Key<T> anonymousKey = Key.get(key.getTypeLiteral(), uniqueAnnotation());
            binder().bind(key).toProvider(new InterceptingProvider<T>(key, anonymousKey));

            LinkedBindingBuilder<T> linkedBindingBuilder = binder().bind(anonymousKey);
            ScopedBindingBuilder scopedBindingBuilder = command.getTarget().execute(linkedBindingBuilder);

            BindScoping scoping = command.getScoping();
            if (scoping != null) {
              scoping.execute(scopedBindingBuilder);
            }

            return null;
          }
        };

        for (Command command : visitableBinder.getCommands()) {
          command.acceptVisitor(visitor);
        }
      }
    };

    Injector injector = Guice.createInjector(interceptingModule);

    // make the injector available for callbacks from early providers
    futureInjector.initialize(injector);

    return injector;
  }

  private static class InterceptingProvider<T> implements Provider<T> {
    private final Key<T> key;
    private final Key<T> anonymousKey;
    private Provider<InjectionInterceptor> injectionInterceptorProvider;
    private Provider<? extends T> delegateProvider;

    public InterceptingProvider(Key<T> key, Key<T> anonymousKey) {
      this.key = key;
      this.anonymousKey = anonymousKey;
    }

    @Inject void initialize(Injector injector, Provider<InjectionInterceptor> injectionInterceptorProvider) {
      this.injectionInterceptorProvider = nonNull(
          injectionInterceptorProvider, "injectionInterceptorProvider");
      this.delegateProvider = nonNull(
          injector.getProvider(anonymousKey), "delegateProvider");
    }

    public T get() {
      nonNull(injectionInterceptorProvider, "injectionInterceptorProvider");
      nonNull(delegateProvider, "delegateProvider");
      return injectionInterceptorProvider.get().intercept(key, delegateProvider);
    }
  }

  /**
   * Returns an annotation instance that is not equal to any other annotation
   * instances, for use in creating distinct {@link Key}s.
   */
  private static Annotation uniqueAnnotation() {
    return new Annotation() {
      public Class<? extends Annotation> annotationType() {
        return Internal.class;
      }
      @Override public String toString() {
        return "InterceptingBinderPrivate";
      }
    };
  }
  @Retention(RUNTIME) @BindingAnnotation
  private @interface Internal { }

}
