/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 org.apache.aries.proxy.impl.common;

import static java.lang.String.format;

import java.util.Map;
import java.util.Set;

import org.apache.aries.proxy.FinalModifierException;
import org.apache.aries.proxy.UnableToProxyException;
import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.Attribute;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.GeneratorAdapter;
import org.objectweb.asm.commons.Method;

/**
 * This class is used to copy concrete methods from a super-class into a sub-class, 
 * but then delegate up to the super-class implementation. We expect to be called
 * with {@link ClassReader#SKIP_CODE}. This class is used when we can't weave
 * all the way up the Class hierarchy and need to override methods on the first
 * subclass we can weave.
 */
final class MethodCopyingClassAdapter extends ClassVisitor implements Opcodes {
  /** The super-class to copy from */
  private final Class<?> superToCopy;
  /** Is the sub-class in the same package as the super */
  private final boolean samePackage;
  /** The ASM {@link Type} of the sub-class */
  private final Type overridingClassType;
  /** 
   * The Set of {@link Method}s that exist in the sub-class. This set must be
   * live so modifications will be reflected in the parent and prevent clashes 
   */
  private final Set<Method> knownMethods;
  /**
   * The map of field names to methods being added
   */
  private final Map<String, TypeMethod> transformedMethods;
  
  private final AbstractWovenProxyAdapter wovenProxyAdapter;
  
  public MethodCopyingClassAdapter(AbstractWovenProxyAdapter awpa, ClassLoader definingLoader,
      Class<?> superToCopy, Type overridingClassType, Set<Method> knownMethods, 
      Map<String, TypeMethod> transformedMethods) {
    super(Opcodes.ASM9);
    this.wovenProxyAdapter = awpa;
    this.superToCopy = superToCopy;
    this.overridingClassType = overridingClassType;
    this.knownMethods = knownMethods;
    this.transformedMethods = transformedMethods;
    
    //To be in the same package they must be loaded by the same classloader and be in the same package!
    if(definingLoader != superToCopy.getClassLoader()) {
    	samePackage = false;
    } else {
    
      String overridingClassName = overridingClassType.getClassName();
      int lastIndex1 = superToCopy.getName().lastIndexOf('.');
      int lastIndex2 = overridingClassName.lastIndexOf('.');
      
      if(lastIndex1 != lastIndex2) {
        samePackage = false;
      } else if (lastIndex1 == -1) {
        samePackage = true;
      } else {
        samePackage = superToCopy.getName().substring(0, lastIndex1)
         .equals(overridingClassName.substring(0, lastIndex2));
      }
    }
  }
  
  @Override
  public final MethodVisitor visitMethod(final int access, String name, String desc,
      String sig, String[] exceptions) {
    
    MethodVisitor mv = null;
    //As in WovenProxyAdapter, we only care about "real" methods, but also not
    //abstract ones!.
    if (!!!name.equals("<init>") && !!!name.equals("<clinit>")
        && (access & (ACC_STATIC | ACC_PRIVATE | ACC_SYNTHETIC | ACC_ABSTRACT
            | ACC_NATIVE | ACC_BRIDGE)) == 0) {

      // identify the target method parameters and return type
      Method currentTransformMethod = new Method(name, desc);
      // We don't want to duplicate a method we already overrode! 
      if(!!!knownMethods.add(currentTransformMethod))
        return null;
      
      // found a method we should weave
      // We can't override a final method
      if((access & ACC_FINAL) != 0)
        throw new RuntimeException(new FinalModifierException(
            superToCopy, name));
      // We can't call up to a default access method if we aren't in the same
      // package
      if((access & (ACC_PUBLIC | ACC_PROTECTED | ACC_PRIVATE)) == 0) {
        if(!!!samePackage) {
            methodHiddenException(name);
        }
      }
      //Safe to copy a call to this method!
      Type superType = Type.getType(superToCopy);
      
      // identify the target method parameters and return type
      String methodStaticFieldName = "methodField" + AbstractWovenProxyAdapter.getSanitizedUUIDString();
      transformedMethods.put(methodStaticFieldName, new TypeMethod(
          superType, currentTransformMethod));  
      
      //Remember we need to copy the fake method *and* weave it, use a 
      //WovenProxyMethodAdapter as well as a CopyingMethodAdapter
      
      MethodVisitor weaver = wovenProxyAdapter.getWeavingMethodVisitor(
              access, name, desc, sig, exceptions, currentTransformMethod, 
              methodStaticFieldName, superType, false);
      
      if(weaver instanceof AbstractWovenProxyMethodAdapter) {
        //If we are weaving this method then we might have a problem. If it's a protected method and we
        //aren't in the same package then we can't dispatch the call to another object. This may sound
        //odd, but if class Super has a protected method foo(), then class Sub, that extends Super, cannot
        //call ((Super)o).foo() in code (it can call super.foo()). If we are in the same package then this
    	//gets around the problem, but if not the class will fail verification.
        if(!samePackage && (access & ACC_PROTECTED) != 0) {
            methodHiddenException(name);
        }
        mv = new CopyingMethodAdapter((GeneratorAdapter) weaver, superType, currentTransformMethod);
      }
      else {
        //For whatever reason we aren't weaving this method. The call to super.xxx() will always work
        mv = new CopyingMethodAdapter(new GeneratorAdapter(access, currentTransformMethod, mv), 
             superType, currentTransformMethod);
      }
    }
    
    return mv;
  }

private void methodHiddenException(String name) {
    String msg = format("The method %s in class %s cannot be called by %s because it is in a different package.",
                        name, superToCopy.getName(), overridingClassType.getClassName());
    throw new RuntimeException(msg,
                                 new UnableToProxyException(superToCopy));
}
  
  /**
   * This class is used to prevent any method body being copied, instead replacing
   * the body with a call to the super-types implementation. The original annotations
   * attributes etc are all copied.
   */
  private static final class CopyingMethodAdapter extends MethodVisitor {
    /** The visitor to delegate to */
    private final GeneratorAdapter mv;
    /** The type that declares this method (not the one that will override it) */
    private final Type superType;
    /** The method we are weaving */
    private final Method currentTransformMethod;
    
    public CopyingMethodAdapter(GeneratorAdapter mv, Type superType, 
        Method currentTransformMethod) {
      super(Opcodes.ASM9);
      this.mv = mv;
      this.superType = superType;
      this.currentTransformMethod = currentTransformMethod;
    }

    //TODO might not work for attributes
    @Override
    public final AnnotationVisitor visitAnnotation(String arg0, boolean arg1) {
      return mv.visitAnnotation(arg0, arg1);
    }

    @Override
    public final AnnotationVisitor visitAnnotationDefault() {
      return mv.visitAnnotationDefault();
    }

    @Override
    public final AnnotationVisitor visitParameterAnnotation(int arg0, String arg1,
        boolean arg2) {
      return mv.visitParameterAnnotation(arg0, arg1, arg2);
    }
    
    @Override
    public final void visitAttribute(Attribute attr) {
      mv.visitAttribute(attr);
    }

    /**
     * We skip code for speed when processing super-classes, this means we
     * need to manually drive some methods here!
     */
    @Override
    public final void visitEnd() {
      mv.visitCode();
      
      //Equivalent to return super.method(args);
      mv.loadThis();
	  mv.loadArgs();
	  mv.visitMethodInsn(INVOKESPECIAL, superType.getInternalName(),
	      currentTransformMethod.getName(), currentTransformMethod.getDescriptor());
	  mv.returnValue();

	  mv.visitMaxs(currentTransformMethod.getArgumentTypes().length + 1, 0);
      mv.visitEnd();
    }
  }
}
