package com.atlassian.bitbucket.content;

import org.junit.Assert;
import org.junit.Test;

import static org.junit.Assert.*;

public class SimplePathTest {

    @Test
    public void testName() {
        Assert.assertEquals("", SimplePath.ROOT.getName());
        assertEquals("a", new SimplePath("a").getName());
        assertEquals("a", new SimplePath("d/a").getName());
    }

    @Test
    public void testGetParent() {
        assertEquals(null, SimplePath.ROOT.getParent());
        assertEquals("", new SimplePath("a").getParent());
        assertEquals("d", new SimplePath("d/a").getParent());
        assertEquals("d/a", new SimplePath("d/a/f").getParent());
    }

    @Test
    public void testGetParentPath() {
        assertEquals(null, SimplePath.ROOT.getParentPath());
        assertEquals(SimplePath.ROOT, new SimplePath("a").getParentPath());
        assertEquals(new SimplePath("d"), new SimplePath("d/a").getParentPath());
        assertEquals(new SimplePath("d/a"), new SimplePath("d/a/f").getParentPath());
    }

    @Test
    public void testGetPath() {
        assertEquals("", SimplePath.ROOT.getPath());
        assertEquals("a", new SimplePath("a").getPath());
        assertEquals("D/a", new SimplePath("D/a").getPath());
        assertEquals("D/a", new SimplePath("D/a").getPath(true));
        assertEquals("d/a", new SimplePath("D/a").getPath(false));
        assertEquals("d/a/f", new SimplePath("d/a/f").getPath());
    }

    @Test
    public void testPaths() {
        assertTrue("'' is root", new SimplePath("").isRoot());
        assertTrue("'/' is root", new SimplePath("/").isRoot());
        assertEquals(new SimplePath("/"), new SimplePath(""));
    }

    @Test
    public void testWindowsPath() {
        SimplePath p = new SimplePath("hello\\there");
        assertEquals(1, p.getComponents().length);

        p = new SimplePath("hello\\there", true);
        assertEquals(2, p.getComponents().length);

        p = new SimplePath("\\hello\\there", true);
        assertEquals(3, p.getComponents().length);

        SimplePath p2 = new SimplePath(p, "foo", true);
        assertEquals(4, p2.getComponents().length);

        p2 = new SimplePath(p, "foo\\bar", true);
        assertEquals(5, p2.getComponents().length);
    }

    @Test
    public void testAbbrev() {
        assertAbbrev("the/brown", "the/brown", 5);
        assertAbbrev("the/.../brown", "the/quick/brown", 5);
        assertAbbrev("the/.../brown", "the/quic1/quic2/brown", 5);
        assertAbbrev("the/.../brown", "the/quic1/very/quic2/brown", 5);

        assertAbbrev("the/quic1/.../quic2/brown", "the/quic1/very/quic2/brown", 21);
        assertAbbrev("longdir/dir1/the/quick/brown/.../blah/foo/bar/file.txt",
                "longdir/dir1/the/quick/brown/fox/jumps/over/the/lazy/dog/too/many/cooks/spoil/the/broth/blah/foo/bar/file.txt", 50);
    }

    private static void assertAbbrev(String expected, String input, int maxlen) {
        assertEquals(expected, new SimplePath(input).abbreviate(maxlen).getPath());
    }

    @Test
    public void testJoin() {
        assertEquals("", SimplePath.join("", ""));
        assertEquals("/", SimplePath.join("/", ""));
        assertEquals("/", SimplePath.join("", "/"));
        assertEquals("/", SimplePath.join("/", "/"));

        assertEquals("asd", SimplePath.join("asd", ""));
        assertEquals("asd/", SimplePath.join("asd", "/"));
        assertEquals("asd", SimplePath.join("", "asd"));
        assertEquals("/asd", SimplePath.join("/", "asd"));

        assertEquals("asd/asd", SimplePath.join("asd", "asd"));
        assertEquals("asd/asd", SimplePath.join("asd/", "asd"));
        assertEquals("asd/asd", SimplePath.join("asd", "/asd"));
        assertEquals("asd/asd", SimplePath.join("asd/", "/asd"));
    }

    @Test
    public void testAncestor() {
        assertTrue(new SimplePath("/").isAncestor(new SimplePath("/blah")));
        assertFalse(new SimplePath("/blah").isAncestor(new SimplePath("/blah")));
        assertTrue(new SimplePath("/blah").isAncestor(new SimplePath("/blah/blah")));
        assertFalse(new SimplePath("/").isAncestor(new SimplePath("/")));
        assertFalse(new SimplePath("").isAncestor(new SimplePath("/")));
    }

    @Test
    public void testExtension() {
        assertEquals("txt", new SimplePath("file.txt").getExtension());
        assertEquals("java", new SimplePath("file.txt.java").getExtension());
        assertEquals(null, new SimplePath("file").getExtension());
        assertEquals(null, new SimplePath("file.").getExtension());
    }

    /*
    TODO: fix path getRelativePath
    @Test
    public void testRelativePathNoCommonRoot() {
        testRelativePath(null, "1/2/3/4/5", "6/7/");
    }
    */

    @Test
    public void testSimplify() {
        assertEquals(new SimplePath("a/b/c"), new SimplePath("a/b/c").simplify());
        assertEquals(new SimplePath("a/b/c"), new SimplePath("a/./b/c").simplify());
        assertEquals(new SimplePath("a/b/c"), new SimplePath("./a/b/c").simplify());
        assertEquals(new SimplePath("a/b/c"), new SimplePath("a/b/c/.").simplify());
        assertEquals(new SimplePath("a/b"), new SimplePath("a/b/c/..").simplify());
        assertEquals(new SimplePath("a/b"), new SimplePath("a/b/c/..").simplify());
        assertEquals(new SimplePath("a"), new SimplePath("a/b/c/../..").simplify());
        assertEquals(new SimplePath("a/c"), new SimplePath("a/b/../c").simplify());
        assertEquals(new SimplePath("c"), new SimplePath("a/b/../../c").simplify());
        assertEquals(new SimplePath("a/b"), new SimplePath("a/././b/c/..").simplify());
        assertEquals(new SimplePath(""), new SimplePath("a/././..").simplify());
    }

    @Test
    public void testOversimplify() {
        assertEquals(new SimplePath(".."), new SimplePath("a/../..").simplify());
        assertEquals(new SimplePath(".."), new SimplePath("a/./.././..").simplify());
    }
    
    @Test
    public void testTrimFirst() {
        assertEquals(new SimplePath("b/c"), new SimplePath("a/b/c").trimFirst());
        assertEquals(SimplePath.ROOT, SimplePath.ROOT.trimFirst());

        assertEquals(new SimplePath("c"), new SimplePath("a/b/c").trimFirst(2));
        assertEquals(SimplePath.ROOT, SimplePath.ROOT.trimFirst(2));

        assertEquals(SimplePath.ROOT, new SimplePath("a/b/c").trimFirst(4));
    }

    @Test
    public void testTrimLast() {
        assertEquals(new SimplePath("a/b"), new SimplePath("a/b/c").trimLast());
        assertEquals(new SimplePath("a"), new SimplePath("a/b").trimLast());
        assertEquals(SimplePath.ROOT, new SimplePath("a").trimLast());
        assertEquals(SimplePath.ROOT, SimplePath.ROOT.trimLast());
    }
    
    @Test
    public void testCommonRoot() {
        assertEquals(new SimplePath("a/b"), new SimplePath("a/b/c/d/e").getCommonRoot(new SimplePath("a/b/q/d")));
        assertEquals(SimplePath.ROOT, new SimplePath("a/b/c/d/e").getCommonRoot(new SimplePath("w/b/c/d")));
    }
    
    @Test
    public void testHasPrefix() {
        assertTrue(new SimplePath("a/b/c").hasPrefix(null));
        assertTrue(new SimplePath("a/b/c").hasPrefix(SimplePath.ROOT));
        assertTrue(new SimplePath("a/b/c").hasPrefix(new SimplePath("a/")));
        assertTrue(new SimplePath("a/b/c").hasPrefix(new SimplePath("a/b")));
        assertFalse(new SimplePath("a/b/c").hasPrefix(new SimplePath("a/b/c/d")));
        assertFalse(new SimplePath("b/c").hasPrefix(new SimplePath("a/b")));
    }
    
    @Test
    public void testCompareTo() {
        assertEquals(0, SimplePath.ROOT.compareTo(SimplePath.ROOT));
        assertTrue(SimplePath.ROOT.compareTo(new SimplePath("a")) < 0);
        assertTrue(new SimplePath("a").compareTo(SimplePath.ROOT) > 0);
    }
    
}
