/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/*
 * Copyright (C) 2012 The Android Open Source Project
 *
 * 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 java.lang.reflect;

import com.android.dex.Dex;
import java.lang.annotation.Annotation;
import libcore.reflect.AnnotationAccess;
import libcore.util.EmptyArray;

/**
 * This class represents methods and constructors.
 * @hide
 */
public final class ArtMethod {
    /* A note on the field order here, it reflects the same field order as laid out by ART. */

    /** Method's declaring class */
    private Class<?> declaringClass;

    /** Short-cut to declaringClass.dexCache.resolvedMethods */
    private ArtMethod[] dexCacheResolvedMethods;

    /** Short-cut to declaringClass.dexCache.resolvedTypes */
    /* package */ Class<?>[] dexCacheResolvedTypes;

    /** Bits encoding access (e.g. public, private) as well as other runtime specific flags */
    private int accessFlags;

    /* Dex file fields. The defining dex file is available via declaringClass.dexCache */

    /** The offset of the code item associated with this method within its defining dex file */
    private int dexCodeItemOffset;

    /** The method index of this method within its defining dex file */
    private int dexMethodIndex;

    /* End of dex file fields. */

    /**
     * Entry within a dispatch table for this method. For static/direct methods the index is
     * into the declaringClass.directMethods, for virtual methods the vtable and for
     * interface methods the ifTable.
     */
    private int methodIndex;

    /** Only created by ART directly. */
    private ArtMethod() {}

    Class getDeclaringClass() {
        return declaringClass;
    }

    public int getAccessFlags() {
        return accessFlags;
    }

    int getDexMethodIndex() {
        return dexMethodIndex;
    }

    public static String getMethodName(ArtMethod artMethod) {
        artMethod = artMethod.findOverriddenMethodIfProxy();
        Dex dex = artMethod.getDeclaringClass().getDex();
        int nameIndex = dex.nameIndexFromMethodIndex(artMethod.getDexMethodIndex());
        // Note, in the case of a Proxy the dex cache strings are equal.
        return artMethod.getDexCacheString(dex, nameIndex);
    }

    /**
     * Returns true if the given parameters match those of the method in the given order.
     *
     * @hide
     */
    public static boolean equalConstructorParameters(ArtMethod artMethod, Class<?>[] params) {
        Dex dex = artMethod.getDeclaringClass().getDex();
        short[] types = dex.parameterTypeIndicesFromMethodIndex(artMethod.getDexMethodIndex());
        if (types.length != params.length) {
            return false;
        }
        for (int i = 0; i < types.length; i++) {
            if (artMethod.getDexCacheType(dex, types[i]) != params[i]) {
                return false;
            }
        }
        return true;
    }

    /**
     * Returns true if the given parameters match those of this method in the given order.
     *
     * @hide
     */
    public static boolean equalMethodParameters(ArtMethod artMethod, Class<?>[] params) {
        return equalConstructorParameters(artMethod.findOverriddenMethodIfProxy(), params);
    }

    Class<?>[] getParameterTypes() {
        Dex dex = getDeclaringClass().getDex();
        short[] types = dex.parameterTypeIndicesFromMethodIndex(dexMethodIndex);
        if (types.length == 0) {
            return EmptyArray.CLASS;
        }
        Class<?>[] parametersArray = new Class[types.length];
        for (int i = 0; i < types.length; i++) {
            // Note, in the case of a Proxy the dex cache types are equal.
            parametersArray[i] = getDexCacheType(dex, types[i]);
        }
        return parametersArray;
    }

    Class<?> getReturnType() {
        Dex dex = declaringClass.getDex();
        int returnTypeIndex = dex.returnTypeIndexFromMethodIndex(dexMethodIndex);
        // Note, in the case of a Proxy the dex cache types are equal.
        return getDexCacheType(dex, returnTypeIndex);
    }

    /**
     * Performs a comparison of the parameters to this method with the given parameters.
     *
     * @hide
     */
    int compareParameters(Class<?>[] params) {
        Dex dex = getDeclaringClass().getDex();
        short[] types = dex.parameterTypeIndicesFromMethodIndex(dexMethodIndex);
        int length = Math.min(types.length, params.length);
        for (int i = 0; i < length; i++) {
            Class<?> aType = getDexCacheType(dex, types[i]);
            Class<?> bType = params[i];
            if (aType != bType) {
                int comparison = aType.getName().compareTo(bType.getName());
                if (comparison != 0) {
                    return comparison;
                }
            }
        }
        return types.length - params.length;
    }

    Annotation[][] getParameterAnnotations() {
        return AnnotationAccess.getParameterAnnotations(declaringClass, dexMethodIndex);
    }

    /**
     * Returns a string from the dex cache, computing the string from the dex file if necessary.
     * Note this method replicates {@link java.lang.Class#getDexCacheString(Dex, int)}, but in
     * Method we can avoid one indirection.
     */
    private String getDexCacheString(Dex dex, int dexStringIndex) {
        return declaringClass.getDexCacheString(dex, dexStringIndex);
    }

    /**
     * Returns a resolved type from the dex cache, computing the string from the dex file if
     * necessary. Note this method delegates to {@link java.lang.Class#getDexCacheType(Dex, int)},
     * but in Method we can avoid one indirection.
     */
    private Class<?> getDexCacheType(Dex dex, int dexTypeIndex) {
        Class<?> resolvedType = dexCacheResolvedTypes[dexTypeIndex];
        if (resolvedType == null) {
            resolvedType = declaringClass.getDexCacheType(dex, dexTypeIndex);
        }
        return resolvedType;
    }

    /**
     * Returns the {@code ArtMethod} that this method overrides for
     * proxy methods, otherwise returns this method. Used to determine
     * the interface method overridden by a proxy method (as the proxy
     * method doesn't directly support operations such as {@link
     * Method#getName}).
     */
    ArtMethod findOverriddenMethodIfProxy() {
        if (declaringClass.isProxy()) {
            // Proxy method's declaring class' dex cache refers to that of Proxy. The local cache in
            // Method refers to the original interface's dex cache and is ensured to be resolved by
            // proxy generation.
            return dexCacheResolvedMethods[dexMethodIndex];
        }
        return this;
    }
}
