/*
 * 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.
 */
package org.apache.el.util;

import java.lang.reflect.Array;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import jakarta.el.ELException;
import jakarta.el.MethodNotFoundException;

import org.apache.el.lang.ELSupport;
import org.apache.el.lang.EvaluationContext;

/**
 * Utilities for Managing Serialization and Reflection.
 */
public class ReflectionUtil {

    /**
     * Names of Java primitive types.
     */
    protected static final String[] PRIMITIVE_NAMES =
            new String[] { "boolean", "byte", "char", "double", "float", "int", "long", "short", "void" };

    /**
     * Class objects for Java primitive types, in the same order as {@link #PRIMITIVE_NAMES}.
     */
    protected static final Class<?>[] PRIMITIVES = new Class[] { boolean.class, byte.class, char.class, double.class,
            float.class, int.class, long.class, short.class, Void.TYPE };

    private ReflectionUtil() {
        super();
    }

    /**
     * Loads a class by name, supporting primitive types and array notation.
     *
     * @param name the class name to load
     *
     * @return the Class object, or {@code null} if the name is empty
     *
     * @throws ClassNotFoundException if the class cannot be found
     */
    public static Class<?> forName(String name) throws ClassNotFoundException {
        if (null == name || name.isEmpty()) {
            return null;
        }
        Class<?> c = forNamePrimitive(name);
        if (c == null) {
            if (name.endsWith("[]")) {
                String nc = name.substring(0, name.length() - 2);
                c = Class.forName(nc, true, Thread.currentThread().getContextClassLoader());
                c = Array.newInstance(c, 0).getClass();
            } else {
                c = Class.forName(name, true, Thread.currentThread().getContextClassLoader());
            }
        }
        return c;
    }

    /**
     * Looks up a primitive class by name.
     *
     * @param name the primitive type name
     *
     * @return the corresponding Class object, or {@code null} if not a primitive
     */
    protected static Class<?> forNamePrimitive(String name) {
        if (name.length() <= 8) {
            int p = Arrays.binarySearch(PRIMITIVE_NAMES, name);
            if (p >= 0) {
                return PRIMITIVES[p];
            }
        }
        return null;
    }

    /**
     * Converts an array of Class names to Class types.
     *
     * @param s The array of class names
     *
     * @return An array of Class instance where the element at index i in the result is an instance of the class with
     *             the name at index i in the input
     *
     * @throws ClassNotFoundException If a class of a given name cannot be found
     */
    public static Class<?>[] toTypeArray(String[] s) throws ClassNotFoundException {
        if (s == null) {
            return null;
        }
        Class<?>[] c = new Class[s.length];
        for (int i = 0; i < s.length; i++) {
            c[i] = forName(s[i]);
        }
        return c;
    }

    /**
     * Converts an array of Class types to Class names.
     *
     * @param c The array of class instances
     *
     * @return An array of Class names where the element at index i in the result is the name of the class instance at
     *             index i in the input
     */
    public static String[] toTypeNameArray(Class<?>[] c) {
        if (c == null) {
            return null;
        }
        String[] s = new String[c.length];
        for (int i = 0; i < c.length; i++) {
            s[i] = c[i].getName();
        }
        return s;
    }

    /**
     * Returns a method based on the criteria.
     *
     * @param ctx         the context in which the expression is being evaluated
     * @param base        the object that owns the method
     * @param property    the name of the method
     * @param paramTypes  the parameter types to use
     * @param paramValues the parameter values
     *
     * @return the method specified
     *
     * @throws MethodNotFoundException If a method cannot be found that matches the given criteria
     */
    /*
     * This class duplicates code in jakarta.el.Util. When making changes keep the code in sync.
     */
    @SuppressWarnings("null")
    public static Method getMethod(EvaluationContext ctx, Object base, Object property, Class<?>[] paramTypes,
            Object[] paramValues) throws MethodNotFoundException {

        if (base == null || property == null) {
            throw new MethodNotFoundException(
                    MessageFactory.get("error.method.notfound", base, property, paramString(paramTypes)));
        }

        String methodName = (property instanceof String) ? (String) property : property.toString();

        int paramCount;
        if (paramTypes == null) {
            paramCount = 0;
        } else {
            paramCount = paramTypes.length;
        }

        Class<?> clazz = base.getClass();

        // Fast path: when no arguments exist, there can only be one matching method and no need for coercion.
        if (paramCount == 0) {
            Method result = null;
            Throwable t = null;
            try {
                Method method = clazz.getMethod(methodName, paramTypes);
                result = getMethod(clazz, base, method);
            } catch (NoSuchMethodException | SecurityException e) {
                // Fall through
                t = e;
            }
            if (result == null) {
                throw new MethodNotFoundException(
                        MessageFactory.get("error.method.notfound", base, property, paramString(paramTypes)), t);
            }
            return result;
        }

        Method[] methods = clazz.getMethods();
        Map<Method,MatchResult> candidates = new HashMap<>();

        for (Method m : methods) {
            if (!m.getName().equals(methodName)) {
                // Method name doesn't match
                continue;
            }

            Class<?>[] mParamTypes = m.getParameterTypes();
            int mParamCount = mParamTypes.length;

            // Check the number of parameters
            // Multiple tests to improve readability
            if (!m.isVarArgs() && paramCount != mParamCount) {
                // Method has wrong number of parameters
                continue;
            }
            if (m.isVarArgs() && paramCount < mParamCount - 1) {
                // Method has wrong number of parameters
                continue;
            }
            if (m.isVarArgs() && paramCount == mParamCount && paramValues != null && paramValues.length > paramCount &&
                    !paramTypes[mParamCount - 1].isArray()) {
                // Method arguments don't match
                continue;
            }
            if (m.isVarArgs() && paramCount > mParamCount && paramValues != null && paramValues.length != paramCount) {
                // Might match a different varargs method
                continue;
            }
            if (!m.isVarArgs() && paramValues != null && paramCount != paramValues.length) {
                // Might match a different varargs method
                continue;
            }

            // Check the parameters match
            int exactMatch = 0;
            int assignableMatch = 0;
            int coercibleMatch = 0;
            int varArgsMatch = 0;
            boolean noMatch = false;
            for (int i = 0; i < mParamCount; i++) {
                // Can't be null
                if (m.isVarArgs() && i == (mParamCount - 1)) {
                    if (i == paramCount || (paramValues != null && paramValues.length == i)) {
                        // Var args defined but nothing is passed as varargs
                        // Use MAX_VALUE so this matches only if nothing else does
                        varArgsMatch = Integer.MAX_VALUE;
                        break;
                    }
                    Class<?> varType = mParamTypes[i].getComponentType();
                    for (int j = i; j < paramCount; j++) {
                        if (isAssignableFrom(paramTypes[j], varType)) {
                            assignableMatch++;
                            varArgsMatch++;
                        } else {
                            if (paramValues == null) {
                                noMatch = true;
                                break;
                            } else {
                                if (isCoercibleFrom(ctx, paramValues[j], varType)) {
                                    coercibleMatch++;
                                    varArgsMatch++;
                                } else {
                                    noMatch = true;
                                    break;
                                }
                            }
                        }
                        // Don't treat a varArgs match as an exact match, it can
                        // lead to a varArgs method matching when the result
                        // should be ambiguous
                    }
                } else {
                    if (mParamTypes[i].equals(paramTypes[i])) {
                        exactMatch++;
                    } else if (paramTypes[i] != null && isAssignableFrom(paramTypes[i], mParamTypes[i])) {
                        assignableMatch++;
                    } else {
                        if (paramValues == null) {
                            noMatch = true;
                            break;
                        } else {
                            if (isCoercibleFrom(ctx, paramValues[i], mParamTypes[i])) {
                                coercibleMatch++;
                            } else {
                                noMatch = true;
                                break;
                            }
                        }
                    }
                }
            }
            if (noMatch) {
                continue;
            }

            // If a method is found where every parameter matches exactly,
            // and no vars args are present, return it
            if (exactMatch == paramCount && varArgsMatch == 0) {
                Method result = getMethod(clazz, base, m);
                if (result == null) {
                    throw new MethodNotFoundException(
                            MessageFactory.get("error.method.notfound", base, property, paramString(paramTypes)));
                }
                return result;
            }

            candidates.put(m, new MatchResult(m.isVarArgs(), exactMatch, assignableMatch, coercibleMatch, varArgsMatch,
                    m.isBridge()));
        }

        // Look for the method that has the highest number of parameters where
        // the type matches exactly
        MatchResult bestMatch = new MatchResult(true, 0, 0, 0, 0, true);
        Method match = null;
        boolean multiple = false;
        for (Map.Entry<Method,MatchResult> entry : candidates.entrySet()) {
            int cmp = entry.getValue().compareTo(bestMatch);
            if (cmp > 0 || match == null) {
                bestMatch = entry.getValue();
                match = entry.getKey();
                multiple = false;
            } else if (cmp == 0) {
                multiple = true;
            }
        }
        if (multiple) {
            if (bestMatch.exactCount() == paramCount - 1) {
                // Only one parameter is not an exact match - try using the
                // super class
                match = resolveAmbiguousMethod(candidates.keySet(), paramTypes);
            } else {
                match = null;
            }

            if (match == null) {
                // If multiple methods have the same matching number of parameters
                // the match is ambiguous so throw an exception
                throw new MethodNotFoundException(
                        MessageFactory.get("error.method.ambiguous", base, property, paramString(paramTypes)));
            }
        }

        // Handle case where no match at all was found
        if (match == null) {
            throw new MethodNotFoundException(
                    MessageFactory.get("error.method.notfound", base, property, paramString(paramTypes)));
        }

        Method result = getMethod(clazz, base, match);
        if (result == null) {
            throw new MethodNotFoundException(
                    MessageFactory.get("error.method.notfound", base, property, paramString(paramTypes)));
        }
        return result;
    }

    /*
     * This class duplicates code in jakarta.el.Util. When making changes keep the code in sync.
     */
    private static Method resolveAmbiguousMethod(Set<Method> candidates, Class<?>[] paramTypes) {
        // Identify which parameter isn't an exact match
        Method m = candidates.iterator().next();

        int nonMatchIndex = 0;
        Class<?> nonMatchClass = null;

        for (int i = 0; i < paramTypes.length; i++) {
            if (m.getParameterTypes()[i] != paramTypes[i]) {
                nonMatchIndex = i;
                nonMatchClass = paramTypes[i];
                break;
            }
        }

        if (nonMatchClass == null) {
            // Null will always be ambiguous
            return null;
        }

        for (Method c : candidates) {
            if (c.getParameterTypes()[nonMatchIndex] == paramTypes[nonMatchIndex]) {
                // Methods have different non-matching parameters
                // Result is ambiguous
                return null;
            }
        }

        // Can't be null
        Class<?> superClass = nonMatchClass.getSuperclass();
        while (superClass != null) {
            for (Method c : candidates) {
                if (c.getParameterTypes()[nonMatchIndex].equals(superClass)) {
                    // Found a match
                    return c;
                }
            }
            superClass = superClass.getSuperclass();
        }

        // Treat instances of Number as a special case
        Method match = null;
        if (Number.class.isAssignableFrom(nonMatchClass)) {
            for (Method c : candidates) {
                Class<?> candidateType = c.getParameterTypes()[nonMatchIndex];
                if (Number.class.isAssignableFrom(candidateType) || candidateType.isPrimitive()) {
                    if (match == null) {
                        match = c;
                    } else {
                        // Match still ambiguous
                        match = null;
                        break;
                    }
                }
            }
        }

        return match;
    }


    /*
     * This class duplicates code in jakarta.el.Util. When making changes keep the code in sync.
     */
    private static boolean isAssignableFrom(Class<?> src, Class<?> target) {
        // src will always be an object
        // Short-cut. null is always assignable to an object and in EL null
        // can always be coerced to a valid value for a primitive
        if (src == null) {
            return true;
        }

        Class<?> targetClass;
        if (target.isPrimitive()) {
            if (target == Boolean.TYPE) {
                targetClass = Boolean.class;
            } else if (target == Character.TYPE) {
                targetClass = Character.class;
            } else if (target == Byte.TYPE) {
                targetClass = Byte.class;
            } else if (target == Short.TYPE) {
                targetClass = Short.class;
            } else if (target == Integer.TYPE) {
                targetClass = Integer.class;
            } else if (target == Long.TYPE) {
                targetClass = Long.class;
            } else if (target == Float.TYPE) {
                targetClass = Float.class;
            } else {
                targetClass = Double.class;
            }
        } else {
            targetClass = target;
        }
        return targetClass.isAssignableFrom(src);
    }


    /*
     * This class duplicates code in jakarta.el.Util. When making changes keep the code in sync.
     */
    private static boolean isCoercibleFrom(EvaluationContext ctx, Object src, Class<?> target) {
        // TODO: This isn't pretty but it works. Significant refactoring would be required to avoid the exception.
        try {
            ELSupport.coerceToType(ctx, src, target);
        } catch (ELException e) {
            return false;
        }
        return true;
    }


    /*
     * This class duplicates code in jakarta.el.Util. When making changes keep the code in sync.
     */
    private static Method getMethod(Class<?> type, Object base, Method m) {
        if (m == null || (Modifier.isPublic(type.getModifiers()) &&
                (Modifier.isStatic(m.getModifiers()) && m.canAccess(null) || m.canAccess(base)))) {
            return m;
        }
        Class<?>[] interfaces = type.getInterfaces();
        Method mp;
        for (Class<?> iface : interfaces) {
            try {
                mp = iface.getMethod(m.getName(), m.getParameterTypes());
                mp = getMethod(mp.getDeclaringClass(), base, mp);
                if (mp != null) {
                    return mp;
                }
            } catch (NoSuchMethodException e) {
                // Ignore
            }
        }
        Class<?> sup = type.getSuperclass();
        if (sup != null) {
            try {
                mp = sup.getMethod(m.getName(), m.getParameterTypes());
                mp = getMethod(mp.getDeclaringClass(), base, mp);
                if (mp != null) {
                    return mp;
                }
            } catch (NoSuchMethodException e) {
                // Ignore
            }
        }
        return null;
    }


    private static String paramString(Class<?>[] types) {
        if (types != null) {
            StringBuilder sb = new StringBuilder();
            for (Class<?> type : types) {
                if (type == null) {
                    sb.append("null, ");
                } else {
                    sb.append(type.getName()).append(", ");
                }
            }
            if (sb.length() > 2) {
                sb.setLength(sb.length() - 2);
            }
            return sb.toString();
        }
        return null;
    }


    /*
     * This class duplicates code in jakarta.el.Util. When making changes keep the code in sync.
     */
    private record MatchResult(boolean varArgs, int exactCount, int assignableCount, int coercibleCount,
            int varArgsCount, boolean bridge) implements Comparable<MatchResult> {

        @Override
        public int compareTo(MatchResult o) {
            // Non-varArgs always beats varArgs
            int cmp = Boolean.compare(o.varArgs(), this.varArgs());
            if (cmp == 0) {
                cmp = Integer.compare(this.exactCount(), o.exactCount());
                if (cmp == 0) {
                    cmp = Integer.compare(this.assignableCount(), o.assignableCount());
                    if (cmp == 0) {
                        cmp = Integer.compare(this.coercibleCount(), o.coercibleCount());
                        if (cmp == 0) {
                            // Fewer var args matches are better
                            cmp = Integer.compare(o.varArgsCount(), this.varArgsCount());
                            if (cmp == 0) {
                                // The nature of bridge methods is such that it actually
                                // doesn't matter which one we pick as long as we pick
                                // one. That said, pick the 'right' one (the non-bridge
                                // one) anyway.
                                cmp = Boolean.compare(o.bridge(), this.bridge());
                            }
                        }
                    }
                }
            }
            return cmp;
        }

        @Override
        public boolean equals(Object o) {
            return o == this || (null != o && this.getClass().equals(o.getClass()) &&
                    ((MatchResult) o).exactCount() == this.exactCount() &&
                    ((MatchResult) o).assignableCount() == this.assignableCount() &&
                    ((MatchResult) o).coercibleCount() == this.coercibleCount() &&
                    ((MatchResult) o).varArgsCount() == this.varArgsCount() &&
                    ((MatchResult) o).varArgs() == this.varArgs() && ((MatchResult) o).bridge() == this.bridge());
        }

        @Override
        public int hashCode() {
            final int prime = 31;
            int result = 1;
            result = prime * result + assignableCount();
            result = prime * result + (bridge() ? 1231 : 1237);
            result = prime * result + coercibleCount();
            result = prime * result + exactCount();
            result = prime * result + (varArgs() ? 1231 : 1237);
            result = prime * result + varArgsCount();
            return result;
        }
    }
}
