// Copyright 2009 Google Inc. All Rights Reserved.

package com.google.inject.throwingproviders;

import com.google.inject.AbstractModule;
import com.google.inject.BindingAnnotation;
import com.google.inject.Exposed;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.PrivateModule;
import com.google.inject.Provides;
import com.google.inject.TypeLiteral;
import com.google.inject.name.Named;
import com.google.inject.name.Names;

import junit.framework.TestCase;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.net.BindException;
import java.rmi.RemoteException;

/**
 * Test methods for {@link CheckedProviderMethodsModule}.
 */
public class CheckedProviderMethodsModuleTest extends TestCase {

  private final TypeLiteral<RpcProvider<String>> rpcProviderOfString
      = new TypeLiteral<RpcProvider<String>>() { };
  private final TypeLiteral<RpcProvider<Integer>> rpcProviderOfInteger
      = new TypeLiteral<RpcProvider<Integer>>() { };
  private final TypeLiteral<RpcProvider<Long>> rpcProviderOfLong
      = new TypeLiteral<RpcProvider<Long>>() { };
  private final TypeLiteral<RpcProvider<Float>> rpcProviderOfFloat
      = new TypeLiteral<RpcProvider<Float>>() { };
  private final TypeLiteral<RpcProvider<Pair<Double, String>>> rpcProviderOfPair
      = new TypeLiteral<RpcProvider<Pair<Double, String>>>() { };

  private final TestScope testScope = new TestScope();

  interface RpcProvider<T> extends CheckedProvider<T> {
    T get() throws RemoteException, BindException;
  }

  @Retention(RetentionPolicy.RUNTIME)
  @BindingAnnotation
  @interface TestAnnotation {
  }

  class TestModule extends AbstractModule {

    private int nextIntToReturn = 100;

    @Override
    protected void configure() {
      bindScope(TestScope.Scoped.class, testScope);
      install(ThrowingProviderBinder.forModule(this));
      install(new TestPrivateModule());
    }

    @CheckedProvides(RpcProvider.class)
    String getSomeStringFromServer() {
      return "Works";
    }

    @CheckedProvides(RpcProvider.class) @TestScope.Scoped
    int getSomeIntegerFromServer() {
      return nextIntToReturn;
    }

    @CheckedProvides(RpcProvider.class) @TestAnnotation
    long getSomeLongFromServer() {
      return 0xffL;
    }

    @Provides
    double getSomeDouble() {
      return 2.0d;
    }

    @CheckedProvides(RpcProvider.class)
    Pair<Double, String> getSomePair(Double input) {
      return new Pair<Double, String>(input * 2, "foo");
    }

    @CheckedProvides(RpcProvider.class)
    float getFloat() throws BindException {
      throw new BindException("foo");
    }

    void setNextIntToReturn(int next) {
      nextIntToReturn = next;
    }
  }

  class TestPrivateModule extends PrivateModule {

    @Override
    protected void configure() {
      install(ThrowingProviderBinder.forModule(this));
    }

    @CheckedProvides(RpcProvider.class) @Named("fruit") @Exposed
    String provideApples() {
      return "apple";
    }
  }
  

  public void testNoAnnotationNoScope() throws BindException, RemoteException {
    Injector injector = Guice.createInjector(new TestModule());
    RpcProvider<String> provider = injector
        .getInstance(Key.get(rpcProviderOfString));
    assertEquals("Works", provider.get());
  }

  public void testWithScope() throws BindException, RemoteException {
    TestModule testModule = new TestModule();
    Injector injector = Guice.createInjector(testModule);
    RpcProvider<Integer> provider = injector
        .getInstance(Key.get(rpcProviderOfInteger));

    assertEquals((Integer)100, provider.get());
    testModule.setNextIntToReturn(120);
    assertEquals((Integer)100, provider.get());
    testScope.beginNewScope();
    assertEquals((Integer)120, provider.get());
  }

  public void testWithAnnotation() throws BindException, RemoteException {
    TestModule testModule = new TestModule();
    Injector injector = Guice.createInjector(testModule);
    RpcProvider<Long> provider = injector
        .getInstance(Key.get(rpcProviderOfLong, TestAnnotation.class));
    assertEquals((Long)0xffL, provider.get());
  }

  public void testWithInjectedParameters() throws BindException, RemoteException {
    TestModule testModule = new TestModule();
    Injector injector = Guice.createInjector(testModule);
    RpcProvider<Pair<Double, String>> provider = injector
        .getInstance(Key.get(rpcProviderOfPair));
    Pair<Double, String> pair = provider.get();
    assertEquals(pair.first, 4.0d);
  }

  public void testWithThrownException() {
    TestModule testModule = new TestModule();
    Injector injector = Guice.createInjector(testModule);
    RpcProvider<Float> provider = injector
        .getInstance(Key.get(rpcProviderOfFloat));
    try {
      provider.get();
      fail();
    } catch (RemoteException e) {
      fail();
    } catch (BindException e) {
      // good
    }
  }

  public void testExposedMethod() throws BindException, RemoteException {
    TestModule testModule = new TestModule();
    Injector injector = Guice.createInjector(testModule);
    RpcProvider<String> provider = injector
        .getInstance(Key.get(rpcProviderOfString, Names.named("fruit")));
    assertEquals("apple", provider.get());

  }
  
  private static class Pair<A, B> {
	A first;
	B second;
	
	Pair(A a, B b) {
	 this.first= a;
	 this.second = b;
	}
  }
}