/*
 * @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.GenericArrayType;
import java.lang.reflect.GenericDeclaration;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.Set;
import net.ranides.assira.reflection.*;

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

    private final IClass<?> rtype;
    private final IClass<?> ctype;

    RGClass(IContext context, GenericArrayType gtype) {
        super(context);
        
        Type gcomponent = gtype.getGenericComponentType();
        IClass<?> icomponent = context.typeinfo(new TV(cname(gcomponent.getTypeName())));

        Class<?> rcomponent;
        try  {
            rcomponent = Class.forName("[L" + icomponent.name() + ";");
        } catch(ClassNotFoundException cne) {
            rcomponent = Object[].class;
        }
        this.rtype = context.typeinfo(rcomponent);
        this.ctype = context.typeinfo(gcomponent);

    }
    
    private static String cname(String typename) {
        int end = typename.indexOf('<');
        return end<0 ? typename : typename.substring(0,end);
    }

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

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

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

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

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

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

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

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

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

    @Override
    public IClass<?> component() {
        return ctype;
    }
    
    @Override
    public boolean isInstance(Object value) {
        return rtype.isInstance(value);
    }

    @Override
    public String name() {
        return ctype + "[]";
    }
    
    @Override
    public final String shortname() {
        return rtype.shortname();
    }

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

    @SuppressWarnings("PMD.MethodReturnsInternalArray")
    private static final class TV implements TypeVariable<GenericDeclaration> {
        
        private static final Annotation[] ANNOTATIONS = new Annotation[0];
        private static final Type[] BOUNDS = new Type[0];
        private static final AnnotatedType[] ABOUNDS = new AnnotatedType[0];
    
        private final String name;

        public TV(String name) {
            this.name = name;
        }

        @Override
        public Type[] getBounds() {
            return BOUNDS;
        }
        
        @Override
        public GenericDeclaration getGenericDeclaration() {
            throw new UnsupportedOperationException("TV:1");
        }

        @Override
        public String getName() {
            return name;
        }

        @Override
        public AnnotatedType[] getAnnotatedBounds() {
            return ABOUNDS;
        }
        
        @Override
        public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
            return null;
        }

        @Override
        public Annotation[] getAnnotations() {
            return ANNOTATIONS;
        }

        @Override
        public Annotation[] getDeclaredAnnotations() {
            return ANNOTATIONS;
        }

        @Override
        public String toString() {
            return name;
        }
        
    }
}
