#!/usr/bin/env perl

# N.B. requires xsltproc to be on the PATH

use strict;

use File::Basename;
use File::Spec::Functions;
use Cwd qw ( realpath );

$| = 1;

my $baseDir = dirname($0);
my $iDir = $ARGV[0] or usage("No input directory specified...");
my $oDir = $ARGV[1] or usage("No output directory specified...");
my $svnDir = $ARGV[2]; # optional
my $foafListFn;

$iDir = realpath($iDir);

print "\nBuilding ASF Committers web site\n".
      "================================\n\n";

my @transforms = (
    [ 'index.xsl', 'index.html' ],
    [ 'map.xsl', 'map.html' ],
    [ 'foaf2gmap.xsl', 'mapData.xml' ],
    [ 'foaf2index.xsl', 'committers.html' ],
    [ 'foaf2blogs.xsl', 'blogs.html' ],
    [ 'gallery.xsl', 'gallery.html' ],
    [ 'foaf2projects.xsl', 'projects.html' ],
    [ 'foaf2list.xsl', '' ],
    [ 'builds.xsl', 'builds.html' ],
    [ 'resources.xsl', 'resources.html' ],
    [ 'foafindex.xsl', 'foaf/index.html' ],
    [ 'calamatic.xsl', 'foaf/calamatic.html' ],
    [ 'foafamatic.xsl', 'foaf/foafamatic.html' ],
    [ 'calendar.xsl', 'calendar.html' ],
    [ 'committer-index.xsl', '../work/committer-index.tmpl'],
    [ 'committers-by-project.xsl', '../work/committers-by-project.tmpl'],
);

# Is the iDir an svn repo? If so try and svn up it
#if ($^O !~ /^MSWin32/ && -d catdir($iDir, '.svn')) {
#    print "  Attempting to update $iDir...";
#    my $cmd = `/usr/bin/which svn`;
#    chomp($cmd);
#    $cmd .= " up $iDir";
#    $cmd .= " --config-dir ".catdir($svnDir, '.subversion') if $svnDir;
#    my $rv = `$cmd`;
#    if ($?) {
#        print "Failed\nCMD: $cmd\n$rv\n";
#    } else {
#        print "OK\n";
#    }
#}

openFoafList($oDir);
getFoafList($iDir);
closeFoafList();

foreach my $arrp (@transforms) {
    my $xslFn = catfile($baseDir, $arrp->[0]);
    my $oFn = catfile($oDir, $arrp->[1]);
    my $cmd = "xsltproc --novalid $xslFn $foafListFn";
    if (! -f $xslFn) {
        print "  XSL file '$xslFn' doesn't exist!\n";
        next;
    }
    print "  Running '$xslFn' ".($arrp->[1] ? "to create '$oFn'" : "")."\n";
    # N.B. We don't use -o (--output) because that also changes the base directory for xsl:document
    if ($arrp->[1]) {
        $cmd .= " > $oFn";
    }
    my $rv = `$cmd`;
    print "\tFailed\n$rv" if $?;
}

unlink($foafListFn);

print "Running Ruby script to create committer index pages\n";
my $rv;
$rv = `ruby templates/pchtml.rb work/committers-by-project.tmpl site/committers-by-project.html`;
print "\tFailed\n$rv" if $?;

$rv = `ruby templates/pchtml.rb work/committer-index.tmpl site/committer-index.html -c`;
print "\tFailed\n$rv" if $?;

my $evList = catfile($iDir, 'events.xml');
my $evTempl = catfile($baseDir, 'eventsgallery.xsl');
my $oFn = catfile($oDir, 'events.html');
if (((stat($oFn))[9] || 0) < (stat($evList))[9]) { # Is output file older than input?
    print "  Creating event galleries (this will take some time...)\n";
    # N.B. We don't use -o (--output) because that also changes the base directory for xsl:document
    my $cmd = "xsltproc --novalid $evTempl $evList > $oFn";
    `$cmd`;
} else {
    print "  Skipping event gallery creation\n";
}

print "\nASF Committers website generation complete\n\n";

sub getFoafList
{
    my $dir = shift;
    opendir(my $dh, $dir) or die "Couldn't open '$dir'\n$!\n";
    print "  Collecting foaf locations from '$dir'\n";
    while (my $f = readdir($dh)) {
        next if $f =~ /^\./;
        if ($f =~ /\.rdf$/) {
            writeFoafEntry(catfile($dir, $f));
        }
        processExternal(catfile($dir, $f)) if $f eq 'external.xml';
    }
    closedir($dh);
}

sub openFoafList
{
    my $dir = shift;
    $foafListFn = catfile($baseDir, 'list.xml');
    print "  Creating foaf location list file '$foafListFn'\n";
    open(OUT, ">$foafListFn") or die "Unable to open '$foafListFn' for".
                                     " writing.\n$!";
    
    print OUT <<EOT;
<?xml version="1.0"?>
<list>
EOT
}

sub writeFoafEntry
{
    my ($u, $id, $url) = @_;

 # N.B. It seems that xsltproc on Windows ignores any entries containing "\"
 # Also, file: locations must start with file:///[drive:]/ or file:///..
 # 
    my $file_pfx='file://'; # default prefix - but should this also be file:/// ?
    if ($^O =~ /^MSWin32/){
        $file_pfx='file:///'; # Use corrected file prefix
    }

    if ($^O =~ /^MSWin32/){
        $u =~ s!\\!/!g; # convert \ to /
    }
    print OUT  "  <location>$file_pfx$u</location>\n" unless $id;
    print OUT  "  <location ASFid=\"$id\" url=\"$url\">$file_pfx$u</location>\n" if $id;
}

sub closeFoafList
{
    print OUT "</list>\n";
    close OUT; # Done with the file
}

sub processExternal
{
    print "    Getting external file locations...\n";
    my $fn = shift;
    open EXT, $fn or die "Unable to open '$fn'\n$!";
    while (<EXT>) {
        next unless m!<location\s+ASFid=\"(.*)\".*?>(.*)</location>!;
        my $id = $1;
        my $url = $2;
        my $tfn = catfile($iDir, 'external', $id . '.rdf');
        if ($^O =~ /linux|freebsd/i) {
            if ($^O =~ /linux/i) {
               `wget -q -t 1 -T 20 -O $tfn $url`;
            } elsif ($^O =~ /freebsd/i) {
                `fetch -q -T 20 -o $tfn $url`;
            }
            if ($? == 0) {
                writeFoafEntry($tfn, $id, $url);
            } else {
                print "      Failed to get FOAF for $id from $url\n";
            }
        } else {
            print OUT;# Save existing entry
        }
    }
    close(EXT);
}


sub usage
{
    my $msg = shift;
    print <<EOF;

$0 Usage:
	$0 <input directory> <output directory> [svn user directory]

Error:
EOF
    die "$msg\n";
}
