/*
 * @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.List;
import java.util.Map;
import net.ranides.assira.generic.TypeToken;
import net.ranides.assira.reflection.IClass;
import org.junit.Test;
import static org.junit.Assert.*;

/**
 *
 * @author Ranides Atterwim <ranides@gmail.com>
 */
@SuppressFBWarnings("UUF_UNUSED_PUBLIC_OR_PROTECTED_FIELD")
public class RGClassTest {
    
    @Test
    public void testArray() throws NoSuchMethodException {
        TypeToken<Container<String>> ic = new TypeToken<Container<String>>(){};
        
        IClass<?>   t1g = new TypeToken<Float[]>(){};
        IClass<?>   t1c = new TypeToken<Float>(){};
        Class<?> t1r = Float[].class;
         
        IClass<?>   t2g = new TypeToken<List<Double>[]>(){};
        IClass<?>   t2c = new TypeToken<List<Double>>(){};
        Class<?> t2r = List[].class;
        
        IClass<?>   t3g = new TypeToken<List<Map<? extends Number, String>>[]>(){};
        IClass<?>   t3c = new TypeToken<List<Map<? extends Number, String>>>(){};
        Class<?> t3r = List[].class;
        
        IClass<?>   t4g = new TypeToken<String[]>(){};
        IClass<?>   t4c = new TypeToken<String>(){};
        Class<?> t4r = String[].class;
        
        IClass<?>   t5g = new TypeToken<Map<String,Short>[]>(){};
        IClass<?>   t5c = new TypeToken<Map<String,Short>>(){};
        Class<?> t5r = Map[].class;
        
        // method return type
        assertArrayType(t1g, t1c, t1r, ic.method("get1").get().returns());
        assertArrayType(t2g, t2c, t2r, ic.method("get2").get().returns());
        assertArrayType(t3g, t3c, t3r, ic.method("get3").get().returns());
        assertArrayType(t4g, t4c, t4r, ic.method("get4").get().returns());
        assertArrayType(t5g, t5c, t5r, ic.method("get5").get().returns());
        
        // method arguments
        assertArrayType(t1g, t1c, t1r, ic.method("set1").get().arguments().types().first().get());
        assertArrayType(t2g, t2c, t2r, ic.method("set2").get().arguments().types().first().get());
        assertArrayType(t3g, t3c, t3r, ic.method("set3").get().arguments().types().first().get());
        assertArrayType(t4g, t4c, t4r, ic.method("set4").get().arguments().types().first().get());
        assertArrayType(t5g, t5c, t5r, ic.method("set5").get().arguments().types().first().get());
        
        // fields
        assertArrayType(t1g, t1c, t1r, ic.field("var1").get().type());
        assertArrayType(t2g, t2c, t2r, ic.field("var2").get().type());
        assertArrayType(t3g, t3c, t3r, ic.field("var3").get().type());
        assertArrayType(t4g, t4c, t4r, ic.field("var4").get().type());
        assertArrayType(t5g, t5c, t5r, ic.field("var5").get().type());
    }
    
    @Test
    public void testField() {
        IClass<?> ic = new TypeToken<Debug<String>>(){};
        assertEquals(ic.method("get1").get().returns(), ic.field("list1").get().type());
    }
    
    private static void assertArrayType(IClass<?> array, IClass<?> component, Class<?> raw, IClass<?> type) {
        assertEquals(array, type);
        assertEquals(raw, type.raw());
        assertEquals(component, type.component());
    }
    
    private static class Debug<R> {
        
        public List<R> list1;
        
        public List<R> get1() { return null; }
    }
    
    private static class IContainer<R> {
        
    }
    
    private static class Container<R> extends IContainer<R> {
        
        public Float[] var1;
        public List<Double>[] var2;
        public List<Map<? extends Number, String>>[] var3;
        public R[] var4;
        public Map<R,Short>[] var5;
        
        public Float[] get1() { return null; }
        
        public List<Double>[] get2() { return null; }
        
        public List<Map<? extends Number, String>>[] get3() { return null; }
        
        public R[] get4() { return null; }
        
        public Map<R,Short>[] get5() { return null; }
        
        public void set1(Float[] array) { }
        public void set2(List<Double>[] array) { }
        public void set3(List<Map<? extends Number, String>>[] array) { }
        public void set4(R[] array) { }
        public void set5(Map<R,Short>[] array) { }
        
    }
    
    
}
