#!/usr/bin/perl

use Modern::Perl;

use utf8::all;
use Time::Moment;
use Lingua::EN::Numbers::Ordinate;
use IO::Prompt::Tiny qw/prompt/;
use List::MoreUtils qw(uniq);
use YAML qw(LoadFile DumpFile);

# Get all commits from git
my @commits =
  `git -c i18n.logOutputEncoding=UTF-8 log --pretty=format:"%ct, %an, %ae"`;
unless (@commits) {
    say 'Hum... no commits?';
    exit 1;
}

my @history;

# Convert commit lines to hashref keyed on epoch date
# and record name -> email and email -> name maps
my $seen_name  = {};
my $seen_email = {};
my $commitref  = {};
for my $commit (@commits) {
    chomp $commit;
    my @bits = split( /,/, $commit );
    my $name = lc( $bits[1] );
    $name =~ s/([^\s\w]*)(\S+)/$1\u\L$2/g;
    $name =~ s/^\s+|\s+$//g;
    my $email = lc( $bits[2] );
    $email =~ s/^\s+|\s+$//g;
    $seen_name->{$name}->{$email}  = 1;
    $seen_email->{$email}->{$name} = 1;
    $commitref->{ $bits[0] } = { name => $name, email => $email };
}

# Construct authors hashmap email + name = author and save to file so we don't need to
# do manual disambiguation, which prompts for user input, for developers we've already
# seen.
my $authors = LoadFile("/home/martin/release-tools/etc/dev_map.yaml");
for my $commit ( sort { $a <=> $b } ( keys %{$commitref} ) ) {
    my $name  = $commitref->{$commit}->{name};
    my $email = $commitref->{$commit}->{email};
    next if ( $name eq '=' || $email eq '=' );
    if ( !defined( $authors->{$email}->{$name} ) ) {
        print "\n\nNew developer found with email $email and name $name\n";
        print "Previous name matches: "
          . join( " ", ( keys %{ $seen_name->{$name} } ) ) . "\n";
        print "Previous email matches: "
          . join( " ", ( keys %{ $seen_email->{$email} } ) ) . "\n";
        my $author =
          prompt( "Please enter their name for disambiguation:", "$name" );
        $authors->{$email}->{$name} = $author;

        # Save progress
        DumpFile( "/home/martin/release-tools/etc/dev_map.yaml", $authors );
    }
}
DumpFile( "/home/martin/release-tools/etc/dev_map.yaml", $authors );

# Create alias map from $authors
my $aliases = {};
for my $email ( keys %{$authors} ) {
    for my $name ( keys %{ $authors->{$email} } ) {
        $aliases->{$name} = $authors->{$email}->{$name};
        $aliases->{ $authors->{$email}->{$name} } = $authors->{$email}->{$name};
    }
}

# Construct contributors hashref keyed on contributor name
# { contributor_name =>
#   { first_commit => epoch_date, commits => number_of_commits }
# }
my $contributors;
for my $commit ( sort { $a <=> $b } ( keys %{$commitref} ) ) {
    my $commit_name  = $commitref->{$commit}->{name};
    my $commit_email = $commitref->{$commit}->{email};
    next if ( $commit_name eq '=' || $commit_email eq '=' );

    my $author = $authors->{$commit_email}->{$commit_name};
    if ( $contributors->{$author} ) {

        # Increment author commits
        $contributors->{$author}->{commits}++;
    }
    else {

        # Set first commit date
        $contributors->{$author}->{first_commit} = $commit;

        # Set first commit increment
        $contributors->{$author}->{commits} = 1;
    }
}

## Merge history and authors
my $history = {};
if (
    open(
        my $file, "<:encoding(UTF-8)",
        "/home/martin/kohaclone/docs/history.txt"
    )
  )
{
    my @lines;
    while ( my $line = <$file> ) {
        chomp $line;
        push @lines, $line;
    }
    close($file);

    shift @lines;    #remove header row
    foreach (@lines) {
        my ( $epoch, $date, $desc, $tag ) = split(/\t/);
        if ( defined( $history->{$epoch} ) ) {
            say "Duplicate epoch in history found: $epoch";
        }
        else {
            $desc =~ s/^\s+|\s+$//g;

            # Reprint original history with cleaned whitespace
            #my $line = $epoch . "\t" . $date . "\t" . $desc;
            #$line .= "\t" . $tag if ( defined($tag) );
            #$line .= "\n";
            #print $line;

            # Map Contributors
            $desc = _get_contributor( $desc, $epoch );

            #my $tm = Time::Moment->from_epoch($epoch);
            #$date = $tm->strftime("%B %e %Y");
            $history->{$epoch} =
              { date => $date, description => $desc, tag => $tag };

        }
    }
}

# Merge contributors found in history file
sub _get_contributor {
    my ( $desc, $epoch ) = (@_);
    if ( $desc =~ /^(.*)\sbecomes\sthe\s\d.*$/ ) {
        my $author = $1;
        $author =~ s/Katipo's new developer //g;
        $author =~ s/Koha production\?\?\?/Anonymous/g;

        if ( defined( $aliases->{$author} ) ) {

            #print "author: " . $author;
            my $match = quotemeta($author);

            #print "\t=>\t" . $match;
            #print "\t=>\t" . $aliases->{$author} . "\n";
            $desc =~ s/$match/$aliases->{$author}/g;
            $author = $aliases->{$author};
        }

        if ( $contributors->{$author} ) {
            if ( $contributors->{$author}->{first_commit} != $epoch ) {

                print "Duplicate contributor $author found\n";
                my $which = prompt(
                    "Which first_commit should we use 0: "
                      . $contributors->{$author}->{first_commit} . " 1: "
                      . $epoch,
                    0
                );
                my $which = 0;
                $contributors->{$author}->{first_commit} =
                  $which ? $epoch : $contributors->{$author}->{first_commit};
            }
        }
        else {
            #print "New contributor found: $author\n";
            $contributors->{$author}->{first_commit} = $epoch;
            $contributors->{$author}->{commits}      = 1;
        }

        $desc =~ s/Katipo's new developer //g;
        $desc =~ s/Koha production\?\?\?/Anonymous/g;

        $history->{$epoch}->{tag} = 'developer';
    }

    return $desc;
}
DumpFile( "/home/martin/release-tools/etc/contributors_map.yaml",
    $contributors );

# Merge contributors into the history hash
for my $contributor ( keys %{$contributors} ) {
    if (
        defined( $history->{ $contributors->{$contributor}->{first_commit} } ) )
    {
        my $line =
          $history->{ $contributors->{$contributor}->{first_commit} };
        if ( $line->{description} =~ /^(.*)\sbecomes\sthe\s\d.*$/ ) {
            my $author = $1;
            $history->{ $contributors->{$contributor}->{first_commit} }->{tag}
              = 'developer';
            unless ( $author eq $contributor ) {
                say "Duplicate epoch line found for contributor: "
                  . $contributors->{$contributor}->{first_commit};
                say "Duplicate author is: " . $contributor;
                say "Description is: "
                  . $history->{ $contributors->{$contributor}->{first_commit} }
                  ->{description};
            }
        }
        else {
            say "Duplicate epoch line found for contributor: "
              . $contributors->{$contributor}->{first_commit};
            say "Duplicate author is: " . $contributor;
            say "Description is: "
              . $history->{ $contributors->{$contributor}->{first_commit} }
              ->{description};
        }
    }
    else {
        my $tm = Time::Moment->from_epoch(
            $contributors->{$contributor}->{first_commit} );
        my $date = $tm->strftime("%B %e %Y");
        my $desc = $contributor . " becomes the 1st";
        $desc .= " committer to Koha"
          if ( $contributors->{$contributor}->{first_commit} < 1274054400 );
        $desc .= " committer to have a patch accepted"
          if ( ( $contributors->{$contributor}->{first_commit} > 1274054400 )
            && ( $contributors->{$contributor}->{first_commit} < 1290211200 ) );
        $desc .= " developer to have a patch pushed"
          if ( $contributors->{$contributor}->{first_commit} > 1290211200 );
        my $tag = 'developer';
        $history->{ $contributors->{$contributor}->{first_commit} } =
          { date => $date, description => $desc, tag => $tag };
    }
}

# Print combined history
my $seen_author = {};
my $dev_number  = 0;
my $histfile;
unless (
    open(
        $histfile, ">:encoding(UTF-8)",
        "/home/martin/kohaclone/docs/history_new.txt"
    )
  )
{
    warn "Failed to open filehandle\n";
}

for my $epoch ( sort { $a <=> $b } ( keys %{$history} ) ) {
    my $line = $history->{$epoch};
    if ( $line->{description} =~ /^(.*)\sbecomes\sthe\s\d.*$/ ) {
        my $author = $1;
        next if ( $seen_author->{$author} );
        next if ( $author eq "Anonymous" );
        next if ( $author eq "QA Manager" );
        next if ( $author eq "Koha production???" );
        next if ( $author eq "PTFS Team" );
        next if ( $author eq "Biblibre Team" );
        next if ( $author eq "ByWater Solutions Team" );
        next if ( $author eq "Koha Translators" );
        next if ( $author eq "Koha Instance Knakk-koha" );
        $dev_number++;
        $dev_number = 5
          if ( $author eq 'Steve Tonnesen' );    # Steve is a fixed point
        my $nth = ordinate($dev_number);
        $line->{description} =~ s/(\d+\w\w)/$nth/;
        $line->{tag} = 'developer';
        $seen_author->{$author} = 1;
    }

    my $new_line = $epoch . "\t" . $line->{date} . "\t" . $line->{description};
    $new_line .= "\t" . $line->{tag} if ( defined( $line->{tag} ) );
    $new_line .= "\n";

    print( $histfile $new_line );
}
close($histfile);

exit 0;
