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

import java.lang.annotation.Annotation;
import java.lang.reflect.Parameter;
import java.util.Optional;
import java.util.Set;
import net.ranides.assira.reflection.*;
import net.ranides.assira.collection.query.CQueryBuilder;

/**
 *
 * @author Ranides Atterwim <ranides@gmail.com>
 */
public class RArgument implements IArgument {

    private final IContext context;
    
    private final AMethod parent;
    
    private final Parameter param;
    
    private final int index;

    RArgument(IContext context, AMethod parent, Parameter param, int index) {
        this.parent = parent;
        this.param = param;
        this.context = context;
        this.index = index;
    }

    @Override
    public IContext context() {
        return context;
    }

    @Override
    public IArguments collect() {
        return FElements.newArguments(AHints.EMPTY, 1, CQueryBuilder.of(this));
    }

    @Override
    public Parameter reflective() {
        return param;
    }

    @Override
    public IClass<?> type() {
        final IContext c = context();
        return FClass.newClass(c, param.getParameterizedType(), param.getAnnotatedType());
    }

    @Override
    public String name() {
        if(!param.isNamePresent()) {
            String[] names = parent.$debugParams();
            if(null == names) {
                throw new UnsupportedOperationException("You have to compile class with -parameters or -g switch");
            }
            return names[index];
        }
        return param.getName();
    }

    private String iname() {
        if(!param.isNamePresent()) {
            String[] names = parent.$debugParams();
            if(null != names) {
                return names[index];
            }
        }
        return param.getName();
    }

    @Override
    public IMethod parent() {
        return parent;
    }

    @Override
    public Set<IAttribute> attributes() {
        return IAttribute.resolve(param);
    }

    @Override
    public IAnnotations annotations() {
        return FElements.newAnnotations(AHints.EMPTY, CQueryBuilder.fromArray(param.getAnnotations()));
    }
    
    @Override
    public <A extends Annotation> Optional<A> annotation(Class<A> type) {
        return annotations().first(type);
    }

    @Override
    public final boolean equals(Object object) {
        return (object instanceof IArgument) && ((IArgument)object).type().equals(type());
    }
    
    @Override
    public final int hashCode() {
        return this.type().hashCode();
    }

    @Override
    public String toString() {
        return type() + " " + iname();
    }
    
}
