#!/usr/bin/env perl
# -*-Perl-*-

use Net::Domain qw(hostname hostfqdn);
unshift (@INC, '/home/ff/cs61b/grading-software/share/lib');
require "GradingBase.pl";
require "GradingCommon.pl";

$repo = $ENV{'GL_REPO'};
my ($type, $who) = ($repo =~ m{(.*)/(.*)});

sub mailBugReport {
    my $tag = shift;
    my $who = shift;
    my $assgn = shift;
    my $annotation = `git show -n 2048 -l $tag`;
    my ($members, $subject, $recipients);

    if (TeamExists($who)) {
        $members = TeamMembers($who);
    } else {
        $members = $who;
    }
    
    $subject = "Error report for assignment $assgn from $who";

    $recipients = "$SUPERVISOR";
    foreach (split(/\s+/, $members)) {
        $recipients .= " " . MailingAddress($_);
    }

    my $reply_addr = MailingAddress($who);

    System("git tag -n 2048 -l $tag "
           . "| ${MAIL_PROG} -S replyto=$reply_addr -s '$subject' $recipients");
}

sub deleteSubmission {
    my $tag = shift;
    my $who = shift;
    my $bugflag = shift;

    my ($assgn, $dir, $tg, $base, $log, $log_base);
    
    if ($tag =~ m{^(.*)-bug.*} or $tag =~ m{^(.+)-\d+$}) {
        $assgn = $1;
    } else {
        return;
    }

    if ($bugflag) {
        $dir = $BUG_SUBMISSION_DIR;
    } else {
        $dir = $SUBMISSION_DIR;
    }
        
    foreach my $subm (GLOB("$dir/$assgn/$who.*[0-9]")) {
        ($base) = ($subm =~ m{.*/(.*)$});
        open(SUBM, $subm);
        <SUBM>;
        <SUBM>;
        $tg = <SUBM>;
        chomp $tg;
        if ($tg eq $tag) {
            unlink($subm);
            if ($bugflag) {
                print STDOUT "*** Deleted bug submission $tag ($base)\n\n";
            } else {
                print STDOUT "*** Deleted submission $tag ($base)\n\n";
            }
            if (not $bugflag) {
                foreach my $log (GLOB("$LOG_DIR/$assgn/*/$base")) {
                    my ($log_base) = ($log =~ m{.*/($assgn/.*/$base)});
                    unlink($log);
                    print STDOUT "*** Deleted log entry $log_base\n\n";
                }
            }
        }
        close(SUBM);
    }
}

if (StudentExists($who) or TeamExists($who)) {
    foreach (<STDIN>) {
        chomp;
        my ($old, $new, $ref) = split;
        my $bugflag;
        my $derefnew;
        my $timestamp;
        $bugflag = 0;
        if (not $ref =~ m{^refs/tags/}) {
            next;
        }
        my ($tag) = ($ref =~ m{^refs/tags/(.*)});
        if ($ref =~ m{(?i)bug}) {
            $bugflag = 1;
        }
        if ($new =~ /^0+$/) {
            deleteSubmission($tag, $who, $bugflag);
            next;
        }
        if ($ref =~ m{(?i)bug}) {
            $bugflag = 1;
        }
        if ($bugflag and $tag !~ m{^(.*)-bug.*}) {
            print STDERR "\nWARNING: bug tag $tag has wrong format.\n\n";
            next;
        }
        if (not ($bugflag and $tag =~ m{^(.+)-bug.*$})
            and not (not $bugflag and $tag =~ m{^(.+)-\d+$})) { 
            print STDERR "\nNote: $tag is not a submission or bug report.\n\n";
            next;
        }
        my $assgn = $1;
        if (not AssignmentExists($assgn)) {
            if ($bugflag) {
                print STDERR "\nWARNING: Unknown assignment $assgn in bug tag $tag.\n\n";
            } else {
                print STDERR "\nWARNING: No assignment $assgn; $tag is not a submission.\n\n";
            }
            next;
        }
        my $dir;
        if ($bugflag) {
            $dir = $BUG_SUBMISSION_DIR;
        } else {
            $dir = $SUBMISSION_DIR;
        }
        if (not -d "$dir/$assgn" && -w "$dir/$assgn") {
            InitDir("$dir/$assgn", 02777, $STAFF_GROUP);
        }
        my ($unixtimestamp) = 
            (`git cat-file commit $ref` =~ m{^author.*\s(\d+)\s[-+]\d+$}m);
        while (1) {
            $timestamp = TimeToTimeStamp($unixtimestamp);
            $subm = "$dir/$assgn/$who.$timestamp";
            if (not -e $subm) {
                last;
            }
            if ($bugflag) {
                $unixtimestamp += 1;
            } else {
                $unixtimestamp -= 1;
            }
        }
        if ($bugflag) {
            $subm_tag = $tag;
        } else {
            %all_tags = ();
            foreach $existing_tag (split(/\s+/, `git tag`)) {
                $all_tags{$existing_tag} = 1;
            }
            for ($i = 1; ; $i += 1) {
                $subm_tag = "submit/$assgn-$i";
                if (not $all_tags{$subm_tag}) {
                    last;
                }
            }
            if (not System("git tag $subm_tag $new")) {
                print STDERR "\n*** Internal submission error.  Please see the staff.\n\n";
                next;
            }
        }
        $derefnew = `git rev-list -1 $new 2>/dev/null`;
        if (not $derefnew) {
            $derefnew = $new;
        }
	open (SUBMIT, ">", $subm) || next;
	print SUBMIT "GIT submission\n";
 	print SUBMIT "$repo\n$subm_tag\n$derefnew\n";
	close SUBMIT || next;
        chmod(0644, $subm);
        if ($bugflag) {
            print STDERR "\n*** Bug report for assignment $assgn submitted.\n\n";
            mailBugReport($tag, $who, $assgn);
            next;
        } else {
            print STDERR "\n*** Assignment $assgn submitted.\n\n";
        }
        next if not TeamExists($who);
	$base = "$who.$timestamp";
	foreach $login (split (/\s+/, TeamMembers($who))) {
	    symlink ($base, "$SUBMISSION_DIR/$assgn/$login.$timestamp");
	}
    }
} else {
    print STDERR "\nWARNING: No registration found for $who.\n\n";
}

exit 0;
