/**
 * Copyright (C) 2007 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.throwingproviders;

import static com.google.common.base.Preconditions.checkNotNull;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.inject.Binder;
import com.google.inject.ConfigurationException;
import com.google.inject.Key;
import com.google.inject.Module;
import com.google.inject.Provider;
import com.google.inject.ProvisionException;
import com.google.inject.Scopes;
import com.google.inject.TypeLiteral;
import com.google.inject.binder.ScopedBindingBuilder;
import com.google.inject.internal.UniqueAnnotations;
import com.google.inject.spi.Dependency;
import com.google.inject.spi.InjectionPoint;
import com.google.inject.spi.Message;
import com.google.inject.spi.ProviderWithDependencies;
import com.google.inject.util.Types;

import java.io.Serializable;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Proxy;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.Arrays;
import java.util.List;
import java.util.Set;

/**
 * <p>Builds a binding for a {@link CheckedProvider}.
 * 
 * <p>You can use a fluent API and custom providers:
 * <pre><code>ThrowingProviderBinder.create(binder())
 *    .bind(RemoteProvider.class, Customer.class)
 *    .to(RemoteCustomerProvider.class)
 *    .in(RequestScope.class);
 * </code></pre>
 * or, you can use throwing provider methods:
 * <pre><code>class MyModule extends AbstractModule {
 *   configure() {
 *     ThrowingProviderBinder.install(this, binder());
 *   }
 *   
 *   {@literal @}CheckedProvides(RemoteProvider.class)
 *   {@literal @}RequestScope
 *   Customer provideCustomer(FlakyCustomerCreator creator) throws RemoteException {
 *     return creator.getCustomerOrThrow();
 *   }
 * }
 * </code></pre>
 * You also can declare that a CheckedProvider construct
 * a particular class whose constructor throws an exception:
 * <pre><code>ThrowingProviderBinder.create(binder())
 *    .bind(RemoteProvider.class, Customer.class)
 *    .providing(CustomerImpl.class)
 *    .in(RequestScope.class);
 * </code></pre>
 * 
 * @author jmourits@google.com (Jerome Mourits)
 * @author jessewilson@google.com (Jesse Wilson)
 * @author sameb@google.com (Sam Berlin)
 */
public class ThrowingProviderBinder {

  private final Binder binder;

  private ThrowingProviderBinder(Binder binder) {
    this.binder = binder;
  }

  public static ThrowingProviderBinder create(Binder binder) {
    return new ThrowingProviderBinder(binder.skipSources(
        ThrowingProviderBinder.class,
        ThrowingProviderBinder.SecondaryBinder.class));
  }
  
  /**
   * Returns a module that installs {@literal @}{@link CheckedProvides} methods.
   * 
   * @since 3.0
   */
  public static Module forModule(Module module) {
    return CheckedProviderMethodsModule.forModule(module);
  }
  
  /**
   * @deprecated Use {@link #bind(Class, Class)} or {@link #bind(Class, TypeLiteral)} instead. 
   */
  @Deprecated
  public <P extends CheckedProvider> SecondaryBinder<P, ?> 
      bind(Class<P> interfaceType, Type clazz) {
    return new SecondaryBinder<P, Object>(interfaceType, clazz);
  }

  public <P extends CheckedProvider, T> SecondaryBinder<P, T> 
      bind(Class<P> interfaceType, Class<T> clazz) {
    return new SecondaryBinder<P, T>(interfaceType, clazz);
  }
  
  public <P extends CheckedProvider, T> SecondaryBinder<P, T> 
      bind(Class<P> interfaceType, TypeLiteral<T> typeLiteral) {
    return new SecondaryBinder<P, T>(interfaceType, typeLiteral.getType());
  }

  public class SecondaryBinder<P extends CheckedProvider, T> {
    private final Class<P> interfaceType;
    private final Type valueType;
    private final List<Class<? extends Throwable>> exceptionTypes;
    private final boolean valid;

    private Class<? extends Annotation> annotationType;
    private Annotation annotation;
    private Key<P> interfaceKey;

    public SecondaryBinder(Class<P> interfaceType, Type valueType) {
      this.interfaceType = checkNotNull(interfaceType, "interfaceType");
      this.valueType = checkNotNull(valueType, "valueType");
      if(checkInterface()) {
        this.exceptionTypes = getExceptionType(interfaceType);
        valid = true;
      } else {
        valid = false;
        this.exceptionTypes = ImmutableList.of();
      }      
    }
    
    List<Class<? extends Throwable>> getExceptionTypes() {
      return exceptionTypes;
    }
    
    Key<P> getKey() {
      return interfaceKey;
    }

    public SecondaryBinder<P, T> annotatedWith(Class<? extends Annotation> annotationType) {
      if (!(this.annotationType == null && this.annotation == null)) {
        throw new IllegalStateException("Cannot set annotation twice");
      }
      this.annotationType = annotationType;
      return this;
    }

    public SecondaryBinder<P, T> annotatedWith(Annotation annotation) {
      if (!(this.annotationType == null && this.annotation == null)) {
        throw new IllegalStateException("Cannot set annotation twice");
      }
      this.annotation = annotation;
      return this;
    }

    public ScopedBindingBuilder to(P target) {
      Key<P> targetKey = Key.get(interfaceType, UniqueAnnotations.create());
      binder.bind(targetKey).toInstance(target);
      return to(targetKey);
    }
    
    public ScopedBindingBuilder to(Class<? extends P> targetType) {
      return to(Key.get(targetType));
    }
    
    public ScopedBindingBuilder providing(Class<? extends T> cxtorClass) {
      return providing(TypeLiteral.get(cxtorClass));
    }
    
    @SuppressWarnings("unchecked") // safe because this is the cxtor of the literal
    public ScopedBindingBuilder providing(TypeLiteral<? extends T> cxtorLiteral) {     
      // Find a constructor that has @ThrowingInject.
      Constructor<? extends T> cxtor =
          CheckedProvideUtils.findThrowingConstructor(cxtorLiteral, binder);

      final Provider<T> typeProvider;
      final Key<? extends T> typeKey;
      // If we found an injection point, then bind the cxtor to a unique key
      if (cxtor != null) {
        // Validate the exceptions are consistent with the CheckedProvider interface.
        CheckedProvideUtils.validateExceptions(
            binder, cxtorLiteral.getExceptionTypes(cxtor), exceptionTypes, interfaceType);
        
        typeKey = Key.get(cxtorLiteral, UniqueAnnotations.create());
        binder.bind(typeKey).toConstructor((Constructor) cxtor).in(Scopes.NO_SCOPE);
        typeProvider = binder.getProvider((Key<T>) typeKey);
      } else {
        // never used, but need it assigned.
        typeProvider = null;
        typeKey = null;
      }
        
      // Create a CheckedProvider that calls our cxtor
      CheckedProvider<T> checkedProvider = new CheckedProviderWithDependencies<T>() {
        @Override
        public T get() throws Exception {
          try {
            return typeProvider.get();
          } catch (ProvisionException pe) {
            // Rethrow the provision cause as the actual exception
            if (pe.getCause() instanceof Exception) {
              throw (Exception) pe.getCause();
            } else if (pe.getCause() instanceof Error) {
              throw (Error) pe.getCause();
            } else {
              // If this failed because of multiple reasons (ie, more than
              // one dependency failed due to scoping errors), then
              // the ProvisionException won't have a cause, so we need
              // to rethrow it as-is.
              throw pe;
            }
          }
        }
        
        @Override
        public Set<Dependency<?>> getDependencies() {
          return ImmutableSet.<Dependency<?>>of(Dependency.get(typeKey));
        }
      };
      
      Key<CheckedProvider> targetKey = Key.get(CheckedProvider.class, UniqueAnnotations.create());
      binder.bind(targetKey).toInstance(checkedProvider);
      return toInternal(targetKey);
    }
    
    ScopedBindingBuilder toProviderMethod(CheckedProviderMethod<?> target) {
      Key<CheckedProviderMethod> targetKey =
          Key.get(CheckedProviderMethod.class, UniqueAnnotations.create());
      binder.bind(targetKey).toInstance(target);

      return toInternal(targetKey);
    }

    public ScopedBindingBuilder to(Key<? extends P> targetKey) {
      checkNotNull(targetKey, "targetKey");
      return toInternal(targetKey);
    }
    
    private ScopedBindingBuilder toInternal(final Key<? extends CheckedProvider> targetKey) {
      final Key<Result> resultKey = Key.get(Result.class, UniqueAnnotations.create());
      final Provider<Result> resultProvider = binder.getProvider(resultKey);
      final Provider<? extends CheckedProvider> targetProvider = binder.getProvider(targetKey);
      interfaceKey = createKey();

      // don't bother binding the proxy type if this is in an invalid state.
      if(valid) {
        binder.bind(interfaceKey).toProvider(new ProviderWithDependencies<P>() {
          private final P instance = interfaceType.cast(Proxy.newProxyInstance(
              interfaceType.getClassLoader(), new Class<?>[] { interfaceType },
              new InvocationHandler() {
                public Object invoke(Object proxy, Method method, Object[] args)
                    throws Throwable {
                  // Allow methods like .equals(..), .hashcode(..), .toString(..) to work.
                  if (method.getDeclaringClass() == Object.class) {
                    return method.invoke(this, args);
                  }
                  return resultProvider.get().getOrThrow();
                }
              }));
            
            public P get() {
              return instance;
            }
            
            public Set<Dependency<?>> getDependencies() {
              return ImmutableSet.<Dependency<?>>of(Dependency.get(resultKey));
            }
          });
      }

      return binder.bind(resultKey).toProvider(new ProviderWithDependencies<Result>() {
        public Result get() {
          try {
            return Result.forValue(targetProvider.get().get());
          } catch (Exception e) {
            for(Class<? extends Throwable> exceptionType : exceptionTypes) {
              if (exceptionType.isInstance(e)) {
                return Result.forException(e);
              }
            }
            
            if (e instanceof RuntimeException) {
              throw (RuntimeException) e;
            } else {
              // this should never happen
              throw new RuntimeException(e);
            }
          }
        }
        
        public Set<Dependency<?>> getDependencies() {
          return ImmutableSet.<Dependency<?>>of(Dependency.get(targetKey));
        }
      });
    }

    /**
     * Returns the exception type declared to be thrown by the get method of
     * {@code interfaceType}.
     */
    private List<Class<? extends Throwable>> getExceptionType(Class<P> interfaceType) {
      try {
        Method getMethod = interfaceType.getMethod("get");
        List<TypeLiteral<?>> exceptionLiterals =
            TypeLiteral.get(interfaceType).getExceptionTypes(getMethod);
        List<Class<? extends Throwable>> results = Lists.newArrayList();
        for (TypeLiteral<?> exLiteral : exceptionLiterals) {
          results.add(exLiteral.getRawType().asSubclass(Throwable.class));
        }
        return results;
      } catch (SecurityException e) {
        throw new IllegalStateException("Not allowed to inspect exception types", e);
      } catch (NoSuchMethodException e) {
        throw new IllegalStateException("No 'get'method available", e);
      }
    }

    private boolean checkInterface() {
      if(!checkArgument(interfaceType.isInterface(),
         "%s must be an interface", interfaceType.getName())) {
        return false;
      }
      if(!checkArgument(interfaceType.getGenericInterfaces().length == 1,
          "%s must extend CheckedProvider (and only CheckedProvider)",
          interfaceType)) {
        return false;
      }
      
      boolean tpMode = interfaceType.getInterfaces()[0] == ThrowingProvider.class;      
      if(!tpMode) {
        if(!checkArgument(interfaceType.getInterfaces()[0] == CheckedProvider.class,
            "%s must extend CheckedProvider (and only CheckedProvider)",
            interfaceType)) {
          return false;
        }
      }

      // Ensure that T is parameterized and unconstrained.
      ParameterizedType genericThrowingProvider
          = (ParameterizedType) interfaceType.getGenericInterfaces()[0];
      if (interfaceType.getTypeParameters().length == 1) {
        String returnTypeName = interfaceType.getTypeParameters()[0].getName();
        Type returnType = genericThrowingProvider.getActualTypeArguments()[0];
        if(!checkArgument(returnType instanceof TypeVariable,
            "%s does not properly extend CheckedProvider, the first type parameter of CheckedProvider (%s) is not a generic type",
            interfaceType, returnType)) {
          return false;
        }
        if(!checkArgument(returnTypeName.equals(((TypeVariable) returnType).getName()),
            "The generic type (%s) of %s does not match the generic type of CheckedProvider (%s)",
            returnTypeName, interfaceType, ((TypeVariable)returnType).getName())) {
          return false;
        }
      } else {
        if(!checkArgument(interfaceType.getTypeParameters().length == 0,
            "%s has more than one generic type parameter: %s",
            interfaceType, Arrays.asList(interfaceType.getTypeParameters()))) {
          return false;
        }
        if(!checkArgument(genericThrowingProvider.getActualTypeArguments()[0].equals(valueType),
            "%s expects the value type to be %s, but it was %s",
            interfaceType, genericThrowingProvider.getActualTypeArguments()[0], valueType)) {
          return false;
        }
      }

      if(tpMode) { // only validate exception in ThrowingProvider mode.
        Type exceptionType = genericThrowingProvider.getActualTypeArguments()[1];
        if(!checkArgument(exceptionType instanceof Class,
            "%s has the wrong Exception generic type (%s) when extending CheckedProvider",
            interfaceType, exceptionType)) {
          return false;
        }
      }
      
      if (interfaceType.getDeclaredMethods().length == 1) {
        Method method = interfaceType.getDeclaredMethods()[0];
        if(!checkArgument(method.getName().equals("get"),
            "%s may not declare any new methods, but declared %s",
            interfaceType, method)) {
          return false;
        }
        if(!checkArgument(method.getParameterTypes().length == 0,
            "%s may not declare any new methods, but declared %s",
            interfaceType, method.toGenericString())) {
          return false;
        }
      } else {
        if(!checkArgument(interfaceType.getDeclaredMethods().length == 0,
            "%s may not declare any new methods, but declared %s",
            interfaceType, Arrays.asList(interfaceType.getDeclaredMethods()))) {
          return false;
        }
      }
      
      return true;
    }

    private boolean checkArgument(boolean condition,
        String messageFormat, Object... args) {
      if (!condition) {
        binder.addError(messageFormat, args);
        return false;
      } else {
        return true;
      }
    }

    @SuppressWarnings({"unchecked"})
    private Key<P> createKey() {
      TypeLiteral<P> typeLiteral;
      if (interfaceType.getTypeParameters().length == 1) {
        ParameterizedType type = Types.newParameterizedTypeWithOwner(
            interfaceType.getEnclosingClass(), interfaceType, valueType);
        typeLiteral = (TypeLiteral<P>) TypeLiteral.get(type);
      } else {
        typeLiteral = TypeLiteral.get(interfaceType);
      }

      if (annotation != null) {
        return Key.get(typeLiteral, annotation);
        
      } else if (annotationType != null) {
        return Key.get(typeLiteral, annotationType);
        
      } else {
        return Key.get(typeLiteral);
      }
    }
  }

  /**
   * Represents the returned value from a call to {@link
   * CheckedProvider#get()}. This is the value that will be scoped by Guice.
   */
  static class Result implements Serializable {
    private final Object value;
    private final Exception exception;

    private Result(Object value, Exception exception) {
      this.value = value;
      this.exception = exception;
    }

    public static Result forValue(Object value) {
      return new Result(value, null);
    }

    public static Result forException(Exception e) {
      return new Result(null, e);
    }

    public Object getOrThrow() throws Exception {
      if (exception != null) {
        throw exception;
      } else {
        return value;
      }
    }
    
    private static final long serialVersionUID = 0L;
  }
}
