// File: 04SortPasswordsSTL.cpp 
// Author: Niall Madden. For NUI Galway module CS319
// What: Version of SortPasswords.cpp from Week 6, but based on 
//      set and multiset from the STL
// When: 15-03-2017
// For more information see
//     http://www.maths.nuigalway.ie/~niall/CS319

#include <iostream>
#include <iomanip>
#include <fstream>
#include <cstdlib>
#include <string>
#include <math.h>
#include <set>       // multiset
#include <vector>    // vector
#include <algorithm> // sort

class pwd {
private:
  std::string word;
  int freq;
public:
  pwd(std::string s, int f) {word=s; freq=f;}; 
  std::string getword(void) const {return(word);};
  int getfreq(void) const {return(freq);};
};

bool comp (pwd p, pwd q)  
{
  return (p.getfreq() > q.getfreq());
}

int FileLength(std::ifstream &InFile, int &LongestWord);

int main(void )
{
  std::ifstream InFile;
  std::string InFileName="UserAccount-1e5.txt";
  std::multiset <std::string> multi_pwd;
  std::multiset <std::string>::iterator multi_pwd_i;
  std::vector <pwd> vector_pwd;

  InFile.open(InFileName.c_str());
  if (InFile.fail() )
  {
    std::cerr << "Error: Cannot open " << InFileName <<
      " for reading." << std::endl;
    exit(1);
  }

  // Need to know the number of lines, and the length of the longest one
  int LineCount=0, LongestLine;
  LineCount =  FileLength(InFile, LongestLine);
  std::cout  << InFileName << " has " << LineCount << " lines.\n";
  std::cout  << "\tThe longest has " << LongestLine << " characters.\n";

  // Read the lines
  char *c_string_word;
  c_string_word = new char [LongestLine+1];
  for (int i=0; i<LineCount; i++)
  {
    InFile.getline(c_string_word, LongestLine+1);
    multi_pwd.insert(c_string_word);
  }

/*
  std::cout << "The set is: " << std::endl;
  for (multi_pwd_i = multi_pwd.begin();
  multi_pwd_i != multi_pwd.end();
  multi_pwd_i++)
  std::cout <<  *multi_pwd_i << std::endl;
*/

  // Copy the passwords to the pwd vector
  multi_pwd_i = multi_pwd.begin();
  vector_pwd.push_back(pwd(*multi_pwd_i, multi_pwd.count(*multi_pwd_i)));
  multi_pwd_i++;
  while (multi_pwd_i != multi_pwd.end())
  {
    if ((vector_pwd.back()).getword() != *multi_pwd_i)
      vector_pwd.push_back(pwd(*multi_pwd_i, multi_pwd.count(*multi_pwd_i)));
    multi_pwd_i++;
  }

  std::sort (vector_pwd.begin(), vector_pwd.end(), comp);

  std::cout << "Top 10 passwords are: " << std::endl;
  for (unsigned int i=0; i<10; i++)
    std::cout <<  std::setw(12) << (vector_pwd[i]).getword() << 
      std::setw(6) << (vector_pwd[i]).getfreq() << std::endl;

  InFile.close();

  return(0);
}

// Return the number of lines in the file. Also set length of longest line
int FileLength(std::ifstream &InFile, int &LongestLine)
{
  // Rewind to the start of the file
  InFile.clear();
  InFile.seekg(std::ios::beg);

  char c;
  InFile.get( c );
  int LineCount=0, ThisLineLength=0;
  while( ! InFile.eof() )
  {
    if (c != '\n')
      ThisLineLength++;
    else
    {
      LineCount++;
      if (LongestLine<ThisLineLength)
	LongestLine = ThisLineLength;
      ThisLineLength=0;
    }
    InFile.get( c );
  }

  // Rewind
  InFile.clear();
  InFile.seekg(std::ios::beg);

  return(LineCount);
}

