/*
 * WordHashBag.java
 * Created on Feb 24, 2005
 */
package word;

/**
 * A hashed-based implementation of WordBag.
 */
public final class WordHashBag implements WordBag {

    private static final int CAPACITY = 200;
    
    private final WordList[] buckets = new WordList[CAPACITY];
    
    public WordHashBag() {}

    public WordCount add(String str) {
        int location = Math.abs(hashString(str) % CAPACITY);
        WordList current = buckets[location], prev = null;
        
        while (current != null) {
            if (current.word().equalsIgnoreCase(str)) {
                current.incrementCount();
                return current;
            }
            prev = current;
            current = current.next;
        }
        
        WordList list = new WordList(str);
        if (prev == null) buckets[location] = list;
        else              prev.next = list;
        return list;
    }
    
    private static final int POW1 = 31;
    private static final int POW2 = POW1 * 31;
    private static final int POW3 = POW2 * 31;
    private static final int POW4 = POW3 * 31;
    
    /** hashes the first fivve characters */
    private static int hashString(String str) {
        char[] strChars = str.toCharArray();
        int hash = 0;
        switch(str.length()) {
        	default: hash += Character.toLowerCase(strChars[4]);
        	case 4:  hash += Character.toLowerCase(strChars[3]) * POW1;
        	case 3:  hash += Character.toLowerCase(strChars[2]) * POW2;
        	case 2:  hash += Character.toLowerCase(strChars[1]) * POW3;
        	case 1:  hash += Character.toLowerCase(strChars[0]) * POW4;
        }
        return hash;
    }
    
    private static class WordList extends WordCount {
        private WordList next = null;
        
        private WordList(String word) {
            super(word);
        }
    }

}
