/**
 * 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.spi;

import com.google.inject.AbstractModule;
import static com.google.inject.Asserts.assertContains;
import com.google.inject.Binding;
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.Scope;
import com.google.inject.Scopes;
import com.google.inject.Singleton;
import com.google.inject.Stage;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.inject.name.Names;
import java.lang.reflect.Constructor;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Logger;

import junit.framework.AssertionFailedError;
import junit.framework.TestCase;

/**
 * @author jessewilson@google.com (Jesse Wilson)
 */
public class SpiBindingsTest extends TestCase {

  public void testBindConstant() {
    checkInjector(
        new AbstractModule() {
          protected void configure() {
            bindConstant().annotatedWith(Names.named("one")).to(1);
          }
        },

        new FailingElementVisitor() {
          @Override public <T> Void visit(Binding<T> binding) {
            assertTrue(binding instanceof InstanceBinding);
            assertEquals(Key.get(Integer.class, Names.named("one")), binding.getKey());
            return null;
          }
        }
    );
  }

  public void testToInstanceBinding() {
    checkInjector(
        new AbstractModule() {
          protected void configure() {
            bind(String.class).toInstance("A");
          }
        },

        new FailingElementVisitor() {
          @Override public <T> Void visit(Binding<T> binding) {
            assertTrue(binding instanceof InstanceBinding);
            assertContains(binding.getSource().toString(), "SpiBindingsTest.java");
            assertEquals(Key.get(String.class), binding.getKey());
            binding.acceptTargetVisitor(new FailingTargetVisitor<T>() {
              @Override public Void visit(InstanceBinding<? extends T> binding) {
                assertEquals("A", binding.getInstance());
                return null;
              }
            });
            binding.acceptScopingVisitor(new FailingBindingScopingVisitor() {
              public Void visitEagerSingleton() {
                return null;
              }
            });
            return null;
          }
        }
    );
  }

  public void testToProviderBinding() {
    final Provider<String> stringProvider = new StringProvider();

    checkInjector(
        new AbstractModule() {
          protected void configure() {
            bind(String.class).toProvider(stringProvider);
          }
        },

        new FailingElementVisitor() {
          @Override public <T> Void visit(Binding<T> binding) {
            assertTrue(binding instanceof ProviderInstanceBinding);
            assertContains(binding.getSource().toString(), "SpiBindingsTest.java");
            assertEquals(Key.get(String.class), binding.getKey());
            binding.acceptTargetVisitor(new FailingTargetVisitor<T>() {
              @Override public Void visit(
                  ProviderInstanceBinding<? extends T> binding) {
                assertSame(stringProvider, binding.getProviderInstance());
                return null;
              }
            });
            return null;
          }
        }
    );
  }

  public void testToProviderKeyBinding() {
    checkInjector(
        new AbstractModule() {
          protected void configure() {
            bind(String.class).toProvider(StringProvider.class);
          }
        },

        new FailingElementVisitor() {
          @Override public <T> Void visit(Binding<T> binding) {
            assertTrue(binding instanceof ProviderKeyBinding);
            assertContains(binding.getSource().toString(), "SpiBindingsTest.java");
            assertEquals(Key.get(String.class), binding.getKey());
            binding.acceptTargetVisitor(new FailingTargetVisitor<T>() {
              @Override public Void visit(ProviderKeyBinding<? extends T> binding) {
                assertEquals(Key.get(StringProvider.class), binding.getProviderKey());
                return null;
              }
            });
            return null;
          }
        }
    );
  }

  public void testToKeyBinding() {
    final Key<String> aKey = Key.get(String.class, Names.named("a"));
    final Key<String> bKey = Key.get(String.class, Names.named("b"));

    checkInjector(
        new AbstractModule() {
          protected void configure() {
            bind(aKey).to(bKey);
            bind(bKey).toInstance("B");
          }
        },

        new FailingElementVisitor() {
          @Override public <T> Void visit(Binding<T> binding) {
            assertTrue(binding instanceof LinkedKeyBinding);
            assertContains(binding.getSource().toString(), "SpiBindingsTest.java");
            assertEquals(aKey, binding.getKey());
            binding.acceptTargetVisitor(new FailingTargetVisitor<T>() {
              @Override public Void visit(LinkedKeyBinding<? extends T> binding) {
                assertEquals(bKey, binding.getLinkedKey());
                return null;
              }
            });
            return null;
          }
        },

        new FailingElementVisitor() {
          @Override public <T> Void visit(Binding<T> binding) {
            assertEquals(bKey, binding.getKey());
            return null;
          }
        }
    );
  }

  public void testToConstructorBinding() {
    checkInjector(
        new AbstractModule() {
          protected void configure() {
            bind(D.class);
          }
        },

        new FailingElementVisitor() {
          @Override public <T> Void visit(Binding<T> binding) {
            assertTrue(binding instanceof ConstructorBinding);
            assertContains(binding.getSource().toString(), "SpiBindingsTest.java");
            assertEquals(Key.get(D.class), binding.getKey());
            binding.acceptTargetVisitor(new FailingTargetVisitor<T>() {
              @Override public Void visit(ConstructorBinding<? extends T> binding) {
                Constructor<?> expected = D.class.getDeclaredConstructors()[0];
                assertEquals(expected, binding.getConstructor().getMember());
                assertEquals(ImmutableSet.<InjectionPoint>of(), binding.getInjectableMembers());
                return null;
              }
            });
            return null;
          }
        }
    );
  }

  public void testConstantBinding() {
    checkInjector(
        new AbstractModule() {
          protected void configure() {
            bindConstant().annotatedWith(Names.named("one")).to(1);
          }
        },

        new FailingElementVisitor() {
          @Override public <T> Void visit(Binding<T> binding) {
            assertTrue(binding instanceof InstanceBinding);
            assertContains(binding.getSource().toString(), "SpiBindingsTest.java");
            assertEquals(Key.get(Integer.class, Names.named("one")), binding.getKey());
            binding.acceptTargetVisitor(new FailingTargetVisitor<T>() {
              @Override public Void visit(InstanceBinding<? extends T> binding) {
                assertEquals(1, binding.getInstance());
                return null;
              }
            });
            return null;
          }
        }
    );
  }

  public void testConvertedConstantBinding() {
    Injector injector = Guice.createInjector(new AbstractModule() {
      protected void configure() {
        bindConstant().annotatedWith(Names.named("one")).to("1");
      }
    });

    Binding<Integer> binding = injector.getBinding(Key.get(Integer.class, Names.named("one")));
    assertEquals(Key.get(Integer.class, Names.named("one")), binding.getKey());
    assertContains(binding.getSource().toString(), "SpiBindingsTest.java");
    assertTrue(binding instanceof ConvertedConstantBinding);
    binding.acceptTargetVisitor(new FailingTargetVisitor<Integer>() {
      @Override public Void visit(
          ConvertedConstantBinding<? extends Integer> binding) {
        assertEquals((Integer) 1, binding.getValue());
        assertEquals(Key.get(String.class, Names.named("one")), binding.getSourceKey());
        return null;
      }
    });
  }

  public void testProviderBinding() {
    Injector injector = Guice.createInjector(new AbstractModule() {
      protected void configure() {
        bind(String.class).toInstance("A");
      }
    });

    Key<Provider<String>> providerOfStringKey = new Key<Provider<String>>() {};
    Binding<Provider<String>> binding = injector.getBinding(providerOfStringKey);
    assertEquals(providerOfStringKey, binding.getKey());
    assertContains(binding.getSource().toString(), "SpiBindingsTest.java");
    assertTrue(binding instanceof ProviderBinding);
    binding.acceptTargetVisitor(new FailingTargetVisitor<Provider<String>>() {
      @Override public Void visit(
          ProviderBinding<? extends Provider<String>> binding) {
        assertEquals(Key.get(String.class), binding.getProvidedKey());
        return null;
      }
    });
  }

  public void testScopes() {
    checkInjector(
        new AbstractModule() {
          protected void configure() {
            bind(String.class).annotatedWith(Names.named("a"))
                .toProvider(StringProvider.class).in(Singleton.class);
            bind(String.class).annotatedWith(Names.named("b"))
                .toProvider(StringProvider.class).in(Scopes.SINGLETON);
            bind(String.class).annotatedWith(Names.named("c"))
                .toProvider(StringProvider.class).asEagerSingleton();
            bind(String.class).annotatedWith(Names.named("d"))
                .toProvider(StringProvider.class);
          }
        },

        new FailingElementVisitor() {
          @Override public <T> Void visit(Binding<T> command) {
            assertEquals(Key.get(String.class, Names.named("a")), command.getKey());
            command.acceptScopingVisitor(new FailingBindingScopingVisitor() {
              @Override public Void visitScope(Scope scope) {
                // even though we bound with an annotation, the injector always uses instances
                assertSame(Scopes.SINGLETON, scope);
                return null;
              }
            });
            return null;
          }
        },

        new FailingElementVisitor() {
          @Override public <T> Void visit(Binding<T> command) {
            assertEquals(Key.get(String.class, Names.named("b")), command.getKey());
            command.acceptScopingVisitor(new FailingBindingScopingVisitor() {
              @Override public Void visitScope(Scope scope) {
                assertSame(Scopes.SINGLETON, scope);
                return null;
              }
            });
            return null;
          }
        },

        new FailingElementVisitor() {
          @Override public <T> Void visit(Binding<T> command) {
            assertEquals(Key.get(String.class, Names.named("c")), command.getKey());
            command.acceptScopingVisitor(new FailingBindingScopingVisitor() {
              @Override public Void visitEagerSingleton() {
                return null;
              }
            });
            return null;
          }
        },

        new FailingElementVisitor() {
          @Override public <T> Void visit(Binding<T> command) {
            assertEquals(Key.get(String.class, Names.named("d")), command.getKey());
            command.acceptScopingVisitor(new FailingBindingScopingVisitor() {
              @Override public Void visitNoScoping() {
                return null;
              }
            });
            return null;
          }
        }
    );
  }
  
  public void testExtensionSpi() {
    final AtomicBoolean visiting = new AtomicBoolean(false);
    
    final Injector injector = Guice.createInjector(new AbstractModule() {
      protected void configure() {
        bind(String.class).toProvider(new ProviderWithExtensionVisitor<String>() {
          public <B, V> V acceptExtensionVisitor(BindingTargetVisitor<B, V> visitor,
              ProviderInstanceBinding<? extends B> binding) {
            assertSame(this, binding.getProviderInstance());
            // We can't always check for FailingSpiTargetVisitor,
            // because constructing the injector visits here, and we need
            // to process the binding as normal
            if(visiting.get()) {
              assertTrue("visitor: " + visitor, visitor instanceof FailingSpiTargetVisitor);
              return (V)"visited";
            } else {
              return visitor.visit(binding);
            }
          }
          
          public String get() {
            return "FooBar";
          }
        });
      }
    });
    
    visiting.set(true);

    // Check for Provider<String> binding -- that is still a ProviderBinding.
    Key<Provider<String>> providerOfStringKey = new Key<Provider<String>>() {};
    Binding<Provider<String>> providerBinding = injector.getBinding(providerOfStringKey);
    assertEquals(providerOfStringKey, providerBinding.getKey());
    assertContains(providerBinding.getSource().toString(), "SpiBindingsTest.java");
    assertTrue("binding: " + providerBinding, providerBinding instanceof ProviderBinding);
    providerBinding.acceptTargetVisitor(new FailingTargetVisitor<Provider<String>>() {
      @Override public Void visit(ProviderBinding<? extends Provider<String>> binding) {
        assertEquals(Key.get(String.class), binding.getProvidedKey());
        return null;
      }
    });
    
    // Check for String binding -- that one is ProviderInstanceBinding, and gets hooked
    Binding<String> binding = injector.getBinding(String.class);
    assertEquals(Key.get(String.class), binding.getKey());
    assertContains(binding.getSource().toString(), "SpiBindingsTest.java");
    assertTrue(binding instanceof ProviderInstanceBinding);
    assertEquals("visited", binding.acceptTargetVisitor(new FailingSpiTargetVisitor<String>()));
  }

  private static class FailingSpiTargetVisitor<T> extends DefaultBindingTargetVisitor<T, String> {
    @Override
    protected String visitOther(Binding<? extends T> binding) {
      throw new AssertionFailedError();
    }
  }

  public void checkInjector(Module module, ElementVisitor<?>... visitors) {
    Injector injector = Guice.createInjector(module);

    List<Binding<?>> bindings = Lists.newArrayList(injector.getBindings().values());
    for (Iterator<Binding<?>> i = bindings.iterator(); i.hasNext(); ) {
      if (BUILT_IN_BINDINGS.contains(i.next().getKey())) {
        i.remove();
      }
    }

    Collections.sort(bindings, orderByKey);

    assertEquals(bindings.size(), visitors.length);

    for (int i = 0; i < visitors.length; i++) {
      ElementVisitor<?> visitor = visitors[i];
      Binding<?> binding = bindings.get(i);
      binding.acceptVisitor(visitor);
    }
  }

  private final ImmutableSet<Key<?>> BUILT_IN_BINDINGS = ImmutableSet.of(
      Key.get(Injector.class), Key.get(Stage.class), Key.get(Logger.class));

  private final Comparator<Binding<?>> orderByKey = new Comparator<Binding<?>>() {
    public int compare(Binding<?> a, Binding<?> b) {
      return a.getKey().toString().compareTo(b.getKey().toString());
    }
  };

  private static class StringProvider implements Provider<String> {
    public String get() {
      return "A";
    }
  }

  private static class C { }

  private static class D extends C {
    @Inject public D(Injector unused) { }
  }
}
