/*
 * 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.commons.jexl3.internal.introspection;

import org.apache.commons.jexl3.introspection.JexlPermissions;
import org.apache.commons.logging.Log;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

/**
 * A cache of introspection information for a specific class instance.
 * Keys objects by an aggregation of the method name and the classes
 * that make up the parameters.
 * <p>
 * Originally taken from the Velocity tree so we can be self-sufficient.
 * </p>
 *
 * @see MethodKey
 * @since 1.0
 */
final class ClassMap {
    /**
     * A method that returns itself used as a marker for cache miss,
     * allows the underlying cache map to be strongly typed.
     *
     * @return itself as a method
     */
    public static Method cacheMiss() {
        try {
            return ClassMap.class.getMethod("cacheMiss");
        } catch (final Exception xio) {
            // this really can't make an error...
            return null;
        }
    }

    /**
     * The cache miss marker method.
     */
    static final Method CACHE_MISS = cacheMiss();
    /**
     * This is the cache to store and look up the method information.
     * <p>
     * It stores the association between:
     * - a key made of a method name and an array of argument types.
     * - a method.
     * </p>
     * <p>
     * Since the invocation of the associated method is dynamic, there is no need (nor way) to differentiate between
     * foo(int,int) and foo(Integer,Integer) since in practice only the latter form will be used through a call.
     * This of course, applies to all 8 primitive types.
     * </p>
     * Uses ConcurrentMap since 3.0, marginally faster than 2.1 under contention.
     */
    private final Map<MethodKey, Method> byKey ;
    /**
     * Keep track of all methods with the same name; this is not modified after creation.
     */
    private final Map<String, Method[]> byName;
    /**
     * Cache of fields.
     */
    private final Map<String, Field> fieldCache;

    /**
     * Singleton for permissions non-allowed classes.
     */
    private static final ClassMap EMPTY = new ClassMap();

    /**
     * @return the empty classmap instance
     */
    static ClassMap empty() {
        return EMPTY;
    }

    /**
     * Empty map.
     */
    private ClassMap() {
        this.byKey = Collections.unmodifiableMap(new AbstractMap<MethodKey, Method>() {
            @Override
            public String toString() {
                return "emptyClassMap{}";
            }
            @Override
            public Set<Entry<MethodKey, Method>> entrySet() {
                return Collections.emptySet();
            }
            @Override public Method get(final Object name) {
                return CACHE_MISS;
            }
        });
        this.byName = Collections.emptyMap();
        this.fieldCache = Collections.emptyMap();
    }

    /**
     * Standard constructor.
     *
     * @param aClass      the class to deconstruct.
     * @param permissions the permissions to apply during introspection
     * @param log         the logger.
     */
    @SuppressWarnings("LeakingThisInConstructor")
    ClassMap(final Class<?> aClass, final JexlPermissions permissions, final Log log) {
        this.byKey = new ConcurrentHashMap<>();
        this.byName = new HashMap<>();
        // eagerly cache methods
        create(this, permissions, aClass, log);
        // eagerly cache public fields
        final Field[] fields = aClass.getFields();
        if (fields.length > 0) {
            final Map<String, Field> cache = new HashMap<>();
            for (final Field field : fields) {
                if (permissions.allow(field)) {
                    cache.put(field.getName(), field);
                }
            }
            fieldCache = cache;
        } else {
            fieldCache = Collections.emptyMap();
        }
    }

    /**
     * Find a Field using its name.
     *
     * @param fname the field name
     * @return A Field object representing the field to invoke or null.
     */
    Field getField(final String fname) {
        return fieldCache.get(fname);
    }

    /**
     * Gets the field names cached by this map.
     *
     * @return the array of field names
     */
    String[] getFieldNames() {
        return fieldCache.keySet().toArray(new String[0]);
    }

    /**
     * Gets the methods names cached by this map.
     *
     * @return the array of method names
     */
    String[] getMethodNames() {
        return byName.keySet().toArray(new String[0]);
    }

    /**
     * Gets all the methods with a given name from this map.
     *
     * @param methodName the seeked methods name
     * @return the array of methods (null or non-empty)
     */
    Method[] getMethods(final String methodName) {
        final Method[] lm = byName.get(methodName);
        if (lm != null && lm.length > 0) {
            return lm.clone();
        }
        return null;
    }

    /**
     * Find a Method using the method name and parameter objects.
     * <p>
     * Look in the methodMap for an entry. If found,
     * it'll either be a CACHE_MISS, in which case we
     * simply give up, or it'll be a Method, in which
     * case, we return it.
     * </p>
     * <p>
     * If nothing is found, then we must actually go
     * and introspect the method from the MethodMap.
     * </p>
     *
     * @param methodKey the method key
     * @return A Method object representing the method to invoke or null.
     * @throws MethodKey.AmbiguousException When more than one method is a match for the parameters.
     */
    Method getMethod(final MethodKey methodKey) throws MethodKey.AmbiguousException {
        // Look up by key
        Method cacheEntry = byKey.get(methodKey);
        // We looked this up before and failed.
        if (cacheEntry == CACHE_MISS) {
            return null;
        }
        if (cacheEntry == null) {
            try {
                // That one is expensive...
                final Method[] methodList = byName.get(methodKey.getMethod());
                if (methodList != null) {
                    cacheEntry = methodKey.getMostSpecificMethod(methodList);
                }
                byKey.put(methodKey, cacheEntry == null? CACHE_MISS : cacheEntry);
            } catch (final MethodKey.AmbiguousException ae) {
                // that's a miss :-)
                byKey.put(methodKey, CACHE_MISS);
                throw ae;
            }
        }

        // Yes, this might just be null.
        return cacheEntry;
    }

    /**
     * Populate the Map of direct hits. These are taken from all the public methods
     * that our class, its parents and their implemented interfaces provide.
     *
     * @param cache          the ClassMap instance we create
     * @param permissions    the permissions to apply during introspection
     * @param clazz          the class to cache
     * @param log            the Log
     */
    private static void create(final ClassMap cache, final JexlPermissions permissions, final Class<?> clazz, final Log log) {
        //
        // Build a list of all elements in the class hierarchy. This one is bottom-first; we start
        // with the actual declaring class and its interfaces and then move up (superclass etc.) until we
        // hit java.lang.Object. That is important because it will give us the methods of the declaring class
        // which might in turn be abstract further up the tree.
        //
        // We also ignore all SecurityExceptions that might happen due to SecurityManager restrictions.
        //
        for (Class<?> classToReflect = clazz; classToReflect != null; classToReflect = classToReflect.getSuperclass()) {
            if (Modifier.isPublic(classToReflect.getModifiers()) && ClassTool.isExported(classToReflect)) {
                populateWithClass(cache, permissions, classToReflect, log);
            }
            final Class<?>[] interfaces = classToReflect.getInterfaces();
            for (final Class<?> anInterface : interfaces) {
                populateWithInterface(cache, permissions, anInterface, log);
            }
        }
        // now that we've got all methods keyed in, lets organize them by name
        if (!cache.byKey.isEmpty()) {
            final List<Method> lm = new ArrayList<>(cache.byKey.size());
            lm.addAll(cache.byKey.values());
            // sort all methods by name
            lm.sort(Comparator.comparing(Method::getName));
            // put all lists of methods with same name in byName cache
            int start = 0;
            while (start < lm.size()) {
                final String name = lm.get(start).getName();
                int end = start + 1;
                while (end < lm.size()) {
                    final String walk = lm.get(end).getName();
                    if (!walk.equals(name)) {
                        break;
                    }
                    end += 1;
                }
                final Method[] lmn = lm.subList(start, end).toArray(new Method[0]);
                cache.byName.put(name, lmn);
                start = end;
            }
        }
    }

    /**
     * Recurses up interface hierarchy to get all super interfaces.
     *
     * @param cache       the cache to fill
     * @param permissions the permissions to apply during introspection
     * @param iface       the interface to populate the cache from
     * @param log         the Log
     */
    private static void populateWithInterface(final ClassMap cache,
                                              final JexlPermissions permissions,
                                              final Class<?> iface,
                                              final Log log) {
        if (Modifier.isPublic(iface.getModifiers())) {
            populateWithClass(cache, permissions, iface, log);
            final Class<?>[] supers = iface.getInterfaces();
            for (final Class<?> aSuper : supers) {
                populateWithInterface(cache, permissions, aSuper, log);
            }
        }
    }

    /**
     * Recurses up class hierarchy to get all super classes.
     *
     * @param cache       the cache to fill
     * @param permissions the permissions to apply during introspection
     * @param clazz       the class to populate the cache from
     * @param log         the Log
     */
    private static void populateWithClass(final ClassMap cache,
                                          final JexlPermissions permissions,
                                          final Class<?> clazz,
                                          final Log log) {
        try {
            final Method[] methods = clazz.getDeclaredMethods();
            for (final Method mi : methods) {
                // method must be public
                if (!Modifier.isPublic(mi.getModifiers())) {
                    continue;
                }
                // add method to byKey cache; do not override
                final MethodKey key = new MethodKey(mi);
                final Method pmi = cache.byKey.putIfAbsent(key, permissions.allow(mi) ? mi : CACHE_MISS);
                if (pmi != null && pmi != CACHE_MISS && log.isDebugEnabled() && !key.equals(new MethodKey(pmi))) {
                    // foo(int) and foo(Integer) have the same signature for JEXL
                    log.debug("Method " + pmi + " is already registered, key: " + key.debugString());
                }
            }
        } catch (final SecurityException se) {
            // Everybody feels better with...
            if (log.isDebugEnabled()) {
                log.debug("While accessing methods of " + clazz + ": ", se);
            }
        }
    }
}
