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

import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import static net.ranides.assira.junit.NewAssert.*;
import net.ranides.assira.reflection.IClass;
import org.junit.Test;

/**
 *
 * @author Ranides Atterwim <ranides@gmail.com>
 */
@SuppressFBWarnings("UUF_UNUSED_PUBLIC_OR_PROTECTED_FIELD")
public class RWClassTest {
    
    public List<? super ArrayList<Float>> a;
    public List<? extends ArrayList<Float>> b;
	
    @Test
    public void testParent() {
        IClass<?> ic1 = IClass.typefor(this).field("a").get().type().params().get(0);
        assertEquals("java.lang.Object", ic1.parent().toString());
        assertEquals("[java.lang.Object]", ic1.parents().toString());
        assertEquals(Arrays.asList(), ic1.interfaces().stream().distinct().list());
        assertEquals("? super java.util.ArrayList<java.lang.Float>", ic1.reflective().toString());
        assertEquals(Object.class, ic1.raw());
        // @todo (assira #6) reflective: generics: isInstance dla wildcards
        // rzecz w tym, że my tu mamy unresolved params, bo przekazujemy objekt (i type erasure wchodzi)
        // a to oznacza, że NIE powinno tutaj nic matchować na ten moment
        // o ile nie zrobimy obsługi prawdziwej dla atrybutu IAttribute.RESOLVED
        // tylko w takim wypadku możemy być "tolerancyjniejsi" względem erasure'owanych typów
        // i je przepuszczać
        
        // test dla wildcardów powinien opierać się na isSuper/isSubclass dla TypeToken jako argumentu
        // bo on zawiera całe info na temat typu testowanego
//        System.out.printf("%s%n", ic1);
//        assertTrue(ic1.isInstance(new ArrayList<Float>())); 

        assertFalse(ic1.isInstance(new ArrayList<Double>()));
        assertFalse(ic1.isInstance(new java.util.LinkedList<Float>()));
        assertEquals("[PUBLIC]", ic1.attributes().toString());
        assertEquals("[]", ic1.annotations().toString());
        
        
        
        IClass<?> ic2 = IClass.typefor(this).field("b").get().type().params().get(0);
        assertEquals("java.util.ArrayList<java.lang.Float>", ic2.parent().toString());
        assertEquals("[java.util.ArrayList<java.lang.Float>, java.util.AbstractList<java.lang.Float>, java.util.AbstractCollection<java.lang.Float>, java.lang.Object]", ic2.parents().toString());
        List<String> interfaces2 = Arrays.asList(
            "java.util.List<java.lang.Float>", 
            "java.util.RandomAccess", 
            "java.lang.Cloneable", 
            "java.io.Serializable",
            "java.util.Collection<java.lang.Float>"
        );
        assertEquivalent(interfaces2, ic2.interfaces().stream().distinct().map(c -> c.toString()).list());
        assertEquals("? extends java.util.ArrayList<java.lang.Float>", ic2.reflective().toString());
        assertEquals(Object.class, ic2.raw());
        
//        assertEquals(false, ic2.isInstance(new ArrayList<Float>()));        // ?
//        assertEquals(false, ic2.isInstance(new ArrayList<Double>()));       // ?
//        assertEquals(false, ic2.isInstance(new LinkedList<Float>()));       // ?
        assertEquals("[PUBLIC]", ic2.attributes().toString());
        assertEquals("[]", ic2.annotations().toString());
    }
    
    
	
}
