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

package net.ranides.assira.reflection.impl.bean;

import java.util.Collection;
import net.ranides.assira.functional.VarFunction;
import net.ranides.assira.reflection.BeanMethod;
import net.ranides.assira.reflection.IClasses;
import net.ranides.assira.reflection.IMethod;

/**
 *
 * @author Ranides Atterwim <ranides@gmail.com>
 */
public class RBeanMethods implements BeanMethod {
    
    private final IMethod[] methods;
    
    RBeanMethods(Collection<IMethod> methods) {
        this.methods = methods.toArray(new IMethod[methods.size()]);
    }

    @Override
    public String name() {
        return methods[0].name();
    }

    @Override
    public VarFunction bind(Object that) {
        if(null == that) {
            throw new IllegalArgumentException("non-static method requires non-null 'this'");
        }
        return (arguments) -> apply(that, arguments);
    }

    @Override
    public Object apply(Object that) {
        for(IMethod m : methods) {
            if(m.arguments().isEmpty()) {
                return m.apply(that);
            }
        }
        throw new RuntimeException("method " + name() + " can't be invoked with no arguments.");
    }

    @Override
    public Object apply(Object that, Object... arguments) {
        for(IMethod m : methods) {
            if(m.accepts(arguments)) {
                return m.apply(that, arguments);
            }
        }
        throw new RuntimeException("method " + name() + " can't be invoked with passed arguments.");
    }

    @Override
    public boolean matches(IClasses arguments) {
        for(IMethod m : methods) {
            if(m.matches(arguments)) {
                return true;
            }
        }
        return false;
    }

    @Override
    public boolean accepts(Object... arguments) {
        for(IMethod m : methods) {
            if(m.accepts(arguments)) {
                return true;
            }
        }
        return false;
    }
    
    
}
