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

import java.net.URI;
import java.util.Arrays;
import java.util.TreeMap;
import org.junit.Test;
import static net.ranides.assira.junit.NewAssert.*;
/**
 *
 * @author Ranides Atterwim <ranides@gmail.com>
 */
public class URIBuilderTest {
    
    @Test
    public void testParse_Scheme() {
        URIBuilder u1 = new URIBuilder("http://ranides.net/dir/main.html?action=open&art=55&now");
        assertEquals("http", u1.scheme());
        
        URIBuilder u2 = new URIBuilder("file:///home/ranides/.git");
        assertEquals("file", u2.scheme());
        
        URIBuilder u3 = new URIBuilder("code://path");
        assertEquals("code", u3.scheme());
    }

    @Test
    public void testParse_HTTP() {
        URIBuilder u1 = new URIBuilder("http://ranides.net/dir/main.html?action=open&art=55&now");
        assertEmpty(u1.login());
        assertEmpty(u1.password());
        assertEquals("ranides.net", u1.host());
        assertEmpty(u1.port());
        assertEquals("/dir/main.html", u1.path().get());
        assertEmpty(u1.fragment());
        assertEquals("{action=>open, art=>55, now=>}", u1.params().map().toString());
        assertEquals(Arrays.asList("open"), u1.param("action"));
        assertEquals(Arrays.asList(), u1.param("unknown"));
        assertEquals("http://ranides.net/dir/main.html?action=open&art=55&now", u1.build().toString());
        
        URIBuilder u2 = new URIBuilder("http://www.ranides.net/dir/page.html?");
        assertEquals("www.ranides.net", u2.host());
        assertEquals("/dir/page.html", u2.path().get());
        assertEmpty(u2.params().map());
        assertEquals("http://www.ranides.net/dir/page.html", u2.build().toString());
        
        URIBuilder u3 = new URIBuilder("http://login:pass@ranides.net:33/rest?action=open&action=write&action=save#top");
        assertEquals("login", u3.login().get());
        assertEquals("pass",u3.password().get());
        assertEquals("ranides.net", u3.host());
        assertEquals("33", u3.port().get());
        assertEquals("/rest", u3.path().get());
        assertEquals("top", u3.fragment().get());
        assertEquals("{action=>open, action=>write, action=>save}", u3.params().map().toString());
        assertEquals(Arrays.asList("open", "write", "save"), u3.param("action"));
        assertEquals(Arrays.asList(), u1.param("unknown"));
        assertEquals("http://login:pass@ranides.net:33/rest?action=open&action=write&action=save#top", u3.build().toString());
        
        URIBuilder u4 = new URIBuilder("http://login:pass@ranides.net:33");
        assertEquals("login", u4.login().get());
        assertEquals("pass",u4.password().get());
        assertEquals("ranides.net", u4.host());
        assertEquals("33", u4.port().get());
        assertEmpty(u4.path());
        assertEmpty(u4.fragment());
        assertEmpty(u4.params().map());
        assertEquals("http://login:pass@ranides.net:33", u4.build().toString());
    }
    
    @Test
    public void testResolve() {
        URIBuilder u1 = new URIBuilder()
            .scheme("jar")
            .host("{domain}.net")
            .login("user:{user}-{uid}")
            .password("h{pass}d")
            .fragment("{fragment}-ontop")
            .port("44")
            .param("action", "do-{action}-now")
            .path("home","dir","file.{ext}")
            .param("id", "5");
        
        u1.port("4{port}");
        URIBuilder u2 = u1.resolve(new Object(){
            String domain = "maven.ranides";
            String user = "login";
            String pass = "ello worl";
            String fragment = "art";
            String port = "7";
            String action = "show";
            String ext = "html";
        });
        assertEquals("jar://user:login-%7Buid%7D:hello%20world@maven.ranides.net:47/home/dir/file.html?action=do-show-now&id=5#art-ontop", u2.build().toString());
        
        u2.port(98);
        u2.path("root/home");
        u2.append("app", "config");
        u2.append("view.html");
        u2.param("list", Arrays.asList("1","2","3"));
        u2.params(new TreeMap<String,String>(){{
            put("zo","2");
            put("{key}","1 7");
            put("at","3");
        }});
        URI uri3 = u2.build(new Object(){
            String user = "EN";
            String uid = "AF";
            String key = "bc";
        });
        assertEquals("jar://user:login-AF:hello%20world@maven.ranides.net:98/root/home/app/config/view.html?action=do-show-now&id=5&list=1&list=2&list=3&at=3&zo=2&bc=1+7#art-ontop", uri3.toString());
    }
    
    @Test
    public void testUserInfo() {
        URIBuilder u1 = new URIBuilder()
            .scheme("ftp")
            .host("ranides.net")
            .login("user")
            .password("pass")
            .path("root/home");
        assertEquals("ftp://user:pass@ranides.net/root/home", u1.build().toString());
        u1.password(null);
        assertEquals("ftp://user@ranides.net/root/home", u1.build().toString());
        u1.login(null);
        assertEquals("ftp://ranides.net/root/home", u1.build().toString());
        u1.password("pass");
        assertThrows(IllegalArgumentException.class, ()->{
            u1.build().toString();
        });
    }
    
    @Test
    public void testParseError() {
        assertThrows(IllegalArgumentException.class, ()->{
            new URIBuilder("http://{host}.net");
        });
        assertThrows(IllegalArgumentException.class, ()->{
            new URIBuilder().scheme("http").host("{host}.net").build();
        });
    }
    
    @Test
    public void testParams() {
        URIBuilder u1 = new URIBuilder("http://host?a=1&a=2&a&b=3&b=4&c=5&c=6&d=7&e");
        assertEquals("http://host?a=1&a=2&a&b=3&b=4&c=5&c=6&d=7&e", u1.build().toString());
        
        assertTrue(u1.params().map().containsKey("a"));
        assertTrue(u1.params().map().containsKey("d"));
        assertTrue(u1.params().map().containsKey("e"));
        assertFalse(u1.params().map().containsKey("f"));
        
        assertTrue(u1.params().map().containsValue("1"));
        assertTrue(u1.params().map().containsValue("7"));
        assertFalse(u1.params().map().containsValue("a"));
        
        assertTrue(u1.params().multimap().containsEntry("a", "2"));
        assertFalse(u1.params().multimap().containsEntry("a", "12"));
        assertTrue(u1.params().multimap().containsEntry("d","7"));
        assertTrue(u1.params().multimap().containsEntry("e",""));
        assertFalse(u1.params().multimap().containsEntry("e",null));
        assertFalse(u1.params().multimap().containsEntry("f","0"));
        
        u1.params().remove("b");
        assertEquals("http://host?a=1&a=2&a&b=4&c=5&c=6&d=7&e", u1.build().toString());
        
        u1.params().remove("a","2");
        assertEquals("http://host?a=1&a&b=4&c=5&c=6&d=7&e", u1.build().toString());
        
        u1.params().removeAll("c");
        assertEquals("http://host?a=1&a&b=4&d=7&e", u1.build().toString());
        
    }
    
}
