/*
 * @author Ranides Atterwim {@literal <ranides@gmail.com>}
 * @copyright Ranides Atterwim
 * @license WTFPL
 * @url http://ranides.net/projects/assira
 */

package net.ranides.assira.reflection.impl;

import lombok.experimental.UtilityClass;

import java.lang.reflect.Parameter;
import java.util.Map;
import net.ranides.assira.reflection.IArgument;
import net.ranides.assira.reflection.IClass;
import net.ranides.assira.reflection.IContext;

/**
 * This is internal factory for IArgument implementations.
 *
 * @author Ranides Atterwim {@literal <ranides@gmail.com>}
 */
@UtilityClass
public final class FArgument {

    /**
     * Creates new non-reflective argument with provided type and name.
     *
     * @param name name
     * @param type type
     * @return IArgument
     */
    public static IArgument newArgument(String name, IClass<?> type) {
        return new CArgument(name, type);
    }

    /**
     * Creates new non-reflective argument with provided type, but without name.
     * If you try to used it as named argument, it will throw exception.
     *
     * @param type type
     * @return IArgument
     */
    public static IArgument newArgument(Class<?> type) {
        return newArgument(null, IClass.typeinfo(type));
    }

    /**
     * Creates new non-reflective argument with provided type, but without name.
     * If you try to used it as named argument, it will throw exception.
     *
     * @param type type
     * @return IArgument
     */
    public static IArgument newArgument(IClass<?> type) {
        return newArgument(null, type);
    }

    /**
     * Creates new non-reflective argument with provided type and name.
     *
     * @param entry entry
     * @return IArgument
     */
    public static IArgument newArgument(Map.Entry<String, IClass<?>> entry) {
        return newArgument(entry.getKey(), entry.getValue());
    }

    /**
     * Creates new reflective argument.
     * It supports generic type resolution (using context), it stores reference to parent method
     * and parameter name.
     *
     * If name is not resolved by reflection, it will return generated one.
     *
     * @param context context
     * @param parent parent
     * @param param param
     * @param index index
     * @return IArgument
     */
    public static IArgument newArgument(IContext context, AExecutable parent, Parameter param, int index) {
        return new RArgument(context, parent, param, index);
    }
    
}
