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

import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import javax.xml.transform.TransformerConfigurationException;
import net.ranides.assira.collection.maps.MultiMap;
import static net.ranides.assira.junit.NewAssert.*;
import org.junit.Test;

/**
 *
 * @author Ranides Atterwim <ranides@gmail.com>
 */
@SuppressWarnings("PMD.AvoidDuplicateLiterals")
public class XMLQueryTest {
    
    @Test
    public void testRoot() throws IOException {
        XMLElement doc = XMLQuery.$(new File("src/test/resources/eclipse/artifacts.xml"));
        
        List<String> root = Arrays.asList("artifactRepository", "configuration", "repository");
        List<String> body = Arrays.asList("#text", "properties", "#text", "mappings", "#text", "artifacts", "#text");
        List<String> items = Arrays.asList("properties", "mappings", "artifacts");
        
        assertEquals(root.subList(0, 3), doc.children().names());
        assertEquals(root.subList(0, 2), doc.children(XMLType.PROCESSING).names());
        assertEquals(root.subList(2, 3), doc.children(XMLType.ELEMENT).names());
        
        assertEquals(body, doc.root().children().names());
        assertEquals(items, doc.root().children(XMLType.ELEMENT).names());
        
        assertEquals("repository", doc.root().name());
    }
    
    @Test
    public void testFindStar() throws IOException {
        XMLElement doc = XMLQuery.$(new File("src/test/resources/eclipse/artifacts.xml"));
        
        assertEquals(3395, doc.find("*").size());
        assertEquals(3394, doc.root().find("*").size());
        
        assertEquals(2378, doc.find("artifact *").size());
        assertEquals(2378, doc.find("artifact").find("*").size());
        assertEquals(4, doc.find("? //artifact[1]").find("*").size());
    }
    
    @Test
    public void testXPath() throws IOException {
        XMLElement doc = XMLQuery.$(new File("src/test/resources/eclipse/artifacts.xml"));
        
        List<String> exp1 = Arrays.asList("plugins.jar", "binary.jar", "features.jar");
        
        assertEquals(exp1, doc.find("? //mappings/rule/@output").texts());
        assertEquals(exp1, doc.find("? /repository/mappings/rule/@output").texts());
    }
    
    @Test
    public void testCSS() throws IOException {
        XMLElement doc = XMLQuery.$(new File("src/test/resources/eclipse/artifacts.xml"));
        
        XMLElements css = doc.find("artifact property[name='download.size']").attrs("value");
        
        assertEquals(1008, css.size());
        
        List<Integer> numbers = Arrays.asList(26817, 159306, 48552, 48832, 731290, 12166, 18032, 150535);
        
        assertEquals(numbers, css.stream(this::$int).filter(v -> 0 == v%7).limit(8).list());
    }

    private int $int(XMLElement n) throws NumberFormatException {
        return Integer.parseInt(n.content());
    }
    
    @Test
    public void testChildren() throws IOException {
        XMLElement doc = XMLQuery.$(new File("src/test/resources/eclipse/artifacts.xml"));
        
        assertFalse(doc.children("xxx").matches());
        assertFalse(doc.children("mappings").matches());
        assertFalse(doc.children(" mappings").matches());
        assertFalse(doc.children("mappings rule").matches());
        
        assertEquals(0, doc.find("xxx").size());
        assertEquals(1, doc.find("mappings").size());
        assertEquals(1, doc.find(" mappings").size());
        assertEquals(3, doc.find("mappings rule").size());
    }
        
    
    @Test
    public void testAttrMap() throws IOException {
        XMLElement doc = XMLQuery.$(new File("src/test/resources/eclipse/artifacts.xml"));

        assertTrue(doc.children("mappings rule").attrs().map().isEmpty());
        
        MultiMap<String, String> attr = doc.find("mappings rule").attrs().map();

        List<String> exp1 = Arrays.asList("A","B","C");
        List<String> exp2 = Arrays.asList("plugins.jar", "binary.jar", "features.jar");
        
        assertEquivalent(exp1, attr.getAll("filter"));
        assertEquivalent(exp2, attr.getAll("output"));
    }
    
    @Test
    public void testAttributes() throws IOException, TransformerConfigurationException {
        XMLElement doc = XMLQuery.$(new File("src/test/resources/eclipse/artifacts.xml"));
        
        XMLElement attr1 = doc.find("repository mappings rule").attrs("output").first();
        XMLElement attr2 = doc.find("repository mappings rule").attrs().first("output");
        
        assertSame(attr1.node(), attr2.node());
        
        assertEquals("output", attr1.name());
        assertEquals("plugins.jar", attr1.content());
        assertEquals("plugins.jar", attr1.text());
        assertEquals("plugins.jar", attr1.get());
        assertEquals("rule", attr1.parent().name());
        assertEquals(Arrays.asList(), attr1.attrs().names());
        assertEquals(Arrays.asList(), attr1.parent().children().names());
        assertEquals(Arrays.asList("filter","output"), attr1.parent().attrs().names());
        assertEquals(Arrays.asList("output", "rule", "mappings", "repository", "#document"), attr1.parents().names());
    }
    
}
