/*
 * @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 net.ranides.assira.functional.VarFunction;
import net.ranides.assira.reflection.impl.FMethod;

/**
 * @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 FMethod.newMethod(method);
    }
    
    /**
     * Collect information using java.reflection API
     * @param method
     * @return 
     */
    static IMethod typeinfo(Constructor<?> method) {
        return FMethod.newMethod(method);
    }
    
    /**
     * Collect information for lambda expression
     * @param object
     * @return 
     */
    static IMethod function(Object object) {
        return FMethod.newFunction(object);
    }
    
    @Override
    IMethods collect();
    
    List<IClass<?>> params();
    
    IClass<?> returns();
    
    IArguments arguments();
    
    @Override
    IClass<?> parent();
    
    boolean matches(IClasses arguments);
    
    boolean matches(IClass<?>... arguments);
    
    boolean matches(Class<?>... arguments);
    
    boolean matches();
    
    boolean accepts(Object... arguments);

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

    Object call(Object... arguments);
    
    @SuppressWarnings("unchecked")
    default <T> T $apply() {
        return (T)apply();
    }
    
    @SuppressWarnings("unchecked")
    default <T> T $apply(Object that) {
        return (T)apply(that);
    }
    
    @SuppressWarnings("unchecked")
    default <T> T $apply(Object that, Object... arguments) {
        return (T)apply(that, arguments);
    }

    @SuppressWarnings("unchecked")
    default <T> T $call(Object... arguments) {
        return (T)call(arguments);
    }
    
    VarFunction bind(Object that);
    
    /**
     * optional
     * @return 
     */
    Method reflective();
    
    MethodHandle handle();
    
    <F> F handle(Class<F> functor);
    
    <F> F handle(IClass<F> functor);
    
}
