/*
 * Copyright 2015 Michael Rozumyanskiy
 *
 * 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 io.michaelrocks.lightsaber.processor.commons;

import io.michaelrocks.lightsaber.processor.descriptors.FieldDescriptor;
import io.michaelrocks.lightsaber.processor.descriptors.MethodDescriptor;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Type;

import static org.objectweb.asm.Opcodes.*;

public class GeneratorAdapter extends org.objectweb.asm.commons.GeneratorAdapter {
    public GeneratorAdapter(final MethodVisitor methodVisitor, final int access, final String name, final String desc) {
        super(ASM5, methodVisitor, access, name, desc);
    }

    public GeneratorAdapter(final MethodVisitor methodVisitor, final int access, final MethodDescriptor method) {
        this(methodVisitor, access, method.getName(), method.getDescriptor());
    }

    public GeneratorAdapter(final ClassVisitor classVisitor, final int access, final MethodDescriptor method,
            final String signature, final Type[] exceptions) {
        this(visitMethod(classVisitor, access, method, signature, exceptions), access, method);
    }

    private static MethodVisitor visitMethod(final ClassVisitor classVisitor, final int access,
            final MethodDescriptor method, final String signature, final Type[] exceptions) {
        return classVisitor.visitMethod(access, method.getName(), method.getDescriptor(), signature,
                getInternalNames(exceptions));
    }

    private static String[] getInternalNames(final Type[] types) {
        if (types == null) {
            return null;
        }
        final String[] names = new String[types.length];
        for (int i = 0; i < names.length; ++i) {
            names[i] = types[i].getInternalName();
        }
        return names;
    }

    public void newArray(final Type type, final int size) {
        push(size);
        super.newArray(type);
    }

    public void invokeVirtual(final Type owner, final MethodDescriptor method) {
        invoke(INVOKEVIRTUAL, owner, method, false);
    }

    public void invokeConstructor(final Type type, final MethodDescriptor method) {
        invoke(INVOKESPECIAL, type, method, false);
    }

    public void invokeStatic(final Type owner, final MethodDescriptor method) {
        invoke(INVOKESTATIC, owner, method, false);
    }

    public void invokeInterface(final Type owner, final MethodDescriptor method) {
        invoke(INVOKEINTERFACE, owner, method, true);
    }

    private void invoke(final int opcode, final Type type, final MethodDescriptor method,
            final boolean ownerIsInterface) {
        final String owner = type.getSort() == Type.ARRAY ? type.getDescriptor() : type.getInternalName();
        visitMethodInsn(opcode, owner, method.getName(), method.getDescriptor(), ownerIsInterface);
    }

    public void getField(final Type owner, final FieldDescriptor field) {
        getField(owner, field.getName(), field.getRawType());
    }

    public void putField(final Type owner, final FieldDescriptor field) {
        putField(owner, field.getName(), field.getRawType());
    }

    public void getStatic(final Type owner, final FieldDescriptor field) {
        getStatic(owner, field.getName(), field.getRawType());
    }

    public void putStatic(final Type owner, final FieldDescriptor field) {
        putStatic(owner, field.getName(), field.getRawType());
    }

    public void pushNull() {
        visitInsn(ACONST_NULL);
    }
}

Introduce a helper class for code generation