#!/bin/perl

use CGI qw/:standard:/;

my %months = ("January" => 1,
	      "February" => 2,
	      "March" => 3,
	      "April" => 4,
	      "May" => 5,
	      "June" => 6,
	      "July" => 7,
	      "August" => 8,
	      "September" => 9,
	      "October" => 10,
	      "November" => 11,
	      "December" => 12);

my %copyrights = ("Springer-Verlag" => "copy_springer.html");

sub rpr ($) {
  my $arg = shift;
  if (ref($arg) eq  "HASH") {
    return map {rpr($_)."=>".rpr($$arg{$_})} keys %$arg;
  } elsif (ref($arg) eq "ARRAY") {
    return "[".(','.join(map {rpr($_)} @$arg))."]";
  } else {
    return $arg;
  }
}

$SPC = '[\s\n]*';
$KEY = '[a-zA-Z0-9_-]*';
$VAL = '(?:\"[^\"]*\"|[a-zA-Z_0-9-]+)';

sub lookup {
  my $val = shift;
  if ($val =~ /^\"\{([^\}]*)\}\"$/ms) {return $1;}
  elsif ($val =~ /^"([^\"]*)"$/ms) {return $1;}
  else {
    if ($bib =~ /\@string $SPC \{ $SPC $val $SPC = $SPC \"([^\"]*)\" /msx) {
      return $1;
    } else {
      return "$val";
    }
  }
}

sub getentry {
  my $name = shift;

  my ($entry,$type,$cite) = $bib =~ m{
    (
    \@([a-zA-Z]*) $SPC  # @article, @inproceedings, etc.
    \{ $SPC $name $SPC , $SPC # the name we're looking for
      (
	(?: $KEY $SPC = $SPC  $VAL $SPC ,? $SPC )+
      )
      \}
    )
  }msxg;

  my @fields = $cite =~ m{ $KEY $SPC = $SPC $VAL }msxg;

  my %fields = ();

  for $field (@fields) {
    my ($key,$val) = split '=',$field,2;
    $key =~s/^$SPC//;
    $key =~s/$SPC$//;
    $val =~s/^$SPC//;
    $val =~s/$SPC$//;
    $fields{$key}=lookup($val);
  }
  return [$name,$type,\%fields,$entry];
}

sub printtitle {
    my ($fields) = @_;
    my $title = $fields->{title};
    my $url = $fields->{url};
    if (defined($url)) {
	print "<a href=\"$url\">$title</a>.";
    }
    else {
	print "<b>$title</b>.";
    }
}

sub printentry {
  my ($stem,$type,$fields) = @{$_[0]};
  if ($type =~ /^inproceedings$/i) {
    print "[$$fields{year}] $$fields{author}. ";
    printtitle($fields);
    print " In <em>$$fields{booktitle}</em>. ";
    if (defined($$fields{series})) {
	print "$$fields{series}";
	print " $$fields{volume}" if defined($$fields{volume});
	print ". ";
    }
    print "$$fields{note}" if defined($$fields{$note});
    if (defined($$fields{copyright})) {
	my $holder = $copyrights{$$fields{copyright}};
	my $linktext = '&copy; ' . "$$fields{copyright} $$fields{year}";
	if (defined($holder)) { print "<a href='$holder'>$linktext</a> "; }
	else { print "$linktext "; }
    }
    print "\n";
  } elsif ($type =~ /^article$/i) {
    print "
    [$$fields{year}] $$fields{author}. ";
    printtitle($fields);
    print " <em>$$fields{journal}</em>, $$fields{volume}($$fields{number}): $$fields{pages}. $$fields{note}
    ";
  } elsif ($type =~ /^techreport$/i) {
    print "
    [$$fields{year}] $$fields{author}. <b>$$fields{title}</b>. ";
    if (defined($$fields{type})) {
	print "$$fields{type}, $$fields{institution}. ";
    }
    else {
	print "Technical Report ";
	print "$$fields{number}" if defined($$fields{number});
        print ", $$fields{institution}. ";
    }
    print "$$fields{note}" if defined($$fields{note});
    print "\n";
  } elsif ($type =~ /^unpublished$/i) {
    print "
    [$$fields{year}] Unpublished: $$fields{author}. <b>$$fields{title}</b>.
    $$fields{note}.
    ";
  } elsif ($type =~ /^misc$/i) {
    print "[$$fields{year}] " if (defined($$fields{year}));
    print "Misc: ";
    print "$$fields{author}. " if (defined($$fields{author}));
    print "<b>$$fields{title}</b>. " if (defined($$fields{title}));
    print "$$fields{howpublished}. " if (defined($$fields{howpublished}));
    print "$$fields{note}. " if (defined($$fields{note}));
    print "\n";
  }
#  print $type, h2s(%fields);
}

sub loadbib {
  $/ = undef;
  open BIB,"mmunson.bib" or die $!;
  $bib = <BIB>;
  close BIB;
}

sub printgroup {
  my ($name, $groups, , $files, @entries) = @_;

  # First check if there are any entries for the grouping.
  my $empty = 1;
CHECK:  for $entry (@entries) {
    my $type = $entry->[1];
    if (defined($groups->{$type})) {
      $empty = 0;
      last CHECK;
    }
  }

  return if ($empty);

  # Have non-empty group.
  print "<h2>$name</h2>\n";    
  print "<ul>\n";

ENTRY:  for $entry (@entries) {
    # Only print entries that are in the given group (by publication type).
    my $type = $entry->[1];
    next ENTRY if (!defined($groups->{$type}));

    print "\n<li>\n";
    printentry($entry);
    for my $ext (@{$files->{$$entry[0]}}) {
      print " <a href=\"docs/$$entry[0].$ext\">$ext</a>\n";
    }
    print " <a href=\"index.plx?bibtex=$$entry[0]\">BiBTeX</a>\n";
    print "\n</li>\n<br>&nbsp;<br>\n";
  }
  print "</ul>\n";
}

sub entrycmp {
  # Sort in reverse chronological order.
  my $pubdateA = $$a[2]{year};
  my $pubdateB = $$b[2]{year};

  my $order = $a cmp $b;

  if (defined($pubdateA) && defined($pubdateB)) {
    $order = $pubdateB cmp $pubdateA;
    if ($order == 0) {
      # Year doesn't distinguish, try month.
      $pubdateA = $$a[2]{month};
      $pubdateB = $$b[2]{month};
      if (defined($pubdateA) && defined($pubdateB)) {
	$order = $months{$pubdateB} <=> $months{$pubdateA};
      }
      elsif (defined($pubdateA)) {
	$order = 1;
      }
      else {
	$order = -1;
      }
    }
  }
  elsif (defined($pubdateA)) {
      $order = 1;
  }
  else {
      $order = -1;
  }

  return $order;
}

sub printentries {
  my $web = "docs";
  
  opendir DIR,$web or die $!;
  my @files = grep {$_ ne '.' and $_ ne '..' and $_ ne 'index.html'} readdir DIR;
  closedir DIR;
  
  my %files = ();
  for my $file (@files) {
    my ($stem,$ext) = split /\./,$file,2;
    push @{$files{$stem}},$ext;
  }
  
  my @entries = map {getentry($_)} keys %files;
  @entries = sort entrycmp @entries;


  printgroup("Journal Papers",
             {"article" => 1},
             \%files,
             @entries);
  printgroup("Conference Papers",
             {"inproceedings" => 1, "conference" => 1}, 
             \%files,
             @entries);
  printgroup("Technical Reports",
             {"techreport" => 1},
             \%files,
             @entries);
  printgroup("Miscellaneous Publications",
             {"misc" => 1},
             \%files,
             @entries);
  printgroup("Unpublished Work", 
             {"unpublished" => 1}, 
             \%files,
             @entries);
}

################################################################
# Begin main program.
################################################################

my $researcher = "Art Munson";
my $email = "mmunson AT cs DOT cornell DOT edu";

#print HTML head

$q = new CGI;

print $q->header;

$bibtex = $q->param('bibtex');
if ($bibtex) {
  loadbib();
  print $q->start_html("${researcher}'s Publications: BiBTeX");
  print $q->h1("${researcher}'s Publications: BiBTeX");
  my $entry = getentry($bibtex);
  print "<PRE>\n";
  print $$entry[3];
  print "</PRE>\n";
} else {
  print $q->start_html("${researcher}'s Publications");
  print $q->h1("${researcher}'s Publications");
  loadbib();
  printentries();
}

#print "perl v$]\n";

print "

<p>
This page is automatically generated.  If you find HTML errors,
citation errors, stylistic errors,
errors in the documents, or anything else wrong with this
page, please let me know at: 
<blockquote>$email</blockquote>
Presumably if you are reading this you don't need to be told, but just in
case: 
ps is PostScript, pdf is Portable Document Format, ppt is Microsoft
  PowerPoint, and doc is
Microsoft Word.  Free viewers for all of these for at least some platforms
are available from <a href=\"http://www.cs.wisc.edu/~ghost/\">Ghostscript</a>, 
<a href=\"http://www.adobe.com/products/acrobat/readstep2.html\">Adobe</a>, 
and <a 
href=\"http://office.microsoft.com/downloads/2000/wd97vwr32.aspx\">Microsoft</a>, respectively.
</p>
";
print $q->end_html;

# to-do:
#  pages for collections: JNLE: http://titles.cambridge.org/journals/journal_catalogue.asp?mnemonic=jnle
#  
#  posters in separate sub-folder, and mark them as poster next to bib info
#
#  how to handle presentation related to work but not at conference?
