package io.prelink.critbit;

import io.prelink.critbit.CritBitTree;
import io.prelink.critbit.MCritBitTree;

import java.util.HashMap;
import java.util.Map;
import java.util.Random;

import org.apache.commons.lang.RandomStringUtils;
import org.apache.commons.lang.math.RandomUtils;

//import org.ardverk.collection.PatriciaTrie;
//import org.ardverk.collection.StringKeyAnalyzer;

public class PatriciaTrieTest {
    private static final int WARMUPS = 1000;
    private static final int ITERS = 50000;
    private static final int SEED = 42;

    private static interface Putter {
        String name();
        void put(String key, String val);
    }
    private static String randomString(Random rand) {
        int len = RandomUtils.nextInt(rand, 100) + 1;
        return RandomStringUtils.random(len, 0, 0, false, false, null, rand);
    }
    private static void putTest(Putter p) {
        Random rand = new Random(SEED);
        System.out.print("Warming up " + p.name() + "... ");
        for(int i=0; i<WARMUPS; i++) {
            String key = randomString(rand);
            p.put(key, ""+i);
        }
        System.out.println("Done!");
        System.out.print(String.format("Starting test for %s...", p.name()));
        final long start = System.currentTimeMillis();
        for(int i=0; i<ITERS; i++) {
            String key = RandomStringUtils.random(RandomUtils.nextInt(100) + 1);
            p.put(key, ""+i);
        }
        final long end = System.currentTimeMillis();
        System.out.println(
            String.format("Done! Put %s keys in %s ms", ITERS, end-start));

        p.put("", "nothing");
        p.put("", "nothingelse");
        p.put("something", "something");
        p.put("something", "somethingelse");
    }

    private static class FCBFlipper {
        //Since FCB is purely functional, this helper class will handle
        //tracking the current FCB.
        private CritBitTree<String,String> fcb;
        public FCBFlipper() {
            this.fcb = new CritBitTree<String, String>(new StringBitChecker());
        }
        public void put(String key, String val) {
            this.fcb = fcb.put(key, val);
        }
    }

    public static void main(final String[] args) throws Exception {

        final Map<String, String> hm = new HashMap<String, String>();
        putTest(new Putter() {
            public String name() { return "HashMap"; }
            public void put(String k, String v) { hm.put(k, v); }
        });

        final Map<String, String> pshm =
            new HashMap<String, String>(WARMUPS+ITERS);
        putTest(new Putter() {
            public String name() { return "Presized HashMap"; }
            public void put(String k, String v) { pshm.put(k, v); }
        });

        final FCBFlipper fcb = new FCBFlipper();
        putTest(new Putter() {
            public String name() { return "Functional Crit Bit"; }
            public void put(String k, String v) { fcb.put(k, v); }
        });

        final MCritBitTree<String, String> mcb =
            new MCritBitTree<String, String>(new StringBitChecker());
        putTest(new Putter() {
            public String name() { return "Mutable Crit Bit"; }
            public void put(String k, String v) { mcb.put(k, v); }
        });

//      final PatriciaTrie<String, String> ptrie =
//          new PatriciaTrie<String, String>(StringKeyAnalyzer.INSTANCE);
//      putTest(new Putter() {
//          public String name() { return "Patricia Trie"; }
//          public void put(String k, String v) { ptrie.put(k, v); }
//      });



        //Give us a chance to look at the heap.
        for(int i=0;i<Integer.MAX_VALUE;i++) Thread.sleep(1000);

        //Added to avoid garbage collection.
        System.out.println(hm);
        System.out.println(pshm);
        System.out.println(fcb);
        System.out.println(mcb);
//      System.out.println(ptrie);
    }

}

@@ -26,88 +26,8 @@
 t;%0A%0A
-import io.prelink.critbit.CritBitTree;%0Aimport io.prelink.critbit.MCritBitTree;%0A%0A
 impo
@@ -44,24 +44,24 @@
 il.HashMap;%0A
+
 import java.
@@ -94,16 +94,42 @@
 .Random;
+%0Aimport java.util.TreeMap;
 %0A%0Aimport
@@ -220,16 +220,65 @@
 omUtils;
+%0Aimport org.ardverk.collection.StringKeyAnalyzer;
 %0A%0A//impo
@@ -487,9 +487,9 @@
 S = 
-5
+3
 0000
@@ -2023,38 +2023,42 @@
 String%3E(
-new 
 String
-BitChecker()
+KeyAnalyzer.INSTANCE
 );%0A     
@@ -2740,32 +2740,267 @@
  %7D%0A        %7D);%0A%0A
+        final Map%3CString, String%3E tm = new TreeMap%3CString, String%3E();%0A        putTest(new Putter() %7B%0A            public String name() %7B return %22TreeMap%22; %7D%0A            public void put(String k, String v) %7B tm.put(k, v); %7D%0A        %7D);%0A%0A
         final FC
@@ -3308,30 +3308,34 @@
 ng%3E(
-new 
 String
-BitChecker()
+KeyAnalyzer.INSTANCE
 );%0A 
@@ -3996,24 +3996,24 @@
 rintln(hm);%0A
-
         Syst
@@ -4030,24 +4030,56 @@
 ntln(pshm);%0A
+        System.out.println(tm);%0A
         Syst

update test to use StringKeyAnalyzer