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

import static com.google.inject.internal.BytecodeGen.newFastClass;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.inject.spi.InjectionPoint;

import net.sf.cglib.core.MethodWrapper;
import net.sf.cglib.proxy.Callback;
import net.sf.cglib.proxy.CallbackFilter;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.reflect.FastClass;
import net.sf.cglib.reflect.FastConstructor;

import org.aopalliance.intercept.MethodInterceptor;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * Builds a construction proxy that can participate in AOP. This class manages applying type and
 * method matchers to come up with the set of intercepted methods.
 *
 * @author jessewilson@google.com (Jesse Wilson)
 */
final class ProxyFactory<T> implements ConstructionProxyFactory<T> {
  
  private static final Logger logger = Logger.getLogger(ProxyFactory.class.getName());

  private final InjectionPoint injectionPoint;
  private final ImmutableMap<Method, List<MethodInterceptor>> interceptors;
  private final Class<T> declaringClass;
  private final List<Method> methods;
  private final Callback[] callbacks;

  /**
   * PUBLIC is default; it's used if all the methods we're intercepting are public. This impacts
   * which classloader we should use for loading the enhanced class
   */
  private BytecodeGen.Visibility visibility = BytecodeGen.Visibility.PUBLIC;

  ProxyFactory(InjectionPoint injectionPoint, Iterable<MethodAspect> methodAspects) {
    this.injectionPoint = injectionPoint;

    @SuppressWarnings("unchecked") // the member of injectionPoint is always a Constructor<T>
        Constructor<T> constructor = (Constructor<T>) injectionPoint.getMember();
    declaringClass = constructor.getDeclaringClass();

    // Find applicable aspects. Bow out if none are applicable to this class.
    List<MethodAspect> applicableAspects = Lists.newArrayList();
    for (MethodAspect methodAspect : methodAspects) {
      if (methodAspect.matches(declaringClass)) {
        applicableAspects.add(methodAspect);
      }
    }

    if (applicableAspects.isEmpty()) {
      interceptors = ImmutableMap.of();
      methods = ImmutableList.of();
      callbacks = null;
      return;
    }

    // Get list of methods from cglib.
    methods = Lists.newArrayList();
    Enhancer.getMethods(declaringClass, null, methods);

    // Create method/interceptor holders and record indices.
    List<MethodInterceptorsPair> methodInterceptorsPairs = Lists.newArrayList();
    for (Method method : methods) {
      methodInterceptorsPairs.add(new MethodInterceptorsPair(method));
    }

    // Iterate over aspects and add interceptors for the methods they apply to
    boolean anyMatched = false;
    for (MethodAspect methodAspect : applicableAspects) {
      for (MethodInterceptorsPair pair : methodInterceptorsPairs) {
        if (methodAspect.matches(pair.method)) {
          if(pair.method.isSynthetic()) {
            logger.log(Level.WARNING,
                "Method [{0}] is synthetic and is being intercepted by {1}."
              + " This could indicate a bug.  The method may be intercepted twice,"
              + " or may not be intercepted at all.",
                new Object[] { pair.method, methodAspect.interceptors() });
          }
          visibility = visibility.and(BytecodeGen.Visibility.forMember(pair.method));
          pair.addAll(methodAspect.interceptors());
          anyMatched = true;
        }
      }
    }

    if (!anyMatched) {
      interceptors = ImmutableMap.of();
      callbacks = null;
      return;
    }

    ImmutableMap.Builder<Method, List<MethodInterceptor>> interceptorsMapBuilder = null; // lazy

    callbacks = new Callback[methods.size()];
    for (int i = 0; i < methods.size(); i++) {
      MethodInterceptorsPair pair = methodInterceptorsPairs.get(i);

      if (!pair.hasInterceptors()) {
        callbacks[i] = net.sf.cglib.proxy.NoOp.INSTANCE;
        continue;
      }

      if (interceptorsMapBuilder == null) {
        interceptorsMapBuilder = ImmutableMap.builder();
      }

      ImmutableList<MethodInterceptor> deDuplicated =
          ImmutableSet.copyOf(pair.interceptors).asList();
      interceptorsMapBuilder.put(pair.method, deDuplicated);
      callbacks[i] = new InterceptorStackCallback(pair.method, deDuplicated);
    }

    interceptors = interceptorsMapBuilder != null
        ? interceptorsMapBuilder.build()
        : ImmutableMap.<Method, List<MethodInterceptor>>of();
  }

  /**
   * Returns the interceptors that apply to the constructed type.
   */
  public ImmutableMap<Method, List<MethodInterceptor>> getInterceptors() {
    return interceptors;
  }

  public ConstructionProxy<T> create() throws ErrorsException {
    if (interceptors.isEmpty()) {
      return new DefaultConstructionProxyFactory<T>(injectionPoint).create();
    }

    @SuppressWarnings("unchecked")
    Class<? extends Callback>[] callbackTypes = new Class[callbacks.length];
    for (int i = 0; i < callbacks.length; i++) {
      if (callbacks[i] == net.sf.cglib.proxy.NoOp.INSTANCE) {
        callbackTypes[i] = net.sf.cglib.proxy.NoOp.class;
      } else {
        callbackTypes[i] = net.sf.cglib.proxy.MethodInterceptor.class;
      }
    }

    // Create the proxied class. We're careful to ensure that all enhancer state is not-specific
    // to this injector. Otherwise, the proxies for each injector will waste PermGen memory
    try {
    Enhancer enhancer = BytecodeGen.newEnhancer(declaringClass, visibility);
    enhancer.setCallbackFilter(new IndicesCallbackFilter(methods));
    enhancer.setCallbackTypes(callbackTypes);
    return new ProxyConstructor<T>(enhancer, injectionPoint, callbacks, interceptors);
    } catch (Throwable e) {
      throw new Errors().errorEnhancingClass(declaringClass, e).toException();
    }
  }

  private static class MethodInterceptorsPair {
    final Method method;
    List<MethodInterceptor> interceptors; // lazy

    MethodInterceptorsPair(Method method) {
      this.method = method;
    }

    void addAll(List<MethodInterceptor> interceptors) {
      if (this.interceptors == null) {
        this.interceptors = Lists.newArrayList();
      }
      this.interceptors.addAll(interceptors);
    }

    boolean hasInterceptors() {
      return interceptors != null;
    }
  }

  /**
   * A callback filter that maps methods to unique IDs. We define equals and
   * hashCode without using any state related to the injector so that enhanced
   * classes intercepting the same methods can be shared between injectors (and
   * child injectors, etc).
   */
  private static class IndicesCallbackFilter implements CallbackFilter {
    final Map<Object, Integer> indices;
    final int hashCode;

    IndicesCallbackFilter(List<Method> methods) {
      final Map<Object, Integer> indices = Maps.newHashMap();
      for (int i = 0; i < methods.size(); i++) {
        indices.put(MethodWrapper.create(methods.get(i)), i);
      }
      this.indices = indices;
      this.hashCode = indices.hashCode();
    }

    public int accept(Method method) {
      return indices.get(MethodWrapper.create(method));
    }

    @Override public boolean equals(Object o) {
      return o instanceof IndicesCallbackFilter &&
          ((IndicesCallbackFilter) o).indices.equals(indices);
    }

    @Override public int hashCode() {
      return hashCode;
    }
  }

  /**
   * Constructs instances that participate in AOP.
   */
  private static class ProxyConstructor<T> implements ConstructionProxy<T> {
    final Class<?> enhanced;
    final InjectionPoint injectionPoint;
    final Constructor<T> constructor;
    final Callback[] callbacks;

    final FastConstructor fastConstructor;
    final ImmutableMap<Method, List<MethodInterceptor>> methodInterceptors;

    @SuppressWarnings("unchecked") // the constructor promises to construct 'T's
    ProxyConstructor(Enhancer enhancer, InjectionPoint injectionPoint, Callback[] callbacks,
        ImmutableMap<Method, List<MethodInterceptor>> methodInterceptors) {
      this.enhanced = enhancer.createClass(); // this returns a cached class if possible
      this.injectionPoint = injectionPoint;
      this.constructor = (Constructor<T>) injectionPoint.getMember();
      this.callbacks = callbacks;
      this.methodInterceptors = methodInterceptors;

      FastClass fastClass = newFastClass(enhanced, BytecodeGen.Visibility.forMember(constructor));
      this.fastConstructor = fastClass.getConstructor(constructor.getParameterTypes());
    }

    @SuppressWarnings("unchecked") // the constructor promises to produce 'T's
    public T newInstance(Object... arguments) throws InvocationTargetException {
      Enhancer.registerCallbacks(enhanced, callbacks);
      try {
        return (T) fastConstructor.newInstance(arguments);
      } finally {
        Enhancer.registerCallbacks(enhanced, null);
      }
    }

    public InjectionPoint getInjectionPoint() {
      return injectionPoint;
    }

    public Constructor<T> getConstructor() {
      return constructor;
    }

    public ImmutableMap<Method, List<MethodInterceptor>> getMethodInterceptors() {
      return methodInterceptors;
    }
  }
}
