/*
 * 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 freemarker.ext.beans;

import java.lang.reflect.Array;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

import freemarker.core.BugException;
import freemarker.template.ObjectWrapperAndUnwrapper;
import freemarker.template.TemplateModel;
import freemarker.template.TemplateModelException;

/**
 * Stores the varargs methods for a {@link OverloadedMethods} object.
 */
class OverloadedVarArgsMethods extends OverloadedMethodsSubset {

    OverloadedVarArgsMethods(boolean bugfixed) {
        super(bugfixed);
    }
    
    /**
     * Replaces the last parameter type with the array component type of it.
     */
    @Override
    Class[] preprocessParameterTypes(CallableMemberDescriptor memberDesc) {
        final Class[] preprocessedParamTypes = memberDesc.getParamTypes().clone();
        int ln = preprocessedParamTypes.length;
        final Class varArgsCompType = preprocessedParamTypes[ln - 1].getComponentType();
        if (varArgsCompType == null) {
            throw new BugException("Only varargs methods should be handled here");
        }
        preprocessedParamTypes[ln - 1] = varArgsCompType;
        return preprocessedParamTypes;
    }

    @Override
    void afterWideningUnwrappingHints(Class[] paramTypes, int[] paramNumericalTypes) {
        // Overview
        // --------
        //
        // So far, m(t1, t2...) was treated by the hint widening like m(t1, t2). So now we have to continue hint
        // widening like if we had further methods:
        // - m(t1, t2, t2), m(t1, t2, t2, t2), ...
        // - m(t1), because a varargs array can be 0 long
        //
        // But we can't do that for real, because we had to add infinite number of methods. Also, for efficiency we
        // don't want to create unwrappingHintsByParamCount entries at the indices which are still unused.
        // So we only update the already existing hints. Remember that we already have m(t1, t2) there.
        
        final int paramCount = paramTypes.length;
        final Class[][] unwrappingHintsByParamCount = getUnwrappingHintsByParamCount();
        
        // The case of e(t1, t2), e(t1, t2, t2), e(t1, t2, t2, t2), ..., where e is an *earlierly* added method.
        // When that was added, this method wasn't added yet, so it had no chance updating the hints of this method,
        // so we do that now:
        // FIXME: Only needed if m(t1, t2) was filled an empty slot, otherwise whatever was there was already
        // widened by the preceding hints, so this will be a no-op.
        for (int i = paramCount - 1; i >= 0; i--) {
            final Class[] previousHints = unwrappingHintsByParamCount[i];
            if (previousHints != null) {
                widenHintsToCommonSupertypes(
                        paramCount,
                        previousHints, getTypeFlags(i));
                break;  // we only do this for the first hit, as the methods before that has already widened it.
            }
        }
        // The case of e(t1), where e is an *earlier* added method.
        // When that was added, this method wasn't added yet, so it had no chance updating the hints of this method,
        // so we do that now:
        // FIXME: Same as above; it's often unnecessary.
        if (paramCount + 1 < unwrappingHintsByParamCount.length) {
            Class[] oneLongerHints = unwrappingHintsByParamCount[paramCount + 1];
            if (oneLongerHints != null) {
                widenHintsToCommonSupertypes(
                        paramCount,
                        oneLongerHints, getTypeFlags(paramCount + 1));
            }
        }
        
        // The case of m(t1, t2, t2), m(t1, t2, t2, t2), ..., where m is the currently added method.
        // Update the longer hints-arrays:  
        for (int i = paramCount + 1; i < unwrappingHintsByParamCount.length; i++) {
            widenHintsToCommonSupertypes(
                    i,
                    paramTypes, paramNumericalTypes);
        }
        // The case of m(t1) where m is the currently added method.
        // update the one-shorter hints-array:  
        if (paramCount > 0) {  // (should be always true, or else it wasn't a varags method)
            widenHintsToCommonSupertypes(
                    paramCount - 1,
                    paramTypes, paramNumericalTypes);
        }
        
    }
    
    private void widenHintsToCommonSupertypes(
            int paramCountOfWidened, Class[] wideningTypes, int[] wideningTypeFlags) {
        final Class[] typesToWiden = getUnwrappingHintsByParamCount()[paramCountOfWidened];
        if (typesToWiden == null) { 
            return;  // no such overload exists; nothing to widen
        }
        
        final int typesToWidenLen = typesToWiden.length;
        final int wideningTypesLen = wideningTypes.length;
        int min = Math.min(wideningTypesLen, typesToWidenLen);
        for (int i = 0; i < min; ++i) {
            typesToWiden[i] = getCommonSupertypeForUnwrappingHint(typesToWiden[i], wideningTypes[i]);
        }
        if (typesToWidenLen > wideningTypesLen) {
            Class varargsComponentType = wideningTypes[wideningTypesLen - 1];
            for (int i = wideningTypesLen; i < typesToWidenLen; ++i) {
                typesToWiden[i] = getCommonSupertypeForUnwrappingHint(typesToWiden[i], varargsComponentType);
            }
        }
        
        if (bugfixed) {
            mergeInTypesFlags(paramCountOfWidened, wideningTypeFlags);
        }
    }
    
    @Override
    MaybeEmptyMemberAndArguments getMemberAndArguments(List tmArgs, BeansWrapper unwrapper) 
    throws TemplateModelException {
        if (tmArgs == null) {
            // null is treated as empty args
            tmArgs = Collections.EMPTY_LIST;
        }
        final int argsLen = tmArgs.size();
        final Class[][] unwrappingHintsByParamCount = getUnwrappingHintsByParamCount();
        final Object[] pojoArgs = new Object[argsLen];
        int[] typesFlags = null;
        // Going down starting from methods with args.length + 1 parameters, because we must try to match against a case
        // where all specified args are fixargs, and we have 0 varargs.
        outer: for (int paramCount = Math.min(argsLen + 1, unwrappingHintsByParamCount.length - 1); paramCount >= 0; --paramCount) {
            Class[] unwarappingHints = unwrappingHintsByParamCount[paramCount];
            if (unwarappingHints == null) {
                if (paramCount == 0) {
                    return EmptyMemberAndArguments.WRONG_NUMBER_OF_ARGUMENTS;
                }
                continue;
            }
            
            typesFlags = getTypeFlags(paramCount);
            if (typesFlags == ALL_ZEROS_ARRAY) {
                typesFlags = null;
            }
            
            // Try to unwrap the arguments
            Iterator it = tmArgs.iterator();
            for (int i = 0; i < argsLen; ++i) {
                int paramIdx = i < paramCount ? i : paramCount - 1;
                Object pojo = unwrapper.tryUnwrapTo(
                        (TemplateModel) it.next(),
                        unwarappingHints[paramIdx],
                        typesFlags != null ? typesFlags[paramIdx] : 0);
                if (pojo == ObjectWrapperAndUnwrapper.CANT_UNWRAP_TO_TARGET_CLASS) {
                    continue outer;
                }
                pojoArgs[i] = pojo;
            }
            break outer;
        }
        
        MaybeEmptyCallableMemberDescriptor maybeEmtpyMemberDesc = getMemberDescriptorForArgs(pojoArgs, true);
        if (maybeEmtpyMemberDesc instanceof CallableMemberDescriptor) {
            CallableMemberDescriptor memberDesc = (CallableMemberDescriptor) maybeEmtpyMemberDesc;
            Object[] pojoArgsWithArray;
            Object argsOrErrorIdx = replaceVarargsSectionWithArray(pojoArgs, tmArgs, memberDesc, unwrapper);
            if (argsOrErrorIdx instanceof Object[]) {
                pojoArgsWithArray = (Object[]) argsOrErrorIdx;
            } else {
                return EmptyMemberAndArguments.noCompatibleOverload(((Integer) argsOrErrorIdx).intValue());
            }
            if (bugfixed) {
                if (typesFlags != null) {
                    // Note that overloaded method selection has already accounted for overflow errors when the method
                    // was selected. So this forced conversion shouldn't cause such corruption. Except, conversion from
                    // BigDecimal is allowed to overflow for backward-compatibility.
                    forceNumberArgumentsToParameterTypes(pojoArgsWithArray, memberDesc.getParamTypes(), typesFlags);
                }
            } else {
                BeansWrapper.coerceBigDecimals(memberDesc.getParamTypes(), pojoArgsWithArray);
            }
            return new MemberAndArguments(memberDesc, pojoArgsWithArray);
        } else {
            return EmptyMemberAndArguments.from((EmptyCallableMemberDescriptor) maybeEmtpyMemberDesc, pojoArgs);
        }
    }
    
    /**
     * Converts a flat argument list to one where the last argument is an array that collects the varargs, also
     * re-unwraps the varargs to the component type. Note that this couldn't be done until we had the concrete
     * member selected.
     * 
     * @return An {@code Object[]} if everything went well, or an {@code Integer} the
     *    order (1-based index) of the argument that couldn't be unwrapped. 
     */
    private Object replaceVarargsSectionWithArray(
            Object[] args, List modelArgs, CallableMemberDescriptor memberDesc, BeansWrapper unwrapper) 
    throws TemplateModelException {
        final Class[] paramTypes = memberDesc.getParamTypes();
        final int paramCount = paramTypes.length;
        final Class varArgsCompType = paramTypes[paramCount - 1].getComponentType(); 
        final int totalArgCount = args.length;
        final int fixArgCount = paramCount - 1;
        if (args.length != paramCount) {
            Object[] packedArgs = new Object[paramCount];
            System.arraycopy(args, 0, packedArgs, 0, fixArgCount);
            Object varargs = Array.newInstance(varArgsCompType, totalArgCount - fixArgCount);
            for (int i = fixArgCount; i < totalArgCount; ++i) {
                Object val = unwrapper.tryUnwrapTo((TemplateModel) modelArgs.get(i), varArgsCompType);
                if (val == ObjectWrapperAndUnwrapper.CANT_UNWRAP_TO_TARGET_CLASS) {
                    return Integer.valueOf(i + 1);
                }
                Array.set(varargs, i - fixArgCount, val);
            }
            packedArgs[fixArgCount] = varargs;
            return packedArgs;
        } else {
            Object val = unwrapper.tryUnwrapTo((TemplateModel) modelArgs.get(fixArgCount), varArgsCompType);
            if (val == ObjectWrapperAndUnwrapper.CANT_UNWRAP_TO_TARGET_CLASS) {
                return Integer.valueOf(fixArgCount + 1);
            }
            Object array = Array.newInstance(varArgsCompType, 1);
            Array.set(array, 0, val);
            args[fixArgCount] = array;
            return args;
        }
    }
    
}