// Main.c
// Nick Cash, 810:061-3
// Assignment 5

#include <fstream>
#include <iostream>
#include <list>

//custom header
#include "main.h"


list<wentry *> w_table;

// find a string in the table
wentry *find_str(string s)
{
  list<wentry *>::const_iterator iter;
  wentry *w = NULL;
  
  for ( iter = w_table.begin(); iter != w_table.end(); iter++ )
  {
    if ( (*iter)->GetStr() == s )
    {
     w = (*iter);
     break;
    }
  }

  return w;
}

int main()
{
   list<wentry *>::iterator iter;
   ifstream f;
   string s,line;
   wentry *w = NULL;
   int i,j,k = 0;
   unsigned int count = 0; // number of words total

   // for sorting
   list<wentry> w_table2;
   list<wentry>::iterator iter2;
   
   
   cout << "\n\nWhat file shall we get input from?\n";
   cin >> s;
   
   f.open(s.c_str());
   
   if ( !f )
    return EXIT_FAILURE;
   else
    s = "";
   
   while ( 1 )
   {
     getline( f, line );
     
     line += ' '; // throw on a space delimiter

     if ( f.eof() )
      break; // break while
      
     // change any control chars or punctuation, minus the apostrophe (')
     for ( j = line.length(), i = 0; i < j; i++ )
     {
      // get rid of caps
      line[i] = tolower(line[i]);
      
      if ( (ispunct(line[i]) != 0 && line[i] != '\'') || iscntrl(line[i]) != 0 )
       line[i] = ' ';
     }

     k = 0;
     
     while ( 1 )
     {
         s = "";
         i = k;

         // find first non-blank
         for ( ; i < j; i++ )
          if ( line[i] != ' ' )
           break;

         // are we at the end?
         if ( i == j )
          break; // break while
          
         // find first blank
         for ( k = i; k < j; k++ )
          if ( line[k] == ' ' )
           break;

         s = line.substr(i, k-i );

         //increment total word counter
         count++;

         // did we find it?
         if( (w = find_str(s)) == NULL )
         {
           //we didn't find it! add it!
           w = new wentry(s); // give us a wentry with str == s and ref == 1
           w_table.push_back(w);
         }
         else // found, now increment ref
          ++(*w);
     } // end while #2
   } // end while #1
   
   // copy table, then sort
   for ( iter = w_table.begin(), iter2 = w_table2.begin(); iter != w_table.end(); iter++, iter2++ )
    w_table2.push_back(*(*iter));
   
   w_table2.sort();    // sorts in ascended order
   w_table2.reverse(); // so we need to reverse

   cout << "\n\n\nResults:\n--------\n\n";

   // iterate and print
   for (iter2 = w_table2.begin(); iter2 != w_table2.end(); iter2++ )
    cout << " " <<(*iter2).GetRef() << "  " << (*iter2).GetStr() << endl;
    

   cout << "\n\n\nTotal Words: " << count << endl << endl;
   
   //close file
   f.close();
   
   return EXIT_SUCCESS;
}

//////////////////////////////////
// class definitions            //
//////////////////////////////////

//constructors and destructors
wentry::wentry()
{
 mStr = "";
 mRef = 0;
}

wentry::wentry(string s)
{
 mStr = s;
 mRef = 1;
}

wentry::wentry(string s, int ref )
{
  mStr = s;
  mRef = ref;
}

wentry::~wentry()
{
    list<wentry *>::iterator iter;

    for (iter = w_table.begin(); iter != w_table.end(); iter++ )
    {
        // erase from list
        if ( (*iter) == this )
        {
            w_table.erase(iter);
            break;
        }
    }
}

///
inline wentry *wentry::operator++()
{
  //increase reference
  mRef++;

  return this;
};

inline bool wentry::operator<(const wentry &Entry) const
{
 return (mRef < Entry.GetRef());
}