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

import java.lang.invoke.MethodHandle;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.List;
import java.util.function.Function;
import net.ranides.assira.reflection.impl.RConstructor;
import net.ranides.assira.reflection.impl.RMethod;

/**
 * @author Ranides Atterwim <ranides@gmail.com>
 */
public interface IMethod extends IElement {
    
    /**
     * Collect information using java.reflection API
     * @param method
     * @return 
     */
    static IMethod typeinfo(Method method) {
        return RMethod.typeinfo(method);
    }
    
    /**
     * Collect information using java.reflection API
     * @param method
     * @return 
     */
    static IMethod typeinfo(Constructor<?> method) {
        return RConstructor.typeinfo(method);
    }
    
    /**
     * Collect information for lambda expression
     * @param object
     * @return 
     */
    static IMethod function(Object object) {
        return RMethod.function(object);
    }
    
    @Override
    IMethods collect();
    
    List<IClass> params();
    
    IClass returns();
    
    IArguments arguments();
    
    @Override
    IClass parent();
    
    boolean matches(IClasses arguments);
    
    boolean accepts(Object... arguments);

    Object apply();
    
    Object apply(Object that);
    
    Object apply(Object that, Object... arguments);

    Object call(Object... arguments);
    
    Function<Object[], Object> bind(Object that);
    
    /**
     * optional
     * @return 
     */
    Method reflective();
    
    MethodHandle handle();

}
