/*
 * @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.util.Arrays;
import java.util.Collections;
import java.util.List;
import net.ranides.assira.annotations.Meta;
import net.ranides.assira.reflection.IClass;
import static net.ranides.assira.junit.NewAssert.*;
import net.ranides.assira.reflection.IAttribute;
import org.junit.Test;

/**
 *
 * @author Ranides Atterwim <ranides@gmail.com>
 */
public class RFClassTest {
    
    public RFClassTest() {
    }

    @Test
    public void testField() {
        IClass<?> f1 = IClass.typeinfo(Owner.class).field("a").get().type();
        
        assertEquals(Collections.emptyList(), f1.fields().names());
        assertEquals(Collections.emptyList(), f1.constructors().list(c -> c.name()+c.params()));
        assertEquals(Collections.emptyList(), f1.methods().list());
        assertEquals(IClass.NULL, f1.parent());
        assertEquals(Collections.emptyList(), f1.parents().list());
        assertEquals(Collections.emptyList(), f1.interfaces().list());
        assertEquals(IClass.NULL, f1.outer());
        assertEquals(Collections.emptyList(), f1.inner().list());
        assertEquals(int.class, f1.reflective());
        assertEquals(true, f1.attributes().contains(IAttribute.PRIMITIVE));
        assertEquals("[PUBLIC, FINAL, ABSTRACT, DECLARED, PRIMITIVE, NUMBER, INTEGER]", f1.attributes().toString());
        assertEquals(Collections.emptyList(), f1.annotations().list());
        
        
        IClass<?> f2 = IClass.typeinfo(Owner.class).field("b").get().type();
        assertEquals(Arrays.asList("x"), f2.fields().names());
        List<String> constructors1 = Arrays.asList(
            "net.ranides.assira.reflection.impl.RFClassTest$Prop[]"
        );
        assertEquals(constructors1, f2.constructors().list(c -> c.name()+c.arguments().types()));
        List<String> constructors2 = Arrays.asList(
            "net.ranides.assira.reflection.impl.RFClassTest$Prop[]",
            "net.ranides.assira.reflection.impl.RFClassTest$Prop[double]" 
        );
        assertEquivalent(constructors2, f2.constructors().require(IAttribute.DECLARED).list(c -> c.name()+c.arguments().types()));
        assertEquals(3, f2.methods().require(IAttribute.DECLARED).discard(IAttribute.SYNTHETIC).count());
        assertEquals(IClass.OBJECT, f2.parent());
        assertEquals(Arrays.asList(IClass.OBJECT), f2.parents().list());
        assertEquals("[java.util.List<E>]", f2.interfaces().toString());
        assertEquals("net.ranides.assira.reflection.impl.RFClassTest", f2.outer().toString());
        assertEquals("[]", f2.inner().toString());
        assertEquals(Prop.class, f2.reflective());
        assertEquals(false, f2.attributes().contains(IAttribute.PRIMITIVE));
        assertEquals("[PRIVATE, STATIC, ABSTRACT, PARAMETERIZED, DECLARED]", f2.attributes().toString());
        assertEquals(Collections.emptyList(), f2.annotations().list());
    }
    
    private static abstract class Owner {
        
        @Meta.Final
        @Deprecated
        public int a;
        
        public Prop<String> b;
        
        public void func0(int a) { }
        
        public void func1(@Deprecated Prop<Double> param) { }
        
    }
    
    private static abstract class Prop<T> implements List<T> {
        
        public double x;
        
        private float y;
        
        public Prop() { }
        
        private Prop(double z) { }
        
        public void met1() { }
        
        private void met1(int x, int y) {};
        
        public void bind(T value) { }
    
    }
    
}
