#!/usr/bin/perl -w

use strict;
no strict 'refs';

use Data::Dumper;

use Text::BibTeX; 
use Text::BibTeX::Name; 


my $bibfile = new Text::BibTeX::File "etc/publications.bib";

# The following is a listing of formats, and how to display them. The key 
# is the format name (as gleened from the bibtex file), and the value is an 
# array of fields, in the order they are to appear in the HTML. 
my %formats = (
    inproceedings => [
        'author', 'title', 'booktitle', 'month', 'year'
    ],
    article => [
        'author', 'title', 'journal', 'month', 'year'
    ],

    techreport => [
        'author', 'title', 'number', 'institution', 'year', 'month'
    ],
);

my @Webpages = (
    [['Carrie', 'Gates'], 'evan.c.hughes@gmail.com']
);

# An array to hold a listing of papers. Each paper is an array, of the
# form:
#
# [ [ year, month-as-number ], text ]
#
# This allows us to sort the papers into order easily.
my @papers = ();
my %hierarchy = ();

# Read each entry
while (my $entry = new Text::BibTeX::Entry $bibfile) {
    next unless $entry->parse_ok;

#    print Text::BibTeX::split_list($entry->get('author'), 'and');
    
    # Walk the entries, generating HTML for each. 
    if (exists $formats{$entry->type}) {
        my @fields = ();
        foreach my $i (0 .. $#{$formats{$entry->type}}) {
            my $type = $formats{$entry->type}[$i];
            my $fn = "handle_$type";

            my $val = &$fn($type, $entry);
	    if ($val)
	    {
            	push(@fields, $val);
	    }
            #push(@fields, &$fn($type, $entry));
        }

        my $text = join('. ', @fields);
        my $date = determine_date($entry);

        my $record = [$date, $text, $entry];

        # Add the paper to the subject hierarchy. 
        add_to_subject_hierarchy($bibfile, \%hierarchy, $record);

        # Add the paper to the list of files. 
        push(@papers, $record);
    }
}

# Sort
@papers = reverse sort {
    my $yr = $a->[0][0] <=> $b->[0][0];
    if ($yr == 0) {
        if (defined $a->[0][1] and defined $b->[0][1]) {
            return $a->[0][1] <=> $b->[0][1];
        }
        else {
            return 0;
        }
    }
    else {
        return $yr;
    }
} @papers;


# Display the list
show_papers(@papers);

sub add_to_subject_hierarchy {
    my ($bibfile, $subs, $entryRef) = @_;

    my $x = $entryRef->[2]->get("subjects");
    if (!defined($x)) {
        return;
    }

    my @subjectMacros = split(/\s*,\s*/, $x);

    print @subjectMacros;

    foreach my $subMacro (@subjectMacros) {
        my $expanded = Text::BibTeX::macro_text($subMacro);
        if (!defined($expanded)) {
            die "Could not locate subject macro named \"$subMacro\"";
        }

        my @splitSubjects = split(/\s*\/\s*/, $expanded);
        foreach my $sub (@splitSubjects) {
            print "$sub...\n";
        }
    }
}

sub handle_author {
    my ($type, $entry) = @_;

    my @result = ();

    # Get the names
    my @names = Text::BibTeX::split_list($entry->get('author'), 'and');

    # Do markup on the names (if possible)
    foreach my $name (@names) {
        my $parser = new Text::BibTeX::Name($name);
        my $webpage = undef;

        foreach my $tuple (@Webpages) {
            my $first = join(' ', $parser->part('first'));
            my $last = join(' ', $parser->part('last'));

            if (($tuple->[0][0] eq $first) and ($tuple->[0][1] eq $last))
            {
                $webpage = $tuple->[1];
                last;
            }
        }

        if (defined($webpage)) {
            push(@result, '<a href="' . $webpage . '">' . $name . '</a>');
        } 
        else {
            push(@result, $name);
        }
    }

    return join(", ", @result);
}

sub handle_title {
    my ($type, $entry) = @_;

    if (defined($entry->get('url'))) {
        return '<a href="' . $entry->get('url') . '">' . $entry->get($type) 
            .  '</a>';
    }

    return $entry->get($type);
}

sub handle_booktitle {
    my ($type, $entry) = @_;

    return $entry->get($type);
}


sub handle_journal {
    my ($type, $entry) = @_;

    return $entry->get($type);
}


sub handle_number {
    my ($type, $entry) = @_;

    return $entry->get($type);
}


sub handle_institution {
    my ($type, $entry) = @_;

    return $entry->get($type);
}


sub handle_month {
    my ($type, $entry) = @_;

    return $entry->get($type);
}

sub handle_year {
    my ($type, $entry) = @_;

    return $entry->get($type);
}


# Determine the date the paper was published. The date is returned in the form 
# [year, month], where each are digits.
sub determine_date {
    my ($entry) = @_;

    my %months = (
        Jan => 0,
        Feb => 1,
        Mar => 2,
        Apr => 3,
        May => 4,
        Jun => 5,
        Jul => 6,
        Aug => 7,
        Sep => 8,
        Oct => 9,
        Nov => 10,
        Dec => 11,
    );

    my $month = undef;
    if (defined $entry->get('month')) {

        if (!defined($months{$entry->get('month')})) {
            die "Unknown month " . $entry->get('month'). "\n";
        }

        $month = $months{$entry->get('month')};
    }

    $entry->get('year') =~ /(\d{4})/;

    return [$1, $month];
}


# Show the papers in order
sub show_papers {
    my (@papers) = @_;

    my $year = 0;
    foreach my $paper (@papers) {
        # Skip entries that aren't refereed. 
        my $x = $paper->[2]->get("refereed");
        if (defined($x) && $x eq "false") {
            next;
        }

        # Skip entries that were written outside the lab. 
        $x = $paper->[2]->get("in_lab");
        if (defined($x) && $x eq "false") {
            next;
        }
        
        # Print the paper. 
        if ($year != $paper->[0][0]) {
            print '<div class="year">', $paper->[0][0], "</div>\n\n";
            $year = $paper->[0][0];
        }

        print '<div class="paper">', "\n\t"; 
        print '<div class="text">', $paper->[1], '</div>', "\n\n\t"; 
        print '<div class="bibtex">', $paper->[2]->print_s(), '</div>', "\n";
        print '</div>', "\n\n";
    }
}
