// Dictionary Class

// C++
#include <iostream>
#include <list>

// Custom/Local
#include "isr/isr.h"
#include "dictionary.h"


// Class Functions

// ctor
cDictionary::cDictionary( void )
{
}

// dctor
cDictionary::~cDictionary( void )
{
}

// Throw all entries into a list, sort list by references
void cDictionary::PrintHighReferences()
{
   std::list<ISR::cWord> WordTable;
   std::list<ISR::cWord>::const_iterator x;
   WordMap::iterator i;
   ISR::cWord * ptr = NULL;
   
   // load map into list
   for ( i = mTable.begin(); i != mTable.end(); i++ )
     WordTable.push_back(*(new ISR::cWord(i->first, i->second)));

   // sort word table
   WordTable.sort();
   WordTable.reverse(); // gets sorted in ascending, we want descending
   
   // print
   std::cout << "\n\n";   // preliminiary new lines
   
   for ( x = WordTable.begin(); x != WordTable.end(); x++ )
    printf( "%9d - %s\n", x->GetRef(), (x->GetStr()).c_str() );
}

// Print all words and numbers in alphabetical order
void cDictionary::PrintAlphabetical( void )
{
  WordMap::iterator i;
  
  // preliminiary new lines
  std::cout << "\n\n";
  
  // loop through and print
  for ( i = mTable.begin(); i != mTable.end(); i++ )
   printf( "%9d - %s\n", i->second, i->first.c_str() );
}


// Populate dictionary with words from cin
void cDictionary::Populate( bool display )
{
  std::string str;
  int i = 0;

  // if we are displaying, print out header
  if ( display )
   std::cout << "Words:           ";

  // Loop until we hit the end of the file
  while ( !std::cin.eof() )
  {
     ISR::ScanAlnum( str ); // grab our word
     AddRef( str ); // add it
     
     i++;
  }
  
  if ( display )
   std::cout << i;
}

// Add to the dictionary. If it exits, reference++. Return # of references
int cDictionary::AddRef( const std::string & str)
{
    WordMap::iterator i;

    i = mTable.find(str);

    // if it wasnt found in the map, add it, otherwise increment its occurance
    if ( i == mTable.end() )
     mTable[str] = 1;
    else
     i->second++;
     
    return i->second;
}

// Subtract reference, if references = 0 then remove word, return # of references
int cDictionary::SubRef( const std::string & str)
{
    WordMap::iterator i;

    i = mTable.find(str);

    // if it wasnt found in the map return 0, otherwise decrement its occurance
    if ( i == mTable.end() )
     return 0;
    else
    {
     i->second--;
     
     if ( i->second <= 0 ) // remove from table?
     {
       mTable.erase(i);
       return 0;
     }
    }
    
    return i->second;
}

// Return number of references to a certain string
int cDictionary::GetRef( const std::string & str)
{
    WordMap::iterator i;

    i = mTable.find(str);

    // if it wasnt found in the map, add it, otherwise increment its occurance
    if ( i == mTable.end() )
     return 0;

    return i->second;
}