/*
 * Copyright (c) 2003 The Visigoth Software Society. All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution, if
 *    any, must include the following acknowledgement:
 *       "This product includes software developed by the
 *        Visigoth Software Society (http://www.visigoths.org/)."
 *    Alternately, this acknowledgement may appear in the software itself,
 *    if and wherever such third-party acknowledgements normally appear.
 *
 * 4. Neither the name "FreeMarker", "Visigoth", nor any of the names of the 
 *    project contributors may be used to endorse or promote products derived
 *    from this software without prior written permission. For written
 *    permission, please contact visigoths@visigoths.org.
 *
 * 5. Products derived from this software may not be called "FreeMarker" or "Visigoth"
 *    nor may "FreeMarker" or "Visigoth" appear in their names
 *    without prior written permission of the Visigoth Software Society.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE VISIGOTH SOFTWARE SOCIETY OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Visigoth Software Society. For more
 * information on the Visigoth Software Society, please see
 * http://www.visigoths.org/
 */
package freemarker.ext.beans;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import freemarker.template.TemplateModelException;
import freemarker.template.utility.ClassUtil;
import freemarker.template.utility.NullArgumentException;

/**
 * @author Attila Szegedi
 */
abstract class OverloadedMethodsSubset {
    
    /** 
     * Used for an optimization trick to substitute an array of whatever size that contains only 0-s. Since this array
     * is 0 long, this means that the code that reads the int[] always have to check if the int[] has this value, and
     * then it has to act like if was all 0-s.  
     */
    static final int[] ALL_ZEROS_ARRAY = new int[0];

    private Class[/*number of args*/][/*arg index*/] unwrappingHintsByParamCount;
    
    /**
     * Tells what numerical types occur at a given parameter position with a bit field, also if the
     * unwrapping will do proper conversion. See {@link OverloadedNumberUtil#FLAG_INTEGER}, etc.
     */
    private int[/*number of args*/][/*arg index*/] possibleNumericalTypesByParamCount;
    
    // TODO: This can cause memory-leak when classes are re-loaded. However, first the genericClassIntrospectionCache
    // and such need to be fixed in this regard. 
    // Java 5: Use ConcurrentHashMap:
    private final Map/*<ArgumentTypes, MaybeEmptyCallableMemberDescriptor>*/ argTypesToMemberDescCache = new HashMap();
    
    private final List/*<CallableMemberDescriptor>*/ memberDescs = new LinkedList();
    
    /** Enables 2.3.21 {@link BeansWrapper} incompatibleImprovements */
    protected final boolean bugfixed;
    
    OverloadedMethodsSubset(BeansWrapper beansWrapper) {
        bugfixed = beansWrapper.is2321Bugfixed();
    }
    
    void addCallableMemberDescriptor(CallableMemberDescriptor memberDesc) {
        memberDescs.add(memberDesc);
        
        // Warning: Do not modify this array, or put it into unwrappingHintsByParamCount by reference, as the arrays
        // inside that are modified!
        final Class[] prepedParamTypes = preprocessParameterTypes(memberDesc);
        final int paramCount = prepedParamTypes.length;  // Must be the same as the length of the original param list
        
        // Merge these unwrapping hints with the existing table of hints:
        if (unwrappingHintsByParamCount == null) {
            unwrappingHintsByParamCount = new Class[paramCount + 1][];
            unwrappingHintsByParamCount[paramCount] = (Class[]) prepedParamTypes.clone();
        } else if (unwrappingHintsByParamCount.length <= paramCount) {
            Class[][] newUnwrappingHintsByParamCount = new Class[paramCount + 1][];
            System.arraycopy(unwrappingHintsByParamCount, 0, newUnwrappingHintsByParamCount, 0,
                    unwrappingHintsByParamCount.length);
            unwrappingHintsByParamCount = newUnwrappingHintsByParamCount;
            unwrappingHintsByParamCount[paramCount] = (Class[]) prepedParamTypes.clone();
        } else {
            Class[] unwrappingHints = unwrappingHintsByParamCount[paramCount]; 
            if (unwrappingHints == null) {
                unwrappingHintsByParamCount[paramCount] = (Class[]) prepedParamTypes.clone();
            } else {
                for (int paramIdx = 0; paramIdx < prepedParamTypes.length; paramIdx++) {
                    // For each parameter list length, we merge the argument type arrays into a single Class[] that
                    // stores the most specific common types for each position. Hence we will possibly use a too generic
                    // hint for the unwrapping. For correct behavior, for each overloaded methods its own parameter
                    // types should be used as a hint. But without unwrapping the arguments, we couldn't select the
                    // overloaded method. So this is a circular reference problem. We could try selecting the
                    // method based on the wrapped value, but that's quite tricky, and the result of such selection
                    // is not cacheable (the TM types are not enough as cache key then). So we just use this
                    // compromise.
                    unwrappingHints[paramIdx] = getCommonSupertypeForUnwrappingHint(
                            unwrappingHints[paramIdx], prepedParamTypes[paramIdx]);
                }
            }
        }

        int[] paramNumericalTypes = ALL_ZEROS_ARRAY;
        if (bugfixed) {
            // Fill possibleNumericalTypesByParamCount (if necessary)
            for (int paramIdx = 0; paramIdx < paramCount; paramIdx++) {
                final int numType = OverloadedNumberUtil.classToTypeFlags(prepedParamTypes[paramIdx]);
                if (numType != 0) {  // It's a numerical type
                    if (paramNumericalTypes == ALL_ZEROS_ARRAY) {
                        paramNumericalTypes = new int[paramCount];
                    }
                    paramNumericalTypes[paramIdx] = numType;
                }
            }
            mergeInNumericalTypes(paramCount, paramNumericalTypes);
        }
        
        afterWideningUnwrappingHints(
                bugfixed ? prepedParamTypes : unwrappingHintsByParamCount[paramCount],
                paramNumericalTypes);
    }
    
    Class[][] getUnwrappingHintsByParamCount() {
        return unwrappingHintsByParamCount;
    }
    
    final MaybeEmptyCallableMemberDescriptor getMemberDescriptorForArgs(Object[] args, boolean varArg) {
        ArgumentTypes argTypes = new ArgumentTypes(args, bugfixed);
        MaybeEmptyCallableMemberDescriptor memberDesc;
        synchronized(argTypesToMemberDescCache) {
            memberDesc = (MaybeEmptyCallableMemberDescriptor) argTypesToMemberDescCache.get(argTypes);
            if(memberDesc == null) {
                memberDesc = argTypes.getMostSpecific(memberDescs, varArg);
                argTypesToMemberDescCache.put(argTypes, memberDesc);
            }
        }
        return memberDesc;
    }
    
    Iterator/*<CallableMemberDescriptor>*/ getMemberDescriptors() {
        return memberDescs.iterator();
    }
    
    abstract Class[] preprocessParameterTypes(CallableMemberDescriptor memberDesc);
    abstract void afterWideningUnwrappingHints(Class[] paramTypes, int[] paramNumericalTypes);
    
    abstract MaybeEmptyMemberAndArguments getMemberAndArguments(List/*<TemplateModel>*/ tmArgs, 
            BeansWrapper w) throws TemplateModelException;

    /**
     * Returns the most specific common class (or interface) of two parameter types for the purpose of unwrapping.
     * This is trickier than finding the most specific overlapping superclass of two classes, because:
     * <ul>
     *   <li>It considers primitive classes as the subclasses of the boxing classes.</li>
     *   <li>If the only common class is {@link Object}, it will try to find a common interface. If there are more
     *       of them, it will start removing those that are known to be uninteresting as unwrapping hints.</li>
     * </ul>
     * 
     * @param c1 Parameter type 1
     * @param c2 Parameter type 2
     */
    protected Class getCommonSupertypeForUnwrappingHint(Class c1, Class c2) {
        if(c1 == c2) return c1;
        // This also means that the hint for (Integer, Integer) will be Integer, not just Number. This is consistent
        // with how non-overloaded method hints work.
        
        if (bugfixed) {
            // c1 primitive class to boxing class:
            final boolean c1WasPrim; 
            if (c1.isPrimitive()) {
                c1 = ClassUtil.primitiveClassToBoxingClass(c1);
                c1WasPrim = true;
            } else {
                c1WasPrim = false;
            }
            
            // c2 primitive class to boxing class:
            final boolean c2WasPrim; 
            if (c2.isPrimitive()) {
                c2 = ClassUtil.primitiveClassToBoxingClass(c2);
                c2WasPrim = true;
            } else {
                c2WasPrim = false;
            }
    
            if (c1 == c2) {
                // If it was like int and Integer, boolean and Boolean, etc., we return the boxing type (as that's the
                // less specific, because it allows null.)
                // (If it was two equivalent primitives, we don't get here, because of the 1st line of the method.) 
                return c1;
            } else if (Number.class.isAssignableFrom(c1) && Number.class.isAssignableFrom(c2)) {
                // We don't want the unwrapper to convert to a numerical super-type [*] as it's not yet known what the
                // actual number type of the chosen method will be. We will postpone the actual numerical conversion
                // until that, especially as some conversions (like fixed point to floating point) can be lossy.
                // * Numerical super-type: Like long > int > short > byte.  
                return Number.class;
            } else if (c1WasPrim || c2WasPrim) {
                // At this point these all stand:
                // - At least one of them was primitive
                // - No more than one of them was numerical
                // - They don't have the same wrapper (boxing) class
                return Object.class;
            }
            // Falls through
        } else {  // old buggy behavior
            if(c2.isPrimitive()) {
                if(c2 == Byte.TYPE) c2 = Byte.class;
                else if(c2 == Short.TYPE) c2 = Short.class;
                else if(c2 == Character.TYPE) c2 = Character.class;
                else if(c2 == Integer.TYPE) c2 = Integer.class;
                else if(c2 == Float.TYPE) c2 = Float.class;
                else if(c2 == Long.TYPE) c2 = Long.class;
                else if(c2 == Double.TYPE) c2 = Double.class;
            }
        }
        
        // We never get to this point if buxfixed is true and any of these stands:
        // - One of classes was a primitive type
        // - One of classes was a numerical type (either boxing type or primitive)
        
        Set commonTypes = MethodUtilities.getAssignables(c1, c2);
        commonTypes.retainAll(MethodUtilities.getAssignables(c2, c1));
        if(commonTypes.isEmpty()) {
            // Can happen when at least one of the arguments is an interface, as
            // they don't have Object at the root of their hierarchy
            return Object.class;
        }
        
        // Gather maximally specific elements. Yes, there can be more than one 
        // thank to interfaces. I.e., if you call this method for String.class 
        // and Number.class, you'll have Comparable, Serializable, and Object as 
        // maximal elements. 
        List max = new ArrayList();
        listCommonTypes:  for (Iterator commonTypesIter = commonTypes.iterator(); commonTypesIter.hasNext();) {
            Class clazz = (Class)commonTypesIter.next();
            for (Iterator maxIter = max.iterator(); maxIter.hasNext();) {
                Class maxClazz = (Class)maxIter.next();
                if(MethodUtilities.isMoreOrSameSpecificParameterType(maxClazz, clazz, false /*bugfixed [1]*/, 0) != 0) {
                    // clazz can't be maximal, if there's already a more specific or equal maximal than it.
                    continue listCommonTypes;
                }
                if(MethodUtilities.isMoreOrSameSpecificParameterType(clazz, maxClazz, false /*bugfixed [1]*/, 0) != 0) {
                    // If it's more specific than a currently maximal element,
                    // that currently maximal is no longer a maximal.
                    maxIter.remove();
                }
                // 1: We don't use bugfixed at the "[1]"-marked points because it's slower and doesn't make any
                //    difference here as it's ensured that nor c1 nor c2 is primitive or numerical. The bugfix has only
                //    affected the treatment of primitives and numerical types. 
            }
            // If we get here, no current maximal is more specific than the
            // current class, so clazz is a new maximal so far.
            max.add(clazz);
        }
        
        if (max.size() > 1) {  // we have an ambiguity
            if (bugfixed) {
                // Find the non-interface class
                for (Iterator it = max.iterator(); it.hasNext();) {
                    Class maxCl = (Class) it.next();
                    if (!maxCl.isInterface()) {
                        if (maxCl != Object.class) {  // This actually shouldn't ever happen, but to be sure...
                            // If it's not Object, we use it as the most specific
                            return maxCl;
                        } else {
                            // Otherwise remove Object, and we will try with the interfaces 
                            it.remove();
                        }
                    }
                }
                
                // At this point we only have interfaces left.
                // Try removing interfaces about which we know that they are useless as unwrapping hints:
                max.remove(Cloneable.class);
                if (max.size() > 1) {  // Still have an ambiguity...
                    max.remove(Serializable.class);
                    if (max.size() > 1) {  // Still had an ambiguity...
                        max.remove(Comparable.class);
                        if (max.size() > 1) {
                            return Object.class; // Still had an ambiguity... no luck.
                        }
                    }
                }
            } else {
                return Object.class;
            }
        }
        
        return (Class) max.get(0);
    }
    
    /**
     * Gets the numerical type "flags" of each parameter positions, or {@code null} if there's no method with this
     * parameter count or if we aren't in pre-2.3.21 mode, {@link #ALL_ZEROS_ARRAY} if there were no numerical
     * parameters. The returned {@code int}-s are on or more {@link OverloadedNumberUtil}} {@code FLAG_...} constants
     * binary "or"-ed together.  
     */
    final protected int[] getPossibleNumericalTypes(int paramCount) {
        return possibleNumericalTypesByParamCount != null && possibleNumericalTypesByParamCount.length > paramCount
                ? possibleNumericalTypesByParamCount[paramCount]
                : null;
    }

    /**
     * @param dstParamCount The parameter count for which we want to merge in the possible numerical types 
     * @param srcNumTypesByParamIdx If shorter than {@code dstParamCount}, it's last item will be repeated until
     *        dstParamCount length is reached. If longer, the excessive items will be ignored.
     *        Maybe {@link #ALL_ZEROS_ARRAY}. Cant'be a 0-length array. Can't be {@code null}.
     */
    final protected void mergeInNumericalTypes(int dstParamCount, int[] srcNumTypesByParamIdx) {
        NullArgumentException.check("srcNumTypesByParamIdx", srcNumTypesByParamIdx);
        if (dstParamCount == 0) return;
        
        // Ensure that possibleNumericalTypesByParamCount[dstParamCount] exists:
        if (possibleNumericalTypesByParamCount == null) {
            possibleNumericalTypesByParamCount = new int[dstParamCount + 1][];
        } else if (possibleNumericalTypesByParamCount.length <= dstParamCount) {
            if (srcNumTypesByParamIdx == null) return;
            
            int[][] newNumericalTypeByParamCount = new int[dstParamCount + 1][];
            System.arraycopy(possibleNumericalTypesByParamCount, 0, newNumericalTypeByParamCount, 0,
                    possibleNumericalTypesByParamCount.length);
            possibleNumericalTypesByParamCount = newNumericalTypeByParamCount;
        }
        
        final int srcParamCount = srcNumTypesByParamIdx.length;
        
        int[] dstNumTypesByParamIdx = possibleNumericalTypesByParamCount[dstParamCount];
        if (dstNumTypesByParamIdx == null) {
            // This is the first method added with this number of params => no merging
            
            if (srcNumTypesByParamIdx != ALL_ZEROS_ARRAY) {
                dstNumTypesByParamIdx = new int[dstParamCount];
                for (int paramIdx = 0; paramIdx < dstParamCount; paramIdx++) {
                    dstNumTypesByParamIdx[paramIdx]
                            = srcNumTypesByParamIdx[paramIdx < srcParamCount ? paramIdx : srcParamCount - 1];
                }
            } else {
                dstNumTypesByParamIdx = ALL_ZEROS_ARRAY;
            }
            
            possibleNumericalTypesByParamCount[dstParamCount] = dstNumTypesByParamIdx;
        } else {
            // dstNumTypesByParamIdx != null, so we need to merge into it.
            
            if (srcNumTypesByParamIdx == dstNumTypesByParamIdx) {
                // Used to occur when both are ALL_ZEROS_ARRAY
                return;
            }
            
            // As we will write dstNumTypesByParamIdx, it can't remain ALL_ZEROS_ARRAY anymore. 
            if (dstNumTypesByParamIdx == ALL_ZEROS_ARRAY && dstParamCount > 0) {
                dstNumTypesByParamIdx = new int[dstParamCount];
                possibleNumericalTypesByParamCount[dstParamCount] = dstNumTypesByParamIdx;
            }
            
            for (int paramIdx = 0; paramIdx < dstParamCount; paramIdx++) {
                final int srcParamNumTypes
                        = srcNumTypesByParamIdx != ALL_ZEROS_ARRAY
                            ? srcNumTypesByParamIdx[paramIdx < srcParamCount ? paramIdx : srcParamCount - 1]
                            : 0;
                final int dstParamNumTypes = dstNumTypesByParamIdx[paramIdx];
                if (dstParamNumTypes != srcParamNumTypes) {
                    dstNumTypesByParamIdx[paramIdx]
                            = dstParamNumTypes | srcParamNumTypes | OverloadedNumberUtil.FLAG_WIDENED_UNWRAPPING_HINT; 
                }
                // Note that if a parameter is non-numerical, its paraNumTypes is 0. So if we have a non-number and
                // a some kind of number (non-0), the merged result will be marked with FLAG_WIDENED_UNWRAPPING_HINT.
                // (I.e., the same happens as with two different numerical types.)
            }
        }
    }
    
    protected void forceNumberArgumentsToParameterTypes(
            Object[] args, Class[] paramTypes, int[] unwrappingNumTypesByParamIndex) {
        final int paramTypesLen = paramTypes.length;
        final int argsLen = args.length;
        for (int argIdx = 0; argIdx < argsLen; argIdx++) {
            final int paramTypeIdx = argIdx < paramTypesLen ? argIdx : paramTypesLen - 1;
            final int unwrappingNumTypes = unwrappingNumTypesByParamIndex[paramTypeIdx];
            
            // Forcing the number type can only be interesting if there are numerical parameter types on that index,
            // and the unwrapping was not to an exact numerical type.
            if (unwrappingNumTypes != 0
                    && (unwrappingNumTypes & OverloadedNumberUtil.FLAG_WIDENED_UNWRAPPING_HINT) != 0) {
                final Object arg = args[argIdx];
                // If arg isn't a number, we can't do any conversions anyway, regardless of the param type.
                if (arg instanceof Number) {
                    final Class targetType = paramTypes[paramTypeIdx];
                    final Number convertedArg = BeansWrapper.forceUnwrappedNumberToType(
                            (Number) arg, targetType, bugfixed);
                    if (convertedArg != null) {
                        args[argIdx] = convertedArg;
                    }
                }
            }
        }
    }
    
}
