// 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 org.apache.tapestry5.internal.plastic;

import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
import org.apache.tapestry5.internal.plastic.asm.Opcodes;
import org.apache.tapestry5.internal.plastic.asm.Type;
import org.apache.tapestry5.internal.plastic.asm.tree.*;
import org.apache.tapestry5.plastic.*;

import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.*;

@SuppressWarnings("all")
public class PlasticClassImpl extends Lockable implements PlasticClass, InternalPlasticClassTransformation, Opcodes
{
    private static final String NOTHING_TO_VOID = "()V";

    static final String CONSTRUCTOR_NAME = "<init>";

    private static final String OBJECT_INT_TO_OBJECT = "(Ljava/lang/Object;I)Ljava/lang/Object;";

    private static final String OBJECT_INT_OBJECT_TO_VOID = "(Ljava/lang/Object;ILjava/lang/Object;)V";

    private static final String OBJECT_INT_OBJECT_ARRAY_TO_METHOD_INVOCATION_RESULT = String.format(
            "(Ljava/lang/Object;I[Ljava/lang/Object;)%s", toDesc(Type.getInternalName(MethodInvocationResult.class)));

    static final String ABSTRACT_METHOD_INVOCATION_INTERNAL_NAME = PlasticInternalUtils
            .toInternalName(AbstractMethodInvocation.class.getName());

    private static final String HANDLE_SHIM_BASE_CLASS_INTERNAL_NAME = Type
            .getInternalName(PlasticClassHandleShim.class);

    static final String STATIC_CONTEXT_INTERNAL_NAME = Type.getInternalName(StaticContext.class);

    private static final String INSTANCE_CONTEXT_INTERNAL_NAME = Type.getInternalName(InstanceContext.class);

    private static final String INSTANCE_CONTEXT_DESC = toDesc(INSTANCE_CONTEXT_INTERNAL_NAME);

    private static final String CONSTRUCTOR_DESC = String.format("(L%s;L%s;)V", STATIC_CONTEXT_INTERNAL_NAME,
            INSTANCE_CONTEXT_INTERNAL_NAME);

    static final Method STATIC_CONTEXT_GET_METHOD = toMethod(StaticContext.class, "get", int.class);

    static final Method COMPUTED_VALUE_GET_METHOD = toMethod(ComputedValue.class, "get", InstanceContext.class);

    private static final Method CONSTRUCTOR_CALLBACK_METHOD = toMethod(ConstructorCallback.class, "onConstruct",
            Object.class, InstanceContext.class);

    private static String toDesc(String internalName)
    {
        return "L" + internalName + ";";
    }

    private static Method toMethod(Class declaringClass, String methodName, Class... parameterTypes)
    {
        return PlasticUtils.getMethod(declaringClass, methodName, parameterTypes);
    }

    static <T> T safeArrayDeref(T[] array, int index)
    {
        if (array == null)
            return null;

        return array[index];
    }

    // Now past the inner classes; these are the instance variables of PlasticClassImpl proper:

    final ClassNode classNode;

    final PlasticClassPool pool;

    private final boolean proxy;

    final String className;

    private final String superClassName;

    private final AnnotationAccess annotationAccess;

    // All the non-introduced (and non-constructor) methods, in sorted order

    private final List<PlasticMethodImpl> methods;

    private final Map<MethodDescription, PlasticMethod> description2method = new HashMap<>();

    final Set<String> methodNames = new HashSet<>();

    private final List<ConstructorCallback> constructorCallbacks = PlasticInternalUtils.newList();

    // All non-introduced instance fields

    private final List<PlasticFieldImpl> fields;

    /**
     * Methods that require special attention inside {@link #createInstantiator()} because they
     * have method advice.
     */
    final Set<PlasticMethodImpl> advisedMethods = PlasticInternalUtils.newSet();

    final NameCache nameCache = new NameCache();

    // This is generated from fields, as necessary
    List<PlasticField> unclaimedFields;

    private final Set<String> fieldNames = PlasticInternalUtils.newSet();

    final StaticContext staticContext;

    final InheritanceData parentInheritanceData, inheritanceData;

    // MethodNodes in which field transformations should occur; this is most existing and
    // introduced methods, outside of special access methods.

    final Set<MethodNode> fieldTransformMethods = PlasticInternalUtils.newSet();

    // Tracks any methods that the Shim class uses to gain access to fields; used to ensure that
    // such methods are not optimized away incorrectly.
    final Set<MethodNode> shimInvokedMethods = PlasticInternalUtils.newSet();


    /**
     * Tracks instrumentations of fields of this class, including private fields which are not published into the
     * {@link PlasticClassPool}.
     */
    private final FieldInstrumentations fieldInstrumentations;

    /**
     * This normal no-arguments constructor, or null. By the end of the transformation
     * this will be converted into an ordinary method.
     */
    private MethodNode originalConstructor;

    private final MethodNode newConstructor;

    final InstructionBuilder constructorBuilder;

    private String instanceContextFieldName;

    private Class<?> transformedClass;

    // Indexes used to identify fields or methods in the shim
    int nextFieldIndex = 0;

    int nextMethodIndex = 0;

    // Set of fields that need to contribute to the shim and gain access to it

    final Set<PlasticFieldImpl> shimFields = PlasticInternalUtils.newSet();

    // Set of methods that need to contribute to the shim and gain access to it

    final Set<PlasticMethodImpl> shimMethods = PlasticInternalUtils.newSet();

    final ClassNode implementationClassNode;

    private ClassNode interfaceClassNode;

    /**
     * @param classNode
     * @param implementationClassNode
     * @param pool
     * @param parentInheritanceData
     * @param parentStaticContext
     * @param proxy
     */
    public PlasticClassImpl(ClassNode classNode, ClassNode implementationClassNode, PlasticClassPool pool, InheritanceData parentInheritanceData,
                            StaticContext parentStaticContext, boolean proxy)
    {
        this.classNode = classNode;
        this.pool = pool;
        this.proxy = proxy;
        this.implementationClassNode = implementationClassNode;

        staticContext = parentStaticContext.dupe();

        className = PlasticInternalUtils.toClassName(classNode.name);
        superClassName = PlasticInternalUtils.toClassName(classNode.superName);
        int lastIndexOfDot = className.lastIndexOf('.');

        String packageName = lastIndexOfDot > -1 ? className.substring(0, lastIndexOfDot) : "";

        fieldInstrumentations = new FieldInstrumentations(classNode.superName);

        annotationAccess = new DelegatingAnnotationAccess(pool.createAnnotationAccess(classNode.visibleAnnotations),
                pool.createAnnotationAccess(superClassName));

        this.parentInheritanceData = parentInheritanceData;

        inheritanceData = parentInheritanceData.createChild(packageName);

        for (String interfaceName : classNode.interfaces)
        {
            inheritanceData.addInterface(interfaceName);
        }

        methods = new ArrayList<>(classNode.methods.size());

        String invalidConstructorMessage = invalidConstructorMessage();

        for (MethodNode node : classNode.methods)
        {
            if (node.name.equals(CONSTRUCTOR_NAME))
            {
                if (node.desc.equals(NOTHING_TO_VOID))
                {
                    originalConstructor = node;
                    fieldTransformMethods.add(node);
                } else
                {
                    node.instructions.clear();

                    newBuilder(node).throwException(IllegalStateException.class, invalidConstructorMessage);
                }

                continue;
            }

            /*
             * Static methods are not visible to the main API methods, but they must still be transformed,
             * in case they directly access fields. In addition, track their names to avoid collisions.
             */
            if (Modifier.isStatic(node.access))
            {
                if (isInheritableMethod(node))
                {
                    inheritanceData.addMethod(node.name, node.desc, node.access == 0);
                }

                methodNames.add(node.name);

                fieldTransformMethods.add(node);

                continue;
            }

            if (!Modifier.isAbstract(node.access))
            {
                fieldTransformMethods.add(node);
            }

            PlasticMethodImpl pmi = new PlasticMethodImpl(this, node);

            methods.add(pmi);
            description2method.put(pmi.getDescription(), pmi);

            if (isInheritableMethod(node))
            {
                inheritanceData.addMethod(node.name, node.desc, node.access == 0);
            }

            methodNames.add(node.name);
        }

        methodNames.addAll(parentInheritanceData.methodNames());

        Collections.sort(methods);

        fields = new ArrayList<>(classNode.fields.size());

        for (FieldNode node : classNode.fields)
        {
            fieldNames.add(node.name);

            // Ignore static fields.

            if (Modifier.isStatic(node.access))
                continue;

            // When we instrument the field such that it must be private, we'll get an exception.

            fields.add(new PlasticFieldImpl(this, node));
        }

        Collections.sort(fields);

        // TODO: Make the output class's constructor protected, and create a shim class to instantiate it
        // efficiently (without reflection).
        newConstructor = new MethodNode(ACC_PUBLIC, CONSTRUCTOR_NAME, CONSTRUCTOR_DESC, null, null);
        constructorBuilder = newBuilder(newConstructor);

        // Start by calling the super-class no args constructor

        if (parentInheritanceData.isTransformed())
        {
            // If the parent is transformed, our first step is always to invoke its constructor.

            constructorBuilder.loadThis().loadArgument(0).loadArgument(1);
            constructorBuilder.invokeConstructor(superClassName, StaticContext.class.getName(),
                    InstanceContext.class.getName());
        } else
        {
            // Assumes the base class includes a visible constructor that takes no arguments.
            // TODO: Do a proper check for this case and throw a meaningful exception
            // if not present.

            constructorBuilder.loadThis().invokeConstructor(superClassName);
        }

        // During the transformation, we'll be adding code to the constructor to pull values
        // out of the static or instance context and assign them to fields.

        // Later on, we'll add the RETURN opcode
    }

    private String invalidConstructorMessage()
    {
        return String.format("Class %s has been transformed and may not be directly instantiated.", className);
    }

    @Override
    public <T extends Annotation> boolean hasAnnotation(Class<T> annotationType)
    {
        check();

        return annotationAccess.hasAnnotation(annotationType);
    }

    @Override
    public <T extends Annotation> T getAnnotation(Class<T> annotationType)
    {
        check();

        return annotationAccess.getAnnotation(annotationType);
    }

    private static void addMethodAndParameterAnnotationsFromExistingClass(MethodNode methodNode, MethodNode implementationMethodNode)
    {
        // visits the method attributes
        int i, j, n;
        if (implementationMethodNode.annotationDefault != null)
        {
            AnnotationVisitor av = methodNode.visitAnnotationDefault();
            AnnotationNode.accept(av, null, implementationMethodNode.annotationDefault);
            if (av != null)
            {
                av.visitEnd();
            }
        }
        n = implementationMethodNode.visibleAnnotations == null ? 0 : implementationMethodNode.visibleAnnotations.size();
        for (i = 0; i < n; ++i)
        {
            AnnotationNode an = implementationMethodNode.visibleAnnotations.get(i);
            an.accept(methodNode.visitAnnotation(an.desc, true));
        }
        n = implementationMethodNode.invisibleAnnotations == null ? 0 : implementationMethodNode.invisibleAnnotations.size();
        for (i = 0; i < n; ++i)
        {
            AnnotationNode an = implementationMethodNode.invisibleAnnotations.get(i);
            an.accept(methodNode.visitAnnotation(an.desc, false));
        }
        n = implementationMethodNode.visibleParameterAnnotations == null
                ? 0
                : implementationMethodNode.visibleParameterAnnotations.length;
        for (i = 0; i < n; ++i)
        {
            List<?> l = implementationMethodNode.visibleParameterAnnotations[i];
            if (l == null)
            {
                continue;
            }
            for (j = 0; j < l.size(); ++j)
            {
                AnnotationNode an = (AnnotationNode) l.get(j);
                an.accept(methodNode.visitParameterAnnotation(i, an.desc, true));
            }
        }
        n = implementationMethodNode.invisibleParameterAnnotations == null
                ? 0
                : implementationMethodNode.invisibleParameterAnnotations.length;
        for (i = 0; i < n; ++i)
        {
            List<?> l = implementationMethodNode.invisibleParameterAnnotations[i];
            if (l == null)
            {
                continue;
            }
            for (j = 0; j < l.size(); ++j)
            {
                AnnotationNode an = (AnnotationNode) l.get(j);
                an.accept(methodNode.visitParameterAnnotation(i, an.desc, false));
            }
        }

        methodNode.visitEnd();

    }

    private static void removeDuplicatedAnnotations(MethodNode node)
    {

        removeDuplicatedAnnotations(node.visibleAnnotations);
        removeDuplicatedAnnotations(node.invisibleAnnotations);

        if (node.visibleParameterAnnotations != null)
        {
            for (List<AnnotationNode> list : node.visibleParameterAnnotations)
            {
                removeDuplicatedAnnotations(list);
            }
        }

        if (node.invisibleParameterAnnotations != null)
        {
            for (List<AnnotationNode> list : node.invisibleParameterAnnotations)
            {
                removeDuplicatedAnnotations(list);
            }
        }

    }

    private static void removeDuplicatedAnnotations(ClassNode node)
    {
        removeDuplicatedAnnotations(node.visibleAnnotations, true);
        removeDuplicatedAnnotations(node.invisibleAnnotations, true);
    }

    private static void removeDuplicatedAnnotations(List<AnnotationNode> list) {
        removeDuplicatedAnnotations(list, false);
    }

    private static void removeDuplicatedAnnotations(List<AnnotationNode> list, boolean reverse) {

        if (list != null)
        {

            final Set<String> annotations = new HashSet<>();
            final List<AnnotationNode> toBeRemoved = new ArrayList<>();
            final List<AnnotationNode> toBeIterated;

            if (reverse)
            {
                toBeIterated = new ArrayList<>(list);
                Collections.reverse(toBeIterated);
            }
            else {
                toBeIterated = list;
            }

            for (AnnotationNode annotationNode : toBeIterated)
            {
                if (annotations.contains(annotationNode.desc))
                {
                    toBeRemoved.add(annotationNode);
                }
                else
                {
                    annotations.add(annotationNode.desc);
                }
            }

            for (AnnotationNode annotationNode : toBeRemoved)
            {
                list.remove(annotationNode);
            }

        }

    }

    private static String getParametersDesc(MethodNode methodNode) {
        return methodNode.desc.substring(methodNode.desc.indexOf('(') + 1, methodNode.desc.lastIndexOf(')'));
    }

    private static MethodNode findExactMatchMethod(MethodNode methodNode, ClassNode source) {

        MethodNode found = null;

        final String methodDescription = getParametersDesc(methodNode);

        for (MethodNode implementationMethodNode : source.methods)
        {

            final String implementationMethodDescription = getParametersDesc(implementationMethodNode);
            if (methodNode.name.equals(implementationMethodNode.name) &&
                    // We don't want synthetic methods.
                    ((implementationMethodNode.access & Opcodes.ACC_SYNTHETIC) == 0)
                    && (methodDescription.equals(implementationMethodDescription)))
            {
                found = implementationMethodNode;
                break;
            }
        }

        return found;

    }

    private static List<Class> getJavaParameterTypes(MethodNode methodNode) {
        final ClassLoader classLoader = PlasticInternalUtils.class.getClassLoader();
        Type[] parameterTypes = Type.getArgumentTypes(methodNode.desc);
        List<Class> list = new ArrayList<>();
        for (Type type : parameterTypes)
        {
            try
            {
                list.add(PlasticInternalUtils.toClass(classLoader, type.getClassName()));
            }
            catch (ClassNotFoundException e)
            {
                throw new RuntimeException(e); // shouldn't happen anyway
            }
        }
        return list;
    }

    /**
     * Returns the first method which matches the given methodNode.
     * FIXME: this may not find the correct method if the correct one is declared after
     * another in which all parameters are supertypes of the parameters of methodNode.
     * To solve this, we would need to dig way deeper than we have time for this.
     * @param methodNode
     * @param classNode
     * @return
     */
    private static MethodNode findGenericMethod(MethodNode methodNode, ClassNode classNode)
    {

        MethodNode found = null;

        List<Class> parameterTypes = getJavaParameterTypes(methodNode);

        for (MethodNode implementationMethodNode : classNode.methods)
        {

            if (methodNode.name.equals(implementationMethodNode.name))
            {

                final List<Class> implementationParameterTypes = getJavaParameterTypes(implementationMethodNode);

                if (parameterTypes.size() == implementationParameterTypes.size())
                {

                    boolean matches = true;
                    for (int i = 0; i < parameterTypes.size(); i++)
                    {
                        final Class implementationParameterType = implementationParameterTypes.get(i);
                        final Class parameterType = parameterTypes.get(i);
                        if (!parameterType.isAssignableFrom(implementationParameterType)) {
                            matches = false;
                            break;
                        }

                    }

                    if (matches && !isBridge(implementationMethodNode))
                    {
                        found = implementationMethodNode;
                        break;
                    }

                }

            }

        }

        return found;

    }

    private static void addMethodAndParameterAnnotationsFromExistingClass(MethodNode methodNode, ClassNode source)
    {
        if (source != null)
        {

            MethodNode candidate = findExactMatchMethod(methodNode, source);

            final String parametersDesc = getParametersDesc(methodNode);

            // candidate will be null when the method has generic parameters
            if (candidate == null && parametersDesc.trim().length() > 0)
            {
                candidate = findGenericMethod(methodNode, source);
            }

            if (candidate != null)
            {
                addMethodAndParameterAnnotationsFromExistingClass(methodNode, candidate);
            }

        }

    }

    /**
     * Tells whether a given method is a bridge one or not.
     * Notice the flag for bridge method is the same as volatile field. Java 6 doesn't have
     * Modifiers.isBridge(), so we use a workaround.
     */
    private static boolean isBridge(MethodNode methodNode)
    {
        return Modifier.isVolatile(methodNode.access);
    }

    @Override
    public PlasticClass proxyInterface(Class interfaceType, PlasticField field)
    {
        check();

        assert field != null;

        introduceInterface(interfaceType);

        for (Method m : getUniqueMethods(interfaceType))
        {
            final MethodDescription description = new MethodDescription(m);
            if(Modifier.isStatic(description.modifiers))
            {
                continue;
            }
            introduceMethod(description).delegateTo(field);
        }

        return this;
    }

    @Override
    public ClassInstantiator createInstantiator()
    {
        lock();

        addClassAnnotations(implementationClassNode);
        removeDuplicatedAnnotations(classNode);

        createShimIfNeeded();

        interceptFieldAccess();

        rewriteAdvisedMethods();

        completeConstructor();

        transformedClass = pool.realizeTransformedClass(classNode, inheritanceData, staticContext);

        return createInstantiatorFromClass(transformedClass);
    }

    private void addClassAnnotations(ClassNode otherClassNode)
    {
        // Copy annotations from implementation if available.
        // Code adapted from ClassNode.accept(), as we just want to copy
        // the annotations and nothing more.
        if (otherClassNode != null)
        {

            int i, n;
            n = otherClassNode.visibleAnnotations == null ? 0 : otherClassNode.visibleAnnotations.size();
            for (i = 0; i < n; ++i)
            {
                AnnotationNode an = otherClassNode.visibleAnnotations.get(i);
                an.accept(classNode.visitAnnotation(an.desc, true));
            }
            n = otherClassNode.invisibleAnnotations == null ? 0 : otherClassNode.invisibleAnnotations.size();
            for (i = 0; i < n; ++i)
            {
                AnnotationNode an = otherClassNode.invisibleAnnotations.get(i);
                an.accept(classNode.visitAnnotation(an.desc, false));
            }

        }
    }

    private ClassInstantiator createInstantiatorFromClass(Class clazz)
    {
        try
        {
            Constructor ctor = clazz.getConstructor(StaticContext.class, InstanceContext.class);

            return new ClassInstantiatorImpl(clazz, ctor, staticContext);
        } catch (Exception ex)
        {
            throw new RuntimeException(String.format("Unable to create ClassInstantiator for class %s: %s",
                    clazz.getName(), PlasticInternalUtils.toMessage(ex)), ex);
        }
    }

    private void completeConstructor()
    {
        if (originalConstructor != null)
        {
            convertOriginalConstructorToMethod();
        }

        invokeCallbacks();

        constructorBuilder.returnResult();

        classNode.methods.add(newConstructor);
    }

    private void invokeCallbacks()
    {
        for (ConstructorCallback callback : constructorCallbacks)
        {
            invokeCallback(callback);
        }
    }

    private void invokeCallback(ConstructorCallback callback)
    {
        int index = staticContext.store(callback);

        // First, load the callback

        constructorBuilder.loadArgument(0).loadConstant(index).invoke(STATIC_CONTEXT_GET_METHOD).castOrUnbox(ConstructorCallback.class.getName());

        // Load this and the InstanceContext
        constructorBuilder.loadThis().loadArgument(1);

        constructorBuilder.invoke(CONSTRUCTOR_CALLBACK_METHOD);
    }


    /**
     * Convert the original constructor into a private method invoked from the
     * generated constructor.
     */
    private void convertOriginalConstructorToMethod()
    {
        String initializerName = makeUnique(methodNames, "initializeInstance");

        int originalAccess = originalConstructor.access;

        originalConstructor.access = ACC_PRIVATE;
        originalConstructor.name = initializerName;

        stripOutSuperConstructorCall(originalConstructor);

        constructorBuilder.loadThis().invokeVirtual(className, "void", initializerName);

        // And replace it with a constructor that throws an exception

        MethodNode replacementConstructor = new MethodNode(originalAccess, CONSTRUCTOR_NAME, NOTHING_TO_VOID, null,
                null);

        newBuilder(replacementConstructor).throwException(IllegalStateException.class, invalidConstructorMessage());

        classNode.methods.add(replacementConstructor);
    }

    private void stripOutSuperConstructorCall(MethodNode cons)
    {
        InsnList ins = cons.instructions;

        ListIterator li = ins.iterator();

        // Look for the ALOAD 0 (i.e., push this on the stack)
        while (li.hasNext())
        {
            AbstractInsnNode node = (AbstractInsnNode) li.next();

            if (node.getOpcode() == ALOAD)
            {
                VarInsnNode varNode = (VarInsnNode) node;

                assert varNode.var == 0;

                // Remove the ALOAD
                li.remove();
                break;
            }
        }

        // Look for the call to the super-class, an INVOKESPECIAL
        while (li.hasNext())
        {
            AbstractInsnNode node = (AbstractInsnNode) li.next();

            if (node.getOpcode() == INVOKESPECIAL)
            {
                MethodInsnNode mnode = (MethodInsnNode) node;

                assert mnode.owner.equals(classNode.superName);
                assert mnode.name.equals(CONSTRUCTOR_NAME);
                assert mnode.desc.equals(cons.desc);

                li.remove();
                return;
            }
        }

        throw new AssertionError("Could not convert constructor to simple method.");
    }

    @Override
    public <T extends Annotation> List<PlasticField> getFieldsWithAnnotation(Class<T> annotationType)
    {
        check();

        List<PlasticField> result = getAllFields();

        Iterator<PlasticField> iterator = result.iterator();

        while (iterator.hasNext())
        {
            PlasticField plasticField = iterator.next();

            if (!plasticField.hasAnnotation(annotationType))
                iterator.remove();
        }

        return result;
    }

    @Override
    public List<PlasticField> getAllFields()
    {
        check();

        return new ArrayList<>(fields);
    }

    @Override
    public List<PlasticField> getUnclaimedFields()
    {
        check();

        // Initially null, and set back to null by PlasticField.claim().

        if (unclaimedFields == null)
        {
            unclaimedFields = new ArrayList<>(fields.size());

            for (PlasticField f : fields)
            {
                if (!f.isClaimed())
                    unclaimedFields.add(f);
            }
        }

        return unclaimedFields;
    }

    @Override
    public PlasticMethod introducePrivateMethod(String typeName, String suggestedName, String[] argumentTypes,
                                                String[] exceptionTypes)
    {
        check();

        assert PlasticInternalUtils.isNonBlank(typeName);
        assert PlasticInternalUtils.isNonBlank(suggestedName);

        String name = makeUnique(methodNames, suggestedName);

        MethodDescription description = new MethodDescription(Modifier.PRIVATE, typeName, name, argumentTypes, null,
                exceptionTypes);

        return introduceMethod(description);
    }

    @Override
    public PlasticField introduceField(String className, String suggestedName)
    {
        check();

        assert PlasticInternalUtils.isNonBlank(className);
        assert PlasticInternalUtils.isNonBlank(suggestedName);

        String name = makeUnique(fieldNames, suggestedName);

        // No signature and no initial value

        FieldNode fieldNode = new FieldNode(ACC_PRIVATE, name, PlasticInternalUtils.toDescriptor(className), null, null);

        classNode.fields.add(fieldNode);

        fieldNames.add(name);

        PlasticFieldImpl newField = new PlasticFieldImpl(this, fieldNode);

        return newField;
    }

    @Override
    public PlasticField introduceField(Class fieldType, String suggestedName)
    {
        assert fieldType != null;

        return introduceField(nameCache.toTypeName(fieldType), suggestedName);
    }

    String makeUnique(Set<String> values, String input)
    {
        return values.contains(input) ? input + "$" + PlasticUtils.nextUID() : input;
    }

    @Override
    public <T extends Annotation> List<PlasticMethod> getMethodsWithAnnotation(Class<T> annotationType)
    {
        check();

        List<PlasticMethod> result = getMethods();

        result.removeIf(method -> !method.hasAnnotation(annotationType));

        return result;
    }

    @Override
    public List<PlasticMethod> getMethods()
    {
        check();

        return new ArrayList<>(methods);
    }

    @Override
    public PlasticMethod introduceMethod(MethodDescription description)
    {
        check();

        if (Modifier.isAbstract(description.modifiers))
        {
            description = description.withModifiers(description.modifiers & ~ACC_ABSTRACT);
        }

        PlasticMethod result = description2method.get(description);

        if (result == null)
        {
            result = createNewMethod(description);

            description2method.put(description, result);
        }

        methodNames.add(description.methodName);

        // Note that is it not necessary to add the new MethodNode to
        // fieldTransformMethods (the default implementations provided by introduceMethod() do not
        // ever access instance fields) ... unless the caller invokes changeImplementation().

        return result;
    }

    @Override
    public PlasticMethod introduceMethod(MethodDescription description, InstructionBuilderCallback callback)
    {
        check();

        // TODO: optimize this so that a default implementation is not created.

        return introduceMethod(description).changeImplementation(callback);
    }

    @Override
    public PlasticMethod introduceMethod(Method method)
    {
        check();
        return introduceMethod(new MethodDescription(method));
    }

    void addMethod(MethodNode methodNode)
    {
        classNode.methods.add(methodNode);

        methodNames.add(methodNode.name);

        if (isInheritableMethod(methodNode))
        {
            inheritanceData.addMethod(methodNode.name, methodNode.desc, methodNode.access == 0);
        }
    }

    private PlasticMethod createNewMethod(MethodDescription description)
    {
        if (Modifier.isStatic(description.modifiers))
            throw new IllegalArgumentException(String.format(
                    "Unable to introduce method '%s' into class %s: introduced methods may not be static.",
                    description, className));

        String desc = nameCache.toDesc(description);

        String[] exceptions = new String[description.checkedExceptionTypes.length];
        for (int i = 0; i < exceptions.length; i++)
        {
            exceptions[i] = PlasticInternalUtils.toInternalName(description.checkedExceptionTypes[i]);
        }

        MethodNode methodNode = new MethodNode(description.modifiers, description.methodName, desc,
                description.genericSignature, exceptions);
        boolean isOverride = inheritanceData.isImplemented(methodNode.name, desc);

        if (!isOverride)
        {
            addMethodAndParameterAnnotationsFromExistingClass(methodNode, implementationClassNode);
            addMethodAndParameterAnnotationsFromExistingClass(methodNode, interfaceClassNode);
            removeDuplicatedAnnotations(methodNode);
        }

        if (isOverride)
            createOverrideOfBaseClassImpl(description, methodNode);
        else
            createNewMethodImpl(description, methodNode);

        addMethod(methodNode);

        return new PlasticMethodImpl(this, methodNode);
    }

    private boolean isDefaultMethod(Method method)
    {
        return method.getDeclaringClass().isInterface() &&
                (method.getModifiers() & (Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC | Opcodes.ACC_ABSTRACT)) == Opcodes.ACC_PUBLIC;
    }

    private void createNewMethodImpl(MethodDescription methodDescription, MethodNode methodNode)
    {
        newBuilder(methodDescription, methodNode).returnDefaultValue();
    }

    private void createOverrideOfBaseClassImpl(MethodDescription methodDescription, MethodNode methodNode)
    {
        InstructionBuilder builder = newBuilder(methodDescription, methodNode);

        builder.loadThis();
        builder.loadArguments();
        builder.invokeSpecial(superClassName, methodDescription);
        builder.returnResult();
    }

    /**
     * Iterates over all non-introduced methods, including the original constructor. For each
     * method, the bytecode is scanned for field reads and writes. When a match is found against an intercepted field,
     * the operation is replaced with a method invocation. This is invoked only after the {@link PlasticClassHandleShim}
     * for the class has been created, as the shim may create methods that contain references to fields that may be
     * subject to field access interception.
     */
    private void interceptFieldAccess()
    {
        for (MethodNode node : fieldTransformMethods)
        {
            // Intercept field access inside the method, tracking which access methods
            // are actually used by removing them from accessMethods

            interceptFieldAccess(node);
        }
    }

    /**
     * Determines if any fields or methods have provided FieldHandles or MethodHandles; if so
     * a shim class must be created to facilitate read/write access to fields, or invocation of methods.
     */
    private void createShimIfNeeded()
    {
        if (shimFields.isEmpty() && shimMethods.isEmpty())
            return;

        PlasticClassHandleShim shim = createShimInstance();

        installShim(shim);
    }

    public void installShim(PlasticClassHandleShim shim)
    {
        for (PlasticFieldImpl f : shimFields)
        {
            f.installShim(shim);
        }

        for (PlasticMethodImpl m : shimMethods)
        {
            m.installShim(shim);
        }
    }

    public PlasticClassHandleShim createShimInstance()
    {
        String shimClassName = String.format("%s$Shim_%s", classNode.name, PlasticUtils.nextUID());

        ClassNode shimClassNode = new ClassNode();

        shimClassNode.visit(PlasticConstants.DEFAULT_VERSION_OPCODE, ACC_PUBLIC | ACC_FINAL, shimClassName, null, HANDLE_SHIM_BASE_CLASS_INTERNAL_NAME,
                null);

        implementConstructor(shimClassNode);

        if (!shimFields.isEmpty())
        {
            implementShimGet(shimClassNode);
            implementShimSet(shimClassNode);
        }

        if (!shimMethods.isEmpty())
        {
            implementShimInvoke(shimClassNode);
        }

        return instantiateShim(shimClassNode);
    }

    private void implementConstructor(ClassNode shimClassNode)
    {
        MethodNode mn = new MethodNode(ACC_PUBLIC, CONSTRUCTOR_NAME, NOTHING_TO_VOID, null, null);

        InstructionBuilder builder = newBuilder(mn);

        builder.loadThis().invokeConstructor(PlasticClassHandleShim.class).returnResult();

        shimClassNode.methods.add(mn);

    }

    private PlasticClassHandleShim instantiateShim(ClassNode shimClassNode)
    {
        try
        {
            Class shimClass = pool.realize(className, ClassType.SUPPORT, shimClassNode);

            return (PlasticClassHandleShim) shimClass.newInstance();
        } catch (Exception ex)
        {
            throw new RuntimeException(
                    String.format("Unable to instantiate shim class %s for plastic class %s: %s",
                            PlasticInternalUtils.toClassName(shimClassNode.name), className,
                            PlasticInternalUtils.toMessage(ex)), ex);
        }
    }

    private void implementShimGet(ClassNode shimClassNode)
    {
        MethodNode mn = new MethodNode(ACC_PUBLIC, "get", OBJECT_INT_TO_OBJECT, null, null);

        InstructionBuilder builder = newBuilder(mn);

        // Arg 0 is the target instance
        // Arg 1 is the index

        builder.loadArgument(0).checkcast(className);
        builder.loadArgument(1);

        builder.startSwitch(0, nextFieldIndex - 1, new SwitchCallback()
        {
            @Override
            public void doSwitch(SwitchBlock block)
            {
                for (PlasticFieldImpl f : shimFields)
                {
                    f.extendShimGet(block);
                }
            }
        });

        shimClassNode.methods.add(mn);
    }

    private void implementShimSet(ClassNode shimClassNode)
    {
        MethodNode mn = new MethodNode(ACC_PUBLIC, "set", OBJECT_INT_OBJECT_TO_VOID, null, null);

        InstructionBuilder builder = newBuilder(mn);

        // Arg 0 is the target instance
        // Arg 1 is the index
        // Arg 2 is the new value

        builder.loadArgument(0).checkcast(className);
        builder.loadArgument(2);

        builder.loadArgument(1);

        builder.startSwitch(0, nextFieldIndex - 1, new SwitchCallback()
        {
            @Override
            public void doSwitch(SwitchBlock block)
            {
                for (PlasticFieldImpl f : shimFields)
                {
                    f.extendShimSet(block);
                }
            }
        });

        builder.returnResult();

        shimClassNode.methods.add(mn);
    }

    private void implementShimInvoke(ClassNode shimClassNode)
    {
        MethodNode mn = new MethodNode(ACC_PUBLIC, "invoke", OBJECT_INT_OBJECT_ARRAY_TO_METHOD_INVOCATION_RESULT, null,
                null);

        InstructionBuilder builder = newBuilder(mn);

        // Arg 0 is the target instance
        // Arg 1 is the index
        // Arg 2 is the object array of parameters

        builder.loadArgument(0).checkcast(className);

        builder.loadArgument(1);

        builder.startSwitch(0, nextMethodIndex - 1, new SwitchCallback()
        {
            @Override
            public void doSwitch(SwitchBlock block)
            {
                for (PlasticMethodImpl m : shimMethods)
                {
                    m.extendShimInvoke(block);
                }
            }
        });

        shimClassNode.methods.add(mn);
    }

    private void rewriteAdvisedMethods()
    {
        for (PlasticMethodImpl method : advisedMethods)
        {
            method.rewriteMethodForAdvice();
        }
    }

    private void interceptFieldAccess(MethodNode methodNode)
    {
        InsnList insns = methodNode.instructions;

        ListIterator<AbstractInsnNode> it = insns.iterator();

        while (it.hasNext())
        {
            AbstractInsnNode node = it.next();

            int opcode = node.getOpcode();

            if (opcode != GETFIELD && opcode != PUTFIELD)
            {
                continue;
            }

            FieldInsnNode fnode = (FieldInsnNode) node;

            FieldInstrumentation instrumentation = findFieldNodeInstrumentation(fnode, opcode == GETFIELD);

            if (instrumentation == null)
            {
                continue;
            }

            // Replace the field access node with the appropriate method invocation.

            insns.insertBefore(fnode, new MethodInsnNode(INVOKEVIRTUAL, fnode.owner, instrumentation.methodName, instrumentation.methodDescription, false));

            it.remove();
        }
    }

    private FieldInstrumentation findFieldNodeInstrumentation(FieldInsnNode node, boolean forRead)
    {
        // First look in the local fieldInstrumentations, which contains private field instrumentations
        // (as well as non-private ones).

        String searchStart = node.owner;

        if (searchStart.equals(classNode.name))
        {
            FieldInstrumentation result = fieldInstrumentations.get(node.name, forRead);

            if (result != null)
            {
                return result;
            }

            // Slight optimization: start the search in the super-classes' fields, since we've already
            // checked this classes fields.

            searchStart = classNode.superName;
        }

        return pool.getFieldInstrumentation(searchStart, node.name, forRead);
    }

    String getInstanceContextFieldName()
    {
        if (instanceContextFieldName == null)
        {
            instanceContextFieldName = makeUnique(fieldNames, "instanceContext");

            // TODO: We could use a protected field and only initialize
            // it once, in the first base class where it is needed, though that raises the possibilities
            // of name conflicts (a subclass might introduce a field with a conflicting name).

            FieldNode node = new FieldNode(ACC_PRIVATE | ACC_FINAL, instanceContextFieldName, INSTANCE_CONTEXT_DESC,
                    null, null);

            classNode.fields.add(node);

            // Extend the constructor to store the context in a field.

            constructorBuilder.loadThis().loadArgument(1)
                    .putField(className, instanceContextFieldName, InstanceContext.class);
        }

        return instanceContextFieldName;
    }

    /**
     * Creates a new private final field and initializes its value (using the StaticContext).
     */
    String createAndInitializeFieldFromStaticContext(String suggestedFieldName, String fieldType,
                                                     Object injectedFieldValue)
    {
        String name = makeUnique(fieldNames, suggestedFieldName);

        FieldNode field = new FieldNode(ACC_PRIVATE | ACC_FINAL, name, nameCache.toDesc(fieldType), null, null);

        classNode.fields.add(field);

        initializeFieldFromStaticContext(name, fieldType, injectedFieldValue);

        return name;
    }

    /**
     * Initializes a field from the static context. The injected value is added to the static
     * context and the class constructor updated to assign the value from the context (which includes casting and
     * possibly unboxing).
     */
    void initializeFieldFromStaticContext(String fieldName, String fieldType, Object injectedFieldValue)
    {
        int index = staticContext.store(injectedFieldValue);

        // Although it feels nicer to do the loadThis() later and then swap(), that breaks
        // on primitive longs and doubles, so its just easier to do the loadThis() first
        // so its at the right place on the stack for the putField().

        constructorBuilder.loadThis();

        constructorBuilder.loadArgument(0).loadConstant(index);
        constructorBuilder.invoke(STATIC_CONTEXT_GET_METHOD);
        constructorBuilder.castOrUnbox(fieldType);

        constructorBuilder.putField(className, fieldName, fieldType);
    }

    void pushInstanceContextFieldOntoStack(InstructionBuilder builder)
    {
        builder.loadThis().getField(className, getInstanceContextFieldName(), InstanceContext.class);
    }

    @Override
    public PlasticClass getPlasticClass()
    {
        return this;
    }

    @Override
    public Class<?> getTransformedClass()
    {
        if (transformedClass == null)
            throw new IllegalStateException(String.format(
                    "Transformed class %s is not yet available because the transformation is not yet complete.",
                    className));

        return transformedClass;
    }

    private boolean isInheritableMethod(MethodNode node)
    {
        return !Modifier.isPrivate(node.access);
    }

    @Override
    public String getClassName()
    {
        return className;
    }

    InstructionBuilderImpl newBuilder(MethodNode mn)
    {
        return newBuilder(PlasticInternalUtils.toMethodDescription(mn), mn);
    }

    InstructionBuilderImpl newBuilder(MethodDescription description, MethodNode mn)
    {
        return new InstructionBuilderImpl(description, mn, nameCache);
    }

    public Set<PlasticMethod> introduceInterface(Class interfaceType)
    {
        return introduceInterface(interfaceType, null);
    }
    
    private Set<PlasticMethod> introduceInterface(Class interfaceType, PlasticMethod method)
    {
        check();

        assert interfaceType != null;

        if (!interfaceType.isInterface())
            throw new IllegalArgumentException(String.format(
                    "Class %s is not an interface; only interfaces may be introduced.", interfaceType.getName()));

        String interfaceName = nameCache.toInternalName(interfaceType);

        try
        {
            interfaceClassNode = PlasticClassPool.readClassNode(interfaceType.getName(), getClass().getClassLoader());
        } catch (IOException e)
        {
            throw new RuntimeException(e);
        }

        if (!inheritanceData.isInterfaceImplemented(interfaceName))
        {
            classNode.interfaces.add(interfaceName);
            inheritanceData.addInterface(interfaceName);
        }

        addClassAnnotations(interfaceClassNode);

        Set<PlasticMethod> introducedMethods = new HashSet<PlasticMethod>();
        Set<Method> alreadyIntroducedMethods = new HashSet<>();

        Method[] sortedMethods = interfaceType.getMethods();
        Arrays.sort(sortedMethods, METHOD_COMPARATOR);
        for (Method m : sortedMethods)
        {
             MethodDescription description = new MethodDescription(m);

            if (!isMethodImplemented(description) && !Modifier.isStatic(description.modifiers) && !contains(alreadyIntroducedMethods, m))
            {
                PlasticMethod introducedMethod = introduceMethod(m);
                introducedMethods.add(introducedMethod);
                if (method != null) {
                    introducedMethod.delegateTo(method);
                }
                alreadyIntroducedMethods.add(m);
            }
        }

        interfaceClassNode = null;

        return introducedMethods;
    }
    
    @Override
    public PlasticClass proxyInterface(Class interfaceType, PlasticMethod method)
    {
        check();
        assert method != null;

        introduceInterface(interfaceType, method);
        
        return this;
    }

    private boolean contains(Set<Method> alreadyIntroducedMethods, Method m) {
        boolean contains = false;
        for (Method method : alreadyIntroducedMethods) 
        {
            if (METHOD_COMPARATOR.compare(method, m) == 0)
            {
                contains = true;
                break;
            }
        }
        return false;
    }

    private Map<MethodSignature, MethodDescription> createMethodSignatureMap(Class interfaceType) {
        // TAP-2582: preprocessing the method list so we don't add duplicated
        // methods, something that happens when an interface has superinterfaces
        // and they define the same method signature.
        // In addition, we collect all the thrown checked exceptions, just in case.
        Map<MethodSignature, MethodDescription> map = new HashMap<>();
        for (Method m : interfaceType.getMethods())
        {
            final MethodSignature methodSignature = new MethodSignature(m);
            final MethodDescription newMethodDescription = new MethodDescription(m);
            if (!map.containsKey(methodSignature))
            {
                map.put(methodSignature, newMethodDescription);
            }
            else
            {
                if (newMethodDescription.checkedExceptionTypes != null && newMethodDescription.checkedExceptionTypes.length > 0)
                {
                    final MethodDescription methodDescription = map.get(methodSignature);
                        final Set<String> checkedExceptionTypes = new HashSet<>();
                        checkedExceptionTypes.addAll(Arrays.asList(methodDescription.checkedExceptionTypes));
                        checkedExceptionTypes.addAll(Arrays.asList(newMethodDescription.checkedExceptionTypes));
                        map.put(methodSignature, new MethodDescription(
                            methodDescription,
                            checkedExceptionTypes.toArray(new String[checkedExceptionTypes.size()])));
                }
            }
        }
        return map;
    }

    final private static class MethodSignature implements Comparable<MethodSignature> {
        final private Method method;
        final private String name;
        final private Class<?>[] parameterTypes;

        public MethodSignature(Method method) {
            this.method = method;
            this.name = method.getName();
            this.parameterTypes = method.getParameterTypes();
        }

        @Override
        public int hashCode() {
            final int prime = 31;
            int result = 1;
            result = prime * result + Arrays.hashCode(parameterTypes);
            result = prime * result + ((name == null) ? 0 : name.hashCode());
            return result;
        }

        @Override
        public boolean equals(Object obj) {
            if (this == obj) return true;
            if (obj == null) return false;
            if (getClass() != obj.getClass()) return false;

            MethodSignature other = (MethodSignature) obj;
            if (!Arrays.equals(parameterTypes, other.parameterTypes)) return false;

            return name == null ? other.name == null : name.equals(other.name);
        }

        @Override
        public int compareTo(MethodSignature o) {
            return method.getName().compareTo(o.method.getName());
        }
    }

    @Override
    public PlasticClass addToString(final String toStringValue)
    {
        check();

        if (!isMethodImplemented(PlasticUtils.TO_STRING_DESCRIPTION))
        {
            introduceMethod(PlasticUtils.TO_STRING_DESCRIPTION, new InstructionBuilderCallback()
            {
                @Override
                public void doBuild(InstructionBuilder builder)
                {
                    builder.loadConstant(toStringValue).returnResult();
                }
            });
        }

        return this;
    }

    @Override
    public boolean isMethodImplemented(MethodDescription description)
    {
        return inheritanceData.isImplemented(description.methodName, nameCache.toDesc(description));
    }

    @Override
    public boolean isInterfaceImplemented(Class interfaceType)
    {
        assert interfaceType != null;
        assert interfaceType.isInterface();

        String interfaceName = nameCache.toInternalName(interfaceType);

        return inheritanceData.isInterfaceImplemented(interfaceName);
    }

    @Override
    public String getSuperClassName()
    {
        return superClassName;
    }

    @Override
    public PlasticClass onConstruct(ConstructorCallback callback)
    {
        check();

        assert callback != null;

        constructorCallbacks.add(callback);

        return this;
    }

    void redirectFieldWrite(String fieldName, boolean privateField, MethodNode method)
    {
        FieldInstrumentation fi = new FieldInstrumentation(method.name, method.desc);

        fieldInstrumentations.write.put(fieldName, fi);

        if (!(proxy || privateField))
        {
            pool.setFieldWriteInstrumentation(classNode.name, fieldName, fi);
        }
    }

    void redirectFieldRead(String fieldName, boolean privateField, MethodNode method)
    {
        FieldInstrumentation fi = new FieldInstrumentation(method.name, method.desc);

        fieldInstrumentations.read.put(fieldName, fi);

        if (!(proxy || privateField))
        {
            pool.setFieldReadInstrumentation(classNode.name, fieldName, fi);
        }
    }
    
    final private MethodComparator METHOD_COMPARATOR = new MethodComparator();
    
    final private class MethodComparator implements Comparator<Method> 
    {

        @Override
        public int compare(Method o1, Method o2) 
        {
            
            int comparison = o1.getName().compareTo(o2.getName());
            
            if (comparison == 0) 
            {
                comparison = o1.getParameterTypes().length - o2.getParameterTypes().length;
            }
            
            if (comparison == 0) 
            {
                final int count = o1.getParameterTypes().length;
                for (int i = 0; i < count; i++) 
                {
                    Class p1 = o1.getParameterTypes()[i];
                    Class p2 = o1.getParameterTypes()[i];
                    if (!p1.equals(p2)) 
                    {
                        comparison = p1.getName().compareTo(p2.getName());
                        break;
                    }
                }
            }
            return comparison;
        }
    }
    
    private List<Method> getUniqueMethods(Class interfaceType) 
    {
        final List<Method> unique = new ArrayList<>(Arrays.asList(interfaceType.getMethods()));
        Collections.sort(unique, METHOD_COMPARATOR);
        Method last = null;
        Iterator<Method> iterator = unique.iterator();
        while (iterator.hasNext()) 
        {
            Method m = iterator.next();
            if (last != null && METHOD_COMPARATOR.compare(m, last) == 0)
            {
                last = m;
                iterator.remove();
            }
        }
        return unique;
    }

    @Override
    public String toString()
    {
        return String.format("PlasticClassImpl[%s]", className);
    }
}
