// Hash table implementation
// By: Nick Cash
// Coded for Computer Science III

// Hash.c - Class implementation

#include <iostream>
#include "hash.h"

// Class implementation

HashTable::HashTable( HashFunction *f )
{
  mHashFunc = f;
  mNumBuckets = HASH_TABLE_SIZE;

  // Get us a new table
  for ( int i = 0; i < mNumBuckets; i++ )
   mBuckets.push_back(new ElemList);
}

HashTable::HashTable( HashFunction* f, uint buckets )
{
  mHashFunc = f;
  mNumBuckets = buckets;
  
  // Make the table
  for ( int i = 0; i < mNumBuckets; i++ )
   mBuckets.push_back(new ElemList);
}

HashTable::~HashTable()
{
/*
	//  Empty each bucket
    for ( uint i = 0; i < mNumBuckets; i++ )
	{
        while ( !mBuckets.empty() )
        {
          ElemList* temp = mBuckets.back();
          
          mBuckets.pop_back();
          delete temp;
        }
	}
*/
}

void HashTable::SetHashFunc( HashFunction* f )
{
  mHashFunc = f;
}

HashFunction* HashTable::GetHashFunc() const
{
  return mHashFunc;
}

int HashTable::Lookup(const std::string& str )
{
  time_t start, end;
  bool found = false;
  
  // start timer
  time(&start);
  
  // Perform lookup
  ElemList* list = mBuckets[Hash(str)];
  
  for ( ElemList::iterator iter = list->begin(); iter != list->end(); iter++ )
  {
    if ( *iter == str )
    {
      found = true;
      break;
    }
  }

  // end timer
  time(&end);

  // if we found it, return the time it took
  if ( found )
   return (int)difftime(end,start);
  
  // otherwise return -1
  return -1;
}

// Add a word
void HashTable::Add(const std::string& str)
{
 ElemList* list = mBuckets[Hash(str)];
 
 list->push_back(str);
}

uint HashTable::Hash(const std::string& str) const
{
  return (mHashFunc(str) % mNumBuckets);
}