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

/**
 *
 * @author Ranides Atterwim <ranides@gmail.com>
 */
public class AFieldsTest {
    
    private IClass<?> ic = IClass.typeinfo(ForFields.B.class);

    @Test
    public void testRequireAnnotation() {
        assertEquivalent(Arrays.asList("f1", "f2"), ic.fields().require(Deprecated.class).names());
        assertEquivalent(Arrays.asList("f2", "f3", "f4"), ic.fields().require(Meta.Final.class).names());
        assertEquivalent(Arrays.asList("f2"), ic.fields().require(IAnnotations.of(Deprecated.class, Meta.Final.class)).names());
    }
    
    @Test
    public void testDiscardAnnotation() {
        assertEquivalent(Arrays.asList("a", "a","a2", "c2", "f3", "f4"), ic.fields().discard(Deprecated.class).names());
        assertEquivalent(Arrays.asList("a", "a","a2", "c2", "f1"), ic.fields().discard(Meta.Final.class).names());
        assertEquivalent(Arrays.asList("a", "a","a2", "c2", "f4"), ic.fields().discard(IAnnotations.of(Deprecated.class, Meta.Final.class)).names());
    }
    
    @Test
    public void testRequireType() {
        assertEquivalent(Arrays.asList("a", "f1", "f2", "f3", "f4"), ic.fields().require(INT).names());
        assertEquivalent(Arrays.asList("a"), ic.fields().require(I_INTEGER).names());
        assertEquivalent(Arrays.asList("a", "c2"), ic.fields().require(I_NUMBER).names());
    }
    
    @Test
    public void testDiscardType() {
        assertEquivalent(Arrays.asList("a", "a2", "c2"), ic.fields().discard(INT).names());
        assertEquivalent(Arrays.asList("a", "a2", "c2", "f1", "f2", "f3", "f4"), ic.fields().discard(I_INTEGER).names());
        assertEquivalent(Arrays.asList("a", "a", "a2", "c2", "f1", "f2", "f3", "f4"), ic.fields().discard(NUMBER).names());
    }
    
    @Test
    public void testRequireAttr() {
        assertEquivalent(Arrays.asList("a", "a", "a2", "c2", "f1", "f2", "f3", "f4"), ic.fields().require(collect(PUBLIC)).names());
        assertEquivalent(Arrays.asList("b","b", "b2"), ic.fields().require(collect(PROTECTED)).names());
    }
    
    @Test
    public void testDiscardAttr() {
        assertEquiList(Arrays.asList("c2", "f1", "f4"), ic.fields().discard(TRANSIENT).names());
        assertEquiList(Arrays.asList("b","b", "c", "c", "b2"), ic.fields().discard(PUBLIC).names());
        
        assertEquiList(Arrays.asList("c2", "f1", "f4"), ic.fields().discard(collect(TRANSIENT)).names());
        assertEquiList(Arrays.asList("b","b", "c", "c", "b2"), ic.fields().discard(collect(PUBLIC)).names());
        assertEquiList(Arrays.asList("b","b", "c", "c", "b2", "c2", "f1", "f4"), ic.fields().discard(collect(TRANSIENT, PUBLIC)).names());
    }
    
    @Test
    public void testReflective() {
        assertEquiList(Arrays.asList("c2", "f1", "f4"), ic.fields().discard(TRANSIENT).reflective().map(Field::getName).list());
        assertEquiList(Arrays.asList("b","b", "c", "c", "b2"), ic.fields().discard(PUBLIC).reflective().map(Field::getName).list());
        
        assertEquiList(Arrays.asList("c2", "f1", "f4"), ic.fields().discard(collect(TRANSIENT)).reflective().map(Field::getName).list());
    }
    
    @Test
    public void testDiscardName() {
        assertEquiList(Arrays.asList("c", "c", "b2"), ic.fields().discard(PUBLIC).discard("b").names());
        assertEquiList(Arrays.asList("b","b", "b2"), ic.fields().discard(PUBLIC).discard("c").names());
    }
    
    @Test
    public void testTypes() {
        assertEquivalent(Arrays.asList(INT, I_INTEGER), ic.fields().require("a").type().list());
        assertEquivalent(Arrays.asList(CHARSEQUENCE, INT), ic.fields().require(PROTECTED).require("b").type().list());
        assertEquivalent(Arrays.asList(), ic.fields().require("q").type().list());
    }
    
    
    @Test
    public void testParent() {
        assertEquivalent(Arrays.asList(ForFields.B.class, ForFields.A.class), ic.fields().require("a").parent().reflective().list());
    }
    
    private static void assertEquiList(List<String> expected, List<String> values) {
        while(values.remove("$jacocoData")) { }
        assertEquivalent(expected, values);
    }
    
}
