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

package net.ranides.assira.reflection.impl;

import net.ranides.assira.collection.query.CQuery;
import net.ranides.assira.reflection.*;
import net.ranides.assira.text.StrBuilder;

import java.io.Serializable;

/**
 * Base abstract class for IMethod implementation.
 *
 * @author Ranides Atterwim {@literal <ranides@gmail.com>}
 */
public abstract class AMethod extends AExecutable implements IMethod, Serializable {

    private static final long serialVersionUID = 1L;

    protected AMethod(IContext context) {
        super(context);
    }

	@Override
	public final IMethods collect() {
        return FElements.newMethods(IHints.none(), CQuery.from().value(this));
	}

	@Override
    protected String[] $debugParams() {
        return CDParameters.getParams(reflective());
    }

    @Override
    public final String toString() {
        return new StrBuilder()
            .append(returns()).append(" ")
            .append(parent())
            .append(".")
            .append(name())
            .open("(", ")",", ").append(arguments().list()).close()
            .toString();
    }

    @Override
    public boolean isGetter() {
        if(isStatic()) {
            return false;
        }
        IClass<?> ctype = parent();

        // eliminacja metod wbudowanych, w szczególności Object#getClass
        if(IClass.OBJECT.equals(ctype)) {
            return false;
        }
        // eliminacja na podstawie deklaracji
        if(arguments().count() != 0) {
            return false;
        }
        if(returns().isVoid()) {
            return false;
        }
        String name = name();
        // akceptacja klasycznego gettera
        if(name.startsWith("get") && name.length()>3 && Character.isUpperCase(name.charAt(3)) ) {
            return true;
        }
        // akceptacja gettera logicznego "isValue"
        if(name.startsWith("is") && name.length()>2 && Character.isUpperCase(name.charAt(2)) && returns().isBoolean() ) {
            return true;
        }
        return false;
    }

    @Override
    public boolean isSetter() {
        if(isStatic()) {
            return false;
        }

        IClass<?> ctype = parent();

        // eliminacja metod wbudowanych
        if(IClass.OBJECT.equals(ctype)) {
            return false;
        }

        IClass<?> rtype = returns();


        // eliminacja na podstawie deklaracji
        if(arguments().count() != 1) {
            return false;
        }
        if(!rtype.isVoid()  && !rtype.isSuper(ctype)) {
            return false;
        }
        String name = name();
        // akceptacja klasycznego settera
        if(name.startsWith("set") && name.length()>3 && Character.isUpperCase(name.charAt(3)) ) {
            return true;
        }
        return false;
    }
}
