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

package net.ranides.assira.reflection.impl;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import net.ranides.assira.collection.maps.OrderedMap;
import net.ranides.assira.collection.query.CQuery;
import net.ranides.assira.collection.query.CQueryBuilder;
import net.ranides.assira.reflection.IAnnotations;
import net.ranides.assira.reflection.IArgument;
import net.ranides.assira.reflection.IArguments;
import net.ranides.assira.reflection.IAttribute;
import net.ranides.assira.reflection.IClass;
import net.ranides.assira.reflection.IField;
import net.ranides.assira.reflection.IFields;
import net.ranides.assira.reflection.IHints;
import net.ranides.assira.reflection.IMethod;
import net.ranides.assira.reflection.IMethods;
import net.ranides.assira.reflection.util.AnnotationUtils;

/**
 *
 * @author Ranides Atterwim <ranides@gmail.com>
 */
public final class FElements {
    
    private FElements() {
        /* utility class */
    }

    public static AAnnotations newAnnotations(IHints hints, CQuery<Annotation> stream) {
        return new AAnnotations(hints, stream);
    }
    
    @SafeVarargs
    public static IAnnotations newAnnotations(Class<? extends Annotation>... annotations) {
        return newAnnotations(AHints.EMPTY, CQueryBuilder.fromArray(annotations).map(a -> AnnotationUtils.make(a)));
    }
    
    public static IAnnotations newAnnotations(Annotation... annotations) {
        return newAnnotations(AHints.EMPTY, CQueryBuilder.fromArray(annotations));
    }
    
    public static AArguments newArguments(IHints hints, int count, CQuery<IArgument> stream) {
        return new AArguments(hints, count, stream);
    }
    
    public static IArguments newArguments(IClass<?>... types) {
        return newArguments(AHints.EMPTY, types.length, CQueryBuilder.fromArray(types).map(v -> FArgument.newArgument(v)));
    }
    
    public static IArguments newArguments(Class<?>... types) {
        return newArguments(AHints.EMPTY, types.length, CQueryBuilder.fromArray(types).map(v -> FArgument.newArgument(v)));
    }
    
    public static IArguments newArguments(OrderedMap<String, IClass<?>> arguments) {
        return newArguments(AHints.EMPTY, arguments.size(), CQueryBuilder.fromCollection(arguments.entrySet()).map(v -> FArgument.newArgument(v)));
    }
    
    public static AClasses newClasses(IClass<?>[] array) {
        return newClasses(AHints.EMPTY, CQueryBuilder.fromArray(array));
    }

    public static AClasses newClasses(IHints hints, CQuery<IClass<?>> stream) {
        return new AClasses(hints, stream);
    }
    
    public static AFields newFields(IHints hints, CQuery<IField> stream) {
        return new AFields(hints, stream);
    }
    
    public static IFields newFields(Field... fields) {
        return newFields(AHints.EMPTY, CQueryBuilder.fromArray(fields).map(IField::typeinfo));
    }

    public static AHints newHints() {
        return new AHints(IAttribute.collect(),IAttribute.collect());
    }
    
    public static AMethods newMethods(IHints hints, CQuery<IMethod> stream) {
        return new AMethods(hints, stream);
    }
	
    public static IMethods newMethods(Method... methods) {
        return newMethods(AHints.EMPTY, CQueryBuilder.fromArray(methods).map(m -> IMethod.typeinfo(m)));
    }

    public static IMethods newFunctions(Object... objects) {
        return newMethods(AHints.EMPTY, CQueryBuilder.fromArray(objects).map(IMethod::function));
    }
    
}
