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

import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.dom.DOMResult;
import net.ranides.assira.TestFiles;
import net.ranides.assira.reflection.IClass;
import net.ranides.assira.text.Charsets;
import net.ranides.assira.text.IOStrings;
import net.ranides.assira.xml.XMLElement;
import net.ranides.assira.xml.XMLException;
import net.ranides.assira.xml.XMLSelector;
import org.junit.Test;
import static net.ranides.assira.junit.NewAssert.*;
import static net.ranides.assira.xml.XMLElement.$;

/**
 *
 * @author Ranides Atterwim <ranides@gmail.com>
 */
public class W3ElementTest {
    
    @Test
    public void testWrapper() throws IOException {
        XMLElement doc = $(TestFiles.XML_INPUT);
        XMLElement user = doc.find("? //user[1]/@id").first();
        
        assertEquals("101", user.get());
        assertEquals(IClass.typeinfo(String.class), user.type());
        user.set("10166");
        
        assertEquals(IOStrings.read(TestFiles.XML_5, Charsets.UTF8), user.parent().normalize().writer().indent(4).toString());
    }
    
    @Test
    public void testHas() {
        XMLElement doc = $(TestFiles.XML_INPUT).normalize();
        assertTrue(doc.find("user").first().has());
        assertTrue(doc.find("user login").first().has());
        assertFalse(doc.find("data item").first().has());
        
        assertTrue(doc.find("user").first().has("login"));
        assertFalse(doc.find("user login").first().has("login"));
        assertFalse(doc.find("user").first().has("xxxx"));
    }
    
    @Test
    public void testNext() {
        XMLElement doc = $(TestFiles.XML_INPUT).normalize();
        List<String> exp = Arrays.asList("ranides@ccms.net", "contact@ranides.net");
        
        assertEquals("password", doc.find("user login").first().next().name());
        assertEquals(exp, doc.find("user login").first().next("mail").texts());
    }
 
    @Test
    public void testSiblinngs() {
        XMLElement doc = $(TestFiles.XML_INPUT).normalize();
        List<String> exp1 = Arrays.asList("login", "name", "mail", "mail");
        List<String> exp2 = Arrays.asList("ranides@ccms.net", "contact@ranides.net");
        
        assertEquals(exp1, doc.find("user password").first().siblings().names());
        assertEquals(exp2, doc.find("user password").first().siblings("mail").texts());
    }
 
    @Test
    public void testPrev() {
        XMLElement doc = $(TestFiles.XML_INPUT).normalize();
        List<String> exp = Arrays.asList("ranides");
        
        assertEquals("password", doc.find("user name").first().prev().name());
        assertEquals(exp, doc.find("user name").first().prev("login").texts());
    }

    @Test
    public void testParents() {
        XMLElement doc = $(TestFiles.XML_INPUT).normalize();
        
        assertEquals(Arrays.asList("user", "users", "ccms", "#document"), doc.find("user name").first().parents().names());
        assertEquals(Arrays.asList("user"), doc.find("user name").first().parents("[id]").names());
        assertEquals(Arrays.asList("ccms"), doc.find("user name").first().parents("ccms").names());
    }
    
    @Test
    public void testSelectors() {
        XMLElement doc = $(TestFiles.XML_INPUT).normalize();
        
        XMLSelector xs1 = XMLSelector.css("user");
        XMLSelector xs2 = XMLSelector.xpath("//user");
        
        assertEquals(doc.find(xs1).nodes(), doc.find(xs2).nodes());
    }
    
    @Test
    public void testTransform() throws TransformerConfigurationException, TransformerException, IOException {
        XMLElement doc = $(TestFiles.XML_INPUT);
        String exp1 = IOStrings.read(TestFiles.XML_USERS, Charsets.UTF8);
        
        XMLElement out = doc.apply($(TestFiles.XSL_USERS));
        XMLElement dom = $(doc.apply($(TestFiles.XSL_USERS), new DOMResult()).getNode());
        
        String sout = out.writer().indent(4).toString();
        String sdom = dom.writer().indent(4).toString();
        
//        System.out.printf("%s%n", sout);
        
        assertEquals(exp1, sout);
        assertEquals(exp1, sdom);
        
        assertThrows(XMLException.class, ()->{
            doc.apply($(TestFiles.XML_1));
        });
        assertThrows(XMLException.class, ()->{
            doc.apply($(TestFiles.XML_1), new DOMResult());
        });
    }
    
    @Test
    public void testXPath() {
        XMLElement doc = $(TestFiles.XML_INPUT).normalize();
        
        assertEquals("/ccms/users/user", doc.find("user[id=\"101\"]").first().xpath() );
        assertEquals("/ccms/users/user[2]", doc.find("user[id=\"102\"]").first().xpath() );
        assertEquals("/ccms/users/user[3]", doc.find("user[id=\"103\"]").first().xpath() );
        
        assertEquals("/ccms/users/user[4]/mail[2]", doc.find("user[id=\"104\"] mail[type=\"private\"]").first().xpath() );
        assertEquals("/ccms/users/user[4]/mail[2]/@type", doc.find("user[id=\"104\"] mail[type=\"private\"]").first().attr("type").xpath() );
    }
    
    protected int position(XMLElement node) {
        return node.prev(node.name()).size();
    }
    
    
}
