// SPDX-FileCopyrightText: The Eigen Authors
// SPDX-License-Identifier: MPL-2.0

#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";
  }

  if (line.find("kayhman@contact.intra.cea.fr") != string::npos) {
    return "Guillaume Saupin";
  }

  // 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;
}
