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

import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.io.IOException;
import java.util.AbstractMap;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import net.ranides.assira.TestFiles;
import net.ranides.assira.collection.maps.MultiMap;
import net.ranides.assira.xml.XMLElement;
import net.ranides.assira.xml.XMLElements;
import static net.ranides.assira.junit.NewAssert.*;
import net.ranides.assira.text.Charsets;
import net.ranides.assira.text.IOStrings;
import net.ranides.assira.xml.XMLSelector;
import org.junit.Test;
import org.w3c.dom.Node;
import static net.ranides.assira.xml.XMLElement.$;


/**
 *
 * @author Ranides Atterwim <ranides@gmail.com>
 */
@SuppressFBWarnings("GC_UNRELATED_TYPES")
public class W3AttributesTest {
    
    @Test
    public void testText() {
        XMLElement doc = $(TestFiles.XML_INPUT).normalize();
        XMLElements attr = doc.find("user").first().attrs();
        
        assertEquals(4, attr.size());
        
        List<String> nodes = attr.nodes().stream().map(Node::getTextContent).collect(Collectors.toList());
        assertEquivalent(Arrays.asList("true", "101", "true", "5461"), nodes);
        assertEquivalent(Arrays.asList("true", "101", "true", "5461"), attr.contents());
        assertEquivalent(Arrays.asList("true", "101", "true", "5461"), attr.texts());
        
        assertEquals(0, attr.attrs().size());
        assertEquals(0, attr.attrs("name").size());
    }
    
    @Test
    public void testChildren() {
        XMLElement doc = $(TestFiles.XML_INPUT).normalize();
        XMLElements attr = doc.find("user").first().attrs();
        
        assertEquivalent(Arrays.asList("true", "101", "true", "5461"), attr.children().texts());
        assertEquivalent(Arrays.asList("id", "uid", "active", "public"), attr.children().names());
        assertEquivalent(Arrays.asList("id", "uid", "active", "public"), attr.children(n->true).names());
        
        assertEquals("5461", attr.children(XMLSelector.compile("uid")).text());
        assertEquals("5461", attr.children("uid").text());
        assertEquals("5461", attr.children(n->n.node().name().equals("uid")).text());
    }
    
    @Test
    public void testFirst() {
        XMLElement doc = $(TestFiles.XML_INPUT).normalize();
        XMLElements attr = doc.find("user").first().attrs();

        assertEquals("5461", attr.first(XMLSelector.compile("uid")).text());
        assertEquals("5461", attr.first("uid").text());
        assertEquals("5461", attr.first(n->n.node().name().equals("uid")).text());
    }
    
    @Test
    public void testHas() {
        XMLElement doc = $(TestFiles.XML_INPUT).normalize();
        XMLElements attr = doc.find("user").first().attrs();

        assertTrue( attr.has());
        assertTrue( attr.has(XMLSelector.compile("uid")));
        assertTrue( attr.has("uid"));
        assertTrue( attr.has(n->n.node().name().equals("uid")));
    }
    
    @Test
    public void testMap() throws IOException {
        XMLElement doc = $(TestFiles.XML_INPUT).normalize();
        MultiMap<String, String> attrs = doc.find("user").first().attrs().map();
        
        // uwaga! wiemy, że zepsute. unfolduje pola, ma złą semantykę a na dodatek złe wyniki daje
        // (przestarzałe)
        MultiMap<String, String> allmap = doc.find("user").attrs().map();
        
        assertEquals(null, attrs.put("ban", "false"));
        assertEquals("101", attrs.put("id", "777"));
        
        assertEquals("5461", attrs.remove("uid"));
        assertEquals(null, attrs.remove("uid"));
        assertEquals(null, attrs.remove(667));
        
        assertEquivalent(Arrays.asList("active","ban","id","public"), attrs.keySet());
        assertEquivalent(Arrays.asList("true","true","false","777"), attrs.values());
        
        assertEquals("777", attrs.get("id"));
        assertEquals(null, attrs.get("hash"));
        assertEquals(null, attrs.get(999));
        
        assertTrue(attrs.containsKey("id"));
        assertFalse(attrs.containsKey("hash"));
        assertFalse(attrs.containsKey(999));
        
        assertEquivalent(Arrays.asList("777"), attrs.getAll("id"));
        assertEquivalent(Arrays.asList("false"), attrs.getAll("ban"));
        assertEquivalent(Arrays.asList(), attrs.getAll("hash"));
        assertEquivalent(Arrays.asList(), attrs.getAll(999));
        
        assertTrue(attrs.entrySet().contains(new AbstractMap.SimpleEntry<>("id","777")));
        assertFalse(attrs.entrySet().contains(new AbstractMap.SimpleEntry<>("id","888")));
        assertFalse(attrs.entrySet().contains(new AbstractMap.SimpleEntry<>("hash","777")));
        assertFalse(attrs.entrySet().contains("ddd"));
        
        assertTrue(attrs.containsValue("777"));
        assertFalse(attrs.containsValue("101"));
        
        assertEquals("777", allmap.get("id"));
        assertEquals("false", allmap.get("ban"));
        
        allmap.put("extra", "19");
        
        assertEquivalent(Arrays.asList("777","102","103","104","105"), allmap.getAll("id"));
        assertEquivalent(Arrays.asList("false"), allmap.getAll("ban"));
        assertEquivalent(Arrays.asList(), allmap.getAll("hash"));
        assertEquivalent(Arrays.asList(), allmap.getAll(888));
        
        String out = doc.find("users").first().writer().indent(4).toString();
        String exp = IOStrings.read(TestFiles.XML_ATTR, Charsets.UTF8);
        assertEquals(exp, out);
    }
    
}
