// 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) && !isDefaultMethod(m) && !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);
    }
}
