package net.onrc.onos.apps.bgproute;

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

public class PatriciaTrieTest {

    IPatriciaTrie<RibEntry> ptrie;
    Prefix[] prefixes;
    Map<Prefix, RibEntry> mappings;

    @Before
    public void setUp() throws Exception {
        ptrie = new PatriciaTrie<RibEntry>(32);
        mappings = new HashMap<Prefix, RibEntry>();

        prefixes = new Prefix[]{
                new Prefix("192.168.10.0", 24),
                new Prefix("192.168.8.0", 23),
                new Prefix("192.168.8.0", 22),
                new Prefix("192.0.0.0", 7),
                new Prefix("192.168.11.0", 24),
                new Prefix("10.0.23.128", 25),
                new Prefix("206.17.144.0", 20),
                new Prefix("9.17.0.0", 12),
                new Prefix("192.168.0.0", 16)
        };

        for (int i = 0; i < prefixes.length; i++) {
            mappings.put(prefixes[i], new RibEntry("192.168.10.101", "192.168.20." + i));
            ptrie.put(prefixes[i], new RibEntry("192.168.10.101", "192.168.20." + i));
        }
    }

    @After
    public void tearDown() throws Exception {
    }

    @Test
    public void testPut() {
        IPatriciaTrie<RibEntry> ptrie = new PatriciaTrie<RibEntry>(32);

        Prefix p1 = new Prefix("192.168.240.0", 20);
        RibEntry r1 = new RibEntry("192.168.10.101", "192.168.60.2");
        RibEntry retval = ptrie.put(p1, r1);
        assertNull(retval);
        retval = ptrie.lookup(p1);
        assertTrue(r1 == retval); //should be the same object

        Prefix p2 = new Prefix("192.160.0.0", 12);
        RibEntry r2 = new RibEntry("192.168.10.101", "192.168.20.1");
        retval = ptrie.put(p2, r2);
        assertNull(retval);

        Prefix p3 = new Prefix("192.168.208.0", 20);
        RibEntry r3 = new RibEntry("192.168.10.101", "192.168.30.1");
        retval = ptrie.put(p3, r3);
        assertNull(retval);

        //Insert a new RibEntry entry over a previous one
        RibEntry r3new = new RibEntry("192.168.10.101", "192.168.60.2");
        retval = ptrie.put(p3, r3new);
        assertNotNull(retval);
        assertTrue(retval.equals(r3));
        assertTrue(retval == r3); //should be the same object

        //Now we have an aggregate node with prefix 192.168.192.0/18.
        //We will insert a RibEntry at this prefix
        Prefix p4 = new Prefix("192.168.192.0", 18);
        RibEntry r4 = new RibEntry("192.168.10.101", "192.168.40.1");
        retval = ptrie.put(p4, r4);
        assertNull(retval);
        retval = ptrie.lookup(p4);
        assertTrue(retval == r4); //should be the same object
    }

    @Test
    public void testLookup() {
        for (Map.Entry<Prefix, RibEntry> entry : mappings.entrySet()) {
            RibEntry r = ptrie.lookup(entry.getKey());
            assertTrue(entry.getValue().equals(r));
        }

        //These are aggregate nodes in the tree. Shouldn't be returned by lookup
        Prefix p1 = new Prefix("0.0.0.0", 0);
        RibEntry retval = ptrie.lookup(p1);
        assertNull(retval);

        //We'll put a RibEntry at an aggregate node and check if lookup returns correctly
        Prefix p2 = new Prefix("192.0.0.0", 4);
        RibEntry r2 = new RibEntry("192.168.10.101", "192.168.60.1");
        retval = ptrie.put(p2, r2);
        assertNull(retval);
        retval = ptrie.lookup(p2);
        assertTrue(retval.equals(r2));
    }

    //@Ignore
    @Test
    public void testMatch() {
        Prefix p1 = new Prefix("192.168.10.30", 32);
        Prefix p2 = new Prefix("192.168.10.30", 31);
        Prefix p3 = new Prefix("192.168.8.241", 32);
        Prefix p4 = new Prefix("1.0.0.0", 32);
        Prefix p5 = new Prefix("192.168.8.0", 22);
        Prefix p6 = new Prefix("192.168.8.0", 21);

        assertTrue(ptrie.match(p1).equals(mappings.get(prefixes[0])));
        assertTrue(ptrie.match(p2).equals(mappings.get(prefixes[0])));
        assertTrue(ptrie.match(p3).equals(mappings.get(prefixes[1])));
        assertNull(ptrie.match(p4));
        assertTrue(ptrie.match(p5).equals(mappings.get(prefixes[2])));
        //System.out.println(ptrie.match(p6).getNextHop().getHostAddress());
        assertTrue(ptrie.match(p6).equals(mappings.get(prefixes[8])));


        //TODO more extensive tests
        //fail("Not yet implemented");
    }

    @Test
    public void testRemove() {
        Prefix p1 = new Prefix("192.168.8.0", 23);
        RibEntry retval = ptrie.lookup(p1);
        assertNotNull(retval);
        boolean success = ptrie.remove(p1, retval);
        assertTrue(success);

        Prefix p2 = new Prefix("192.168.8.0", 22);
        Prefix p3 = new Prefix("192.168.10.0", 24);

        //Test it does the right thing with null arguments
        success = ptrie.remove(null, null);
        assertFalse(success);
        success = ptrie.remove(p2, null);
        assertFalse(success);

        //Check other prefixes are still there
        retval = ptrie.lookup(p2);
        assertNotNull(retval);
        retval = ptrie.lookup(p3);
        assertNotNull(retval);

        Prefix p4 = new Prefix("9.17.0.0", 12);
        retval = ptrie.lookup(p4);
        assertNotNull(retval);
        success = ptrie.remove(p4, retval);
        assertTrue(success);
        success = ptrie.remove(p4, retval);
        assertFalse(success);

        //Check other prefixes are still there
        retval = ptrie.lookup(p2);
        assertNotNull(retval);
        retval = ptrie.lookup(p3);
        assertNotNull(retval);

        Prefix p5 = new Prefix("192.0.0.0", 7);
        retval = ptrie.lookup(p5);
        assertNotNull(retval);
        success = ptrie.remove(p5, retval);
        assertTrue(success);

        //Check other prefixes are still there
        retval = ptrie.lookup(p2);
        assertNotNull(retval);
        retval = ptrie.lookup(p3);
        assertNotNull(retval);


    }

    @Test(expected = java.util.NoSuchElementException.class)
    public void testIterator() {
        int[] order = new int[]{7, 5, 3, 8, 2, 1, 0, 4, 6};

        Iterator<IPatriciaTrie.Entry<RibEntry>> it = ptrie.iterator();
        int i = 0;
        assertTrue(it.hasNext());
        while (it.hasNext()) {
            IPatriciaTrie.Entry<RibEntry> entry = it.next();
            assertTrue(entry.getPrefix().equals(prefixes[order[i]]));
            i++;
        }
        assertFalse(it.hasNext());
        assertTrue(i == order.length);

        IPatriciaTrie<RibEntry> pt = new PatriciaTrie<RibEntry>(32);
        Iterator<IPatriciaTrie.Entry<RibEntry>> it2 = pt.iterator();
        assertFalse(it2.hasNext());
        it.next(); //throws NoSuchElementException
    }

}
