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

import net.ranides.assira.annotations.Meta;
import net.ranides.assira.functional.special.AnyFunction;
import net.ranides.assira.reflection.impl.FMethod;

import java.lang.reflect.Constructor;

/**
 * This interface represent constructors.
 *
 * Because java.reflect Constructor is generic, we use the same here: T parameter
 * is the type of created instance.
 *
 * @param <T> T
 * @author Ranides Atterwim {@literal <ranides@gmail.com>}
 */
public interface IConstructor<T> extends IExecutable {

    /**
     * Factory: creates IConstructor from java.reflection constructor
     *
     * @param method method
     * @param <T> T
     * @return IConstructor
     */
    static <T> IConstructor<T> typeinfo(Constructor<T> method) {
        return FMethod.newConstructor(method);
    }

    @Override
    IConstructors<T> collect();

    @Override
    IConstructor<T> accessible();

    /**
     * Returns reflective Constructor assocciated with this IConstructor.
     *
     * @return Constructor
     */
    Constructor<T> reflective();

    /**
     * Returns function which uses ConstructorAccessor to create new instance objects.
     *
     * Accessor is useful if you want to bypass all sanity checks inside Class#newInstance.
     * Most of them can be disabled by calling AccessibleObject#setAccessible, but not all.
     *
     * It applies especially for enum types. Creation new instances of enum is extremally strange,
     * but possible if you use accessor
     *
     * @return AnyFunction
     */
    @Meta.UnstableAPI
    AnyFunction<T> accessor();

}
