/*
 * Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0,
 * or the Eclipse Distribution License v. 1.0 which is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
 */

// Contributors:
//     Oracle - initial API and implementation from Oracle TopLink
//     bdoughan - Mar 18/2009 - 2.0 - Dynamically generated impl classes now
//                                    implement correct interface.
package org.eclipse.persistence.sdo.helper;

import java.io.ObjectStreamException;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.List;

import org.eclipse.persistence.sdo.SDOConstants;
import org.eclipse.persistence.sdo.SDODataObject;
import org.eclipse.persistence.sdo.SDOProperty;
import org.eclipse.persistence.sdo.SDOType;
import org.eclipse.persistence.sdo.helper.extension.SDOUtil;
import org.eclipse.persistence.internal.libraries.asm.ClassWriter;
import org.eclipse.persistence.internal.libraries.asm.MethodVisitor;
import org.eclipse.persistence.internal.libraries.asm.Opcodes;
import org.eclipse.persistence.internal.libraries.asm.Type;
import org.eclipse.persistence.internal.security.PrivilegedAccessHelper;

import commonj.sdo.helper.HelperContext;
import org.eclipse.persistence.internal.libraries.asm.EclipseLinkASMClassWriter;

/*
 * Dynamically generate the implementation class for the SDO type.  If the type has an instance
 * (interface) class then the dynamically generated impl class must fully implement it.  Additionally
 * a constructor and a writeReplace() method are added.
 */
public class DynamicClassWriter {
    private static final String START_PROPERTY_INDEX = "START_PROPERTY_INDEX";
    private static final String END_PROPERTY_INDEX = "END_PROPERTY_INDEX";
    private static final String GET = "get";
    private static final String SET = "set";
    private static final String LIST = "List";
    private static final String WRITE_REPLACE = "writeReplace";

    private Class parentClass;
    private String typeImplClassDescriptor;
    private SDOType type;
    private Integer startPropertyIndex;

    // hold the context containing all helpers so that we can preserve
    // inter-helper relationships
    private HelperContext aHelperContext;

    public DynamicClassWriter(String className, SDOType type, HelperContext aContext) {
        this.aHelperContext = aContext;
        this.parentClass = SDODataObject.class;
        this.typeImplClassDescriptor = className.replace('.', '/');
        this.type = type;
        initializeParentClass();

        if (type.isSubType()) {
            try {
                Field parentEndPropertyIndexField = PrivilegedAccessHelper.getField(parentClass, END_PROPERTY_INDEX, true);
                Integer parentEndPropertyIndex = PrivilegedAccessHelper.getValueFromField(parentEndPropertyIndexField, parentClass);
                startPropertyIndex = parentEndPropertyIndex + 1;
            } catch (NoSuchFieldException e) {
                startPropertyIndex = 0;
            } catch (IllegalAccessException e) {
                startPropertyIndex = 0;
            }
        } else {
            startPropertyIndex = 0;
        }
    }

    private void initializeParentClass() {
        if (type.isSubType()) {
            SDOType parentSDOType = (SDOType) type.getBaseTypes().get(0);
            String parentClassName = parentSDOType.getInstanceClassName() + SDOConstants.SDO_IMPL_NAME;
            try {
                parentClass = ((SDOXMLHelper) aHelperContext.getXMLHelper()).getLoader().loadClass(parentClassName, parentSDOType);
            } catch (Exception e) {
                parentClass = null;
            }
            if (parentClass == null) {
                parentClass = SDODataObject.class;
            }
        } else {
            parentClass = SDODataObject.class;
        }
    }

    public Class getParentClass() {
        return this.parentClass;
    }

    /**
     * This is where the byte codes for the generic subclass are defined and the
     * class is created dynamically from them.
     */
    public byte[] createClass() {
        EclipseLinkASMClassWriter cw = new EclipseLinkASMClassWriter();

        if (null == type.getInstanceClass()) {
            cw.visit(Opcodes.ACC_PUBLIC + Opcodes.ACC_SUPER, typeImplClassDescriptor, null, Type.getType(parentClass).getInternalName(), null);
        } else {
            String[] interfaces = new String[1];
            interfaces[0] = type.getInstanceClassName().replace('.', '/');
            cw.visit(Opcodes.ACC_PUBLIC + Opcodes.ACC_SUPER, typeImplClassDescriptor, null, Type.getType(parentClass).getInternalName(), interfaces);
            addPropertyIndices(cw);
            for (Object object : type.getDeclaredProperties()) {
                SDOProperty sdoProperty = (SDOProperty) object;
                addPropertyGetMethod(cw, sdoProperty);
                addPropertySetMethod(cw, sdoProperty);
            }
        }

        addConstructors(cw);
        addWriteReplace(cw);
        cw.visitEnd();

        return cw.toByteArray();
    }

    private void addPropertyIndices(ClassWriter cw) {
        cw.visitField(Opcodes.ACC_PUBLIC + Opcodes.ACC_FINAL + Opcodes.ACC_STATIC, START_PROPERTY_INDEX, "I", null, startPropertyIndex).visitEnd();
        int declaredPropsSize = type.getDeclaredProperties().size();

        Integer endPropertyIndex;
        if (declaredPropsSize > 0) {
            endPropertyIndex = startPropertyIndex + declaredPropsSize - 2;
        } else {
            endPropertyIndex = startPropertyIndex - 1;
        }
        cw.visitField(Opcodes.ACC_PUBLIC + Opcodes.ACC_FINAL + Opcodes.ACC_STATIC, END_PROPERTY_INDEX, "I", null, endPropertyIndex).visitEnd();
    }

    private void addConstructors(ClassWriter cw) {
        MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "<init>", Type.getMethodDescriptor(Type.VOID_TYPE, new Type[0]), null, new String[] { Type.getInternalName(Serializable.class) });
        mv.visitVarInsn(Opcodes.ALOAD, 0);
        mv.visitMethodInsn(Opcodes.INVOKESPECIAL, Type.getType(parentClass).getInternalName(), "<init>", Type.getMethodDescriptor(Type.VOID_TYPE, new Type[0]), false);
        mv.visitInsn(Opcodes.RETURN);
        mv.visitMaxs(1, 1);
        mv.visitEnd();
    }

    private void addPropertyGetMethod(ClassWriter cw, SDOProperty property) {
        String returnType = SDOUtil.getJavaTypeForProperty(property);
        String outerGetMethodName = SDOUtil.getMethodName(property.getName(), returnType);

        if (property.getType() == SDOConstants.SDO_BOOLEAN || property.getType() == SDOConstants.SDO_BOOLEANOBJECT) {
            String booleanGetterName = SDOUtil.getBooleanGetMethodName(property.getName(), returnType);
            addPropertyGetMethodInternal(cw, property, booleanGetterName, returnType);
        }
        addPropertyGetMethodInternal(cw, property, outerGetMethodName, returnType);
    }

    private void addPropertyGetMethodInternal(ClassWriter cw, SDOProperty property, String outerGetMethodName, String returnType) {
        String propertyInstanceClassDescriptor;
        if (property.isMany()) {
            propertyInstanceClassDescriptor = Type.getDescriptor(List.class);
        } else if (property.getType().isDataType()) {
            propertyInstanceClassDescriptor = Type.getDescriptor(property.getType().getInstanceClass());
        } else {
            propertyInstanceClassDescriptor = "L" + returnType.replace('.', '/') + ";";
        }
        MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, outerGetMethodName, "()" + propertyInstanceClassDescriptor, null, null);

        mv.visitVarInsn(Opcodes.ALOAD, 0);
        mv.visitIntInsn(Opcodes.BIPUSH, startPropertyIndex + property.getIndexInType());

        String builtIn = SDOUtil.getBuiltInType(returnType);
        if (null != builtIn) {
            if (property.getType().isDataType() && !builtIn.equals(LIST)) {
                mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, typeImplClassDescriptor, GET + builtIn, "(I)" + propertyInstanceClassDescriptor, false);
                int iReturnOpcode = Type.getType(property.getType().getInstanceClass()).getOpcode(Opcodes.IRETURN);
                mv.visitInsn(iReturnOpcode);
            } else {
                mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, typeImplClassDescriptor, GET, "(I)Ljava/lang/Object;", false);
                mv.visitInsn(Opcodes.ARETURN);
            }
        } else {
            mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, typeImplClassDescriptor, GET, "(I)Ljava/lang/Object;", false);
            mv.visitInsn(Opcodes.ARETURN);
        }
        mv.visitMaxs(2, 1);
        mv.visitEnd();
    }

    private void addPropertySetMethod(ClassWriter cw, SDOProperty property) {
        String returnType = SDOUtil.getJavaTypeForProperty(property);
        String outerSetMethodName = SDOUtil.setMethodName(property.getName());

        String propertyInstanceClassDescriptor;

        if (property.isMany()) {
            propertyInstanceClassDescriptor = Type.getDescriptor(List.class);
        } else if (property.getType().isDataType()) {
            propertyInstanceClassDescriptor = Type.getDescriptor(property.getType().getInstanceClass());
        } else {
            propertyInstanceClassDescriptor = "L" + returnType.replace('.', '/') + ";";
        }
        MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, outerSetMethodName, "(" + propertyInstanceClassDescriptor + ")V", null, null);

        mv.visitVarInsn(Opcodes.ALOAD, 0);
        mv.visitIntInsn(Opcodes.BIPUSH, startPropertyIndex + property.getIndexInType());

        String builtIn = SDOUtil.getBuiltInType(returnType);
        int iLoadOpcode = Opcodes.ALOAD;
        if (null != builtIn) {
            if (property.getType().isDataType() && !builtIn.equals(LIST)) {
                iLoadOpcode = Type.getType(property.getType().getInstanceClass()).getOpcode(Opcodes.ILOAD);
                mv.visitVarInsn(iLoadOpcode, 1);
                mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, typeImplClassDescriptor, SET + builtIn, "(I" + propertyInstanceClassDescriptor + ")V", false);
            } else {
                mv.visitVarInsn(iLoadOpcode, 1);
                mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, typeImplClassDescriptor, SET, "(ILjava/lang/Object;)V", false);
            }
        } else {
            mv.visitVarInsn(iLoadOpcode, 1);
            mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, typeImplClassDescriptor, SET, "(ILjava/lang/Object;)V", false);
        }

        mv.visitInsn(Opcodes.RETURN);
        if (iLoadOpcode == Opcodes.DLOAD || iLoadOpcode == Opcodes.LLOAD) {
            mv.visitMaxs(4, 3);
        } else {
            mv.visitMaxs(3, 2);
        }
        mv.visitEnd();
    }

    private void addWriteReplace(ClassWriter cw) {
        Method method;
        try {
            method = parentClass.getDeclaredMethod(WRITE_REPLACE, new Class[0]);
        } catch (NoSuchMethodException e) {
            return;
        }

        MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PROTECTED, method.getName(), Type.getMethodDescriptor(method), null, new String[] { Type.getInternalName(ObjectStreamException.class) });

        mv.visitVarInsn(Opcodes.ALOAD, 0);
        mv.visitMethodInsn(Opcodes.INVOKESPECIAL, Type.getInternalName(parentClass), method.getName(), Type.getMethodDescriptor(method), false);
        mv.visitInsn(Opcodes.ARETURN);
        mv.visitMaxs(1, 1);
        mv.visitEnd();
    }

}
