/*
 * @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.AnnotatedType;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Set;
import net.ranides.assira.collection.query.CQuery;
import net.ranides.assira.collection.query.CQueryBuilder;
import net.ranides.assira.reflection.*;

/**
 *
 * @author Ranides Atterwim <ranides@gmail.com>
 */
public class RFClass<T> extends AClass<T> {

    private final IClass<T> itype;
    private final AnnotatedType atype;

    RFClass(IContext context, IClass<T> itype, AnnotatedType atype) {
        super(context);
        this.itype = itype;
        this.atype = atype;
    }

    @Override
    public List<IClass<?>> params() {
        return itype.params();
    }

    @Override
    public IFields fields() {
        return itype.fields();
    }

    @Override
    public IMethods constructors() {
        return itype.constructors();
    }

    @Override
    public IMethods methods() {
        return itype.methods();
    }

    @Override
    public IClass<?> parent() {
        return itype.parent();
    }

    @Override
    public IClasses parents() {
        return itype.parents();
    }

    @Override
    public IClasses interfaces() {
        return itype.interfaces();
    }

    @Override
    public IClass<?> outer() {
        return itype.outer();
    }

    @Override
    public IClasses inner() {
        return itype.inner();
    }
    
    @Override
    public Type reflective() {
        return itype.reflective();
    }

    @Override
    public Class<?> raw() {
        return itype.raw();
    }

    @Override
    public boolean isInstance(Object value) {
        return itype.isInstance(value);
    }

    @Override
    public String name() {
        return itype.name();
    }
    
    @Override
    public final String shortname() {
        return itype.shortname();
    }

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

    @Override
    public IAnnotations annotations() {
        AHints attr = FElements.newHints();
        CQuery<Annotation> query = new CQueryBuilder<Annotation>()
            .addQuery(itype.annotations().hint(attr).stream())
            .addArray(attr, this::getRFAnnotations)
            .result();
        return FElements.newAnnotations(attr, query);
    }
    
    public Annotation[] getRFAnnotations(AHints hints) {
        if(hints.require().contains(IAttribute.DECLARED)) {
            return atype.getDeclaredAnnotations();
        } else {
            return atype.getAnnotations();
        }
    }

    public IClass<?> $itype() {
        return itype;
    }
    
}
