/**
 * 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.common.base.Nullable;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Ordering;
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.inject.name.Names;
import java.lang.reflect.Constructor;
import java.util.List;
import java.util.logging.Logger;
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 visitBinding(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 visitBinding(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 visitInstance(InstanceBinding<T> binding) {
                assertEquals("A", binding.getInstance());
                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 visitBinding(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 visitProviderInstance(ProviderInstanceBinding<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 visitBinding(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 visitProviderKey(ProviderKeyBinding<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 visitBinding(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 visitLinkedKey(LinkedKeyBinding<T> binding) {
                assertEquals(bKey, binding.getLinkedKey());
                return null;
              }
            });
            return null;
          }
        },

        new FailingElementVisitor() {
          @Override public <T> Void visitBinding(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 visitBinding(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 visitConstructor(ConstructorBinding<T> binding) {
                Constructor<?> expected = D.class.getDeclaredConstructors()[0];
                assertEquals(expected, binding.getConstructor());
                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 visitBinding(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 visitInstance(InstanceBinding<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 visitConvertedConstant(ConvertedConstantBinding<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 visitProviderBinding(ProviderBinding<?> 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 visitBinding(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 visitBinding(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 visitBinding(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 visitBinding(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 checkInjector(Module module, ElementVisitor<?>... visitors) {
    Injector injector = Guice.createInjector(module);

    List<Binding<?>> bindings = Lists.newArrayList(
        Iterables.filter(injector.getBindings().values(), isUserBinding));
    orderByKey.sort(bindings);

    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 Predicate<Binding<?>> isUserBinding = new Predicate<Binding<?>>() {
    private final ImmutableSet<Key<?>> BUILT_IN_BINDINGS = ImmutableSet.of(
        Key.get(Injector.class), Key.get(Stage.class), Key.get(Logger.class));
    public boolean apply(@Nullable Binding<?> binding) {
      return !BUILT_IN_BINDINGS.contains(binding.getKey());
    }
  };

  private final Ordering<Binding<?>> orderByKey = new Ordering<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) { }
  }
}
