#include <string>
#include <sstream>
#include <iostream>
#include <fstream>
#include <iomanip>
#include <map>
#include <list>

using namespace std;

// this function takes a line that may contain a name and/or email address,
// and returns just the name, while fixing the "bad cases".
std::string contributor_name(const std::string& line)
{
  string result;

  // let's first take care of the case of isolated email addresses, like
  // "user@localhost.localdomain" entries
  if(line.find("markb@localhost.localdomain") != string::npos)
  {
    return "Mark Borgerding";
  }

  // from there on we assume that we have a entry of the form
  // either:
  //   Bla bli Blurp
  // or:
  //   Bla bli Blurp <bblurp@email.com>
  
  size_t position_of_email_address = line.find_first_of('<');
  if(position_of_email_address != string::npos)
  {
    // there is an e-mail address in <...>.
    
    // Hauke once committed as "John Smith", fix that.
    if(line.find("hauke.heibel") != string::npos)
      result = "Hauke Heibel";
    else
    {
      // just remove the e-mail address
      result = line.substr(0, position_of_email_address);
    }
  }
  else
  {
    // there is no e-mail address in <...>.
    
    if(line.find("convert-repo") != string::npos)
      result = "";
    else
      result = line;
  }

  // remove trailing spaces
  size_t length = result.length();
  while(length >= 1 && result[length-1] == ' ') result.erase(--length);

  return result;
}

// parses hg churn output to generate a contributors map.
map<string,int> contributors_map_from_churn_output(const char *filename)
{
  map<string,int> contributors_map;

  string line;
  ifstream churn_out;
  churn_out.open(filename, ios::in);
  while(!getline(churn_out,line).eof())
  {
    // remove the histograms "******" that hg churn may draw at the end of some lines
    size_t first_star = line.find_first_of('*');
    if(first_star != string::npos) line.erase(first_star);
    
    // remove trailing spaces
    size_t length = line.length();
    while(length >= 1 && line[length-1] == ' ') line.erase(--length);

    // now the last space indicates where the number starts
    size_t last_space = line.find_last_of(' ');
    
    // get the number (of changesets or of modified lines for each contributor)
    int number;
    istringstream(line.substr(last_space+1)) >> number;

    // get the name of the contributor
    line.erase(last_space);    
    string name = contributor_name(line);
    
    map<string,int>::iterator it = contributors_map.find(name);
    // if new contributor, insert
    if(it == contributors_map.end())
      contributors_map.insert(pair<string,int>(name, number));
    // if duplicate, just add the number
    else
      it->second += number;
  }
  churn_out.close();

  return contributors_map;
}

// find the last name, i.e. the last word.
// for "van den Schbling" types of last names, that's not a problem, that's actually what we want.
string lastname(const string& name)
{
  size_t last_space = name.find_last_of(' ');
  if(last_space >= name.length()-1) return name;
  else return name.substr(last_space+1);
}

struct contributor
{
  string name;
  int changedlines;
  int changesets;
  string url;
  string misc;
  
  contributor() : changedlines(0), changesets(0) {}
  
  bool operator < (const contributor& other)
  {
    return lastname(name).compare(lastname(other.name)) < 0;
  }
};

void add_online_info_into_contributors_list(list<contributor>& contributors_list, const char *filename)
{
  string line;
  ifstream online_info;
  online_info.open(filename, ios::in);
  while(!getline(online_info,line).eof())
  {
    string hgname, realname, url, misc;
    
    size_t last_bar = line.find_last_of('|');
    if(last_bar == string::npos) continue;
    if(last_bar < line.length())
      misc = line.substr(last_bar+1);
    line.erase(last_bar);
    
    last_bar = line.find_last_of('|');
    if(last_bar == string::npos) continue;
    if(last_bar < line.length())
      url = line.substr(last_bar+1);
    line.erase(last_bar);

    last_bar = line.find_last_of('|');
    if(last_bar == string::npos) continue;
    if(last_bar < line.length())
      realname = line.substr(last_bar+1);
    line.erase(last_bar);

    hgname = line;
    
    // remove the example line
    if(hgname.find("MercurialName") != string::npos) continue;
    
    list<contributor>::iterator it;
    for(it=contributors_list.begin(); it != contributors_list.end() && it->name != hgname; ++it)
    {}
    
    if(it == contributors_list.end())
    {
      contributor c;
      c.name = realname;
      c.url = url;
      c.misc = misc;
      contributors_list.push_back(c);
    }
    else
    {
      it->name = realname;
      it->url = url;
      it->misc = misc;
    }
  }
}

int main()
{
  // parse the hg churn output files
  map<string,int> contributors_map_for_changedlines = contributors_map_from_churn_output("churn-changedlines.out");
  //map<string,int> contributors_map_for_changesets = contributors_map_from_churn_output("churn-changesets.out");
  
  // merge into the contributors list
  list<contributor> contributors_list;
  map<string,int>::iterator it;
  for(it=contributors_map_for_changedlines.begin(); it != contributors_map_for_changedlines.end(); ++it)
  {
    contributor c;
    c.name = it->first;
    c.changedlines = it->second;
    c.changesets = 0; //contributors_map_for_changesets.find(it->first)->second;
    contributors_list.push_back(c);
  }
  
  add_online_info_into_contributors_list(contributors_list, "online-info.out");
  
  contributors_list.sort();
  
  cout << "{| cellpadding=\"5\"\n";
  cout << "!\n";
  cout << "! Lines changed\n";
  cout << "!\n";

  list<contributor>::iterator itc;
  int i = 0;
  for(itc=contributors_list.begin(); itc != contributors_list.end(); ++itc)
  {
    if(itc->name.length() == 0) continue;
    if(i%2) cout << "|-\n";
    else cout << "|- style=\"background:#FFFFD0\"\n";
    if(itc->url.length())
      cout << "| [" << itc->url << " " << itc->name << "]\n";
    else
      cout << "| " << itc->name << "\n";
    if(itc->changedlines)
      cout << "| " << itc->changedlines << "\n";
    else
      cout << "| (no information)\n";
    cout << "| " << itc->misc << "\n";
    i++;
  }
  cout << "|}" << endl;
}
