#!/usr/local/bin/perl -w
use strict;
use Getopt::Std;
use Fcntl;

my $diskcache	= "$ENV{HOME}/share/rfc";
my @fetchcmd	= ('/usr/local/bin/wget', '-q');

my $nicmirror	= 'ftp://ftp.demon.nl/pub/mirrors/internic';

my %sources = (
	rfc	=> "$nicmirror/rfc",
	std	=> "$nicmirror/rfc/std",
	fyi	=> "$nicmirror/rfc/fyi",
	bcp	=> "$nicmirror/rfc/bcp",
	draft	=> "$nicmirror/internet-drafts",
);

my %indexes = (
	rfc	=> [ 'rfc-index.txt', $sources{'rfc'} ],
	fyi	=> [ 'fyi-index.txt', $sources{'rfc'} ],
	std	=> [ 'std-index.txt', $sources{'rfc'} ],
	bcp	=> undef,
	draft	=> [ '1id-index.txt', $sources{'draft'} ]
);

my %templates = (
	rfc	=> 'rfc%.txt',
	fyi	=> 'fyi%.txt',
	std	=> 'std%.txt',
	bcp	=> 'bcp%.txt',
);

my @wndexfiles	= ( '.wnindex', 'index.wn' );
my @wndexcmd	= ();
my @flagsset	= ( '/usr/bin/chflags', 'nodump');

#=======================================================================

sub doc_fetch ($$);
sub handle_index ($);
sub usage ($$);
sub update_indices ();
sub view_file ($);

my $type	= 'rfc';	# default
my $options	= 'hft:';
my %opts;
my $sysret	= 0;
my $force	= undef;
my $foo;

my $pager = 'more';
$pager = $ENV{'PAGER'} if exists $ENV{'PAGER'};
my @pager = split(/\s+/, $pager);

chdir($diskcache) or die "Failed to chdir to '$diskcache': $!";

$foo = $0;
$foo =~ s{^.*/}{};
$type = $foo if exists $indexes{$foo};
undef $foo;

usage(1, \*STDERR) if ($#ARGV == -1);
getopts($options, \%opts);
$force = 1		if exists $opts{'f'};
$type = $opts{'t'}	if exists $opts{'t'};
usage(0, \*STDOUT)	if exists $opts{'h'};
undef %opts;

usage(1, \*STDERR) if (not exists $sources{$type});

foreach my $fn (@ARGV) {
	undef $foo;

	if ($fn eq 'index') {
		handle_index($type);
		next;
	}

	if ($fn =~ m/^draft-/ or $type eq 'draft') {
		doc_fetch($fn, $sources{'draft'});

	} elsif ($fn =~ m{^(\w+)-?(\d+)(?:\.txt)$}) {
		if (exists $indexes{$1}) {
			$type = $1;
			$fn = $2;
			$foo = 1;
		} else {
			usage (1, \*STDERR);
		}

	} else {
		usage (1, \*STDERR) unless ($fn =~ m{^\d+$});
		$foo = 1;
	}

	if (defined $foo) {
		usage (1, \*STDERR) unless exists $templates{$type};
		$foo = $templates{$type};
		$foo =~ s{%}{$fn};
		$fn = $foo;
		doc_fetch($fn, $sources{$type});
	}

	view_file($fn);
}

exit($sysret);

#=======================================================================
sub handle_index ($)
{
	my $res;

	if (not defined ${indexes{$type}}) {
		print STDERR "No index available for type '$type'\n";
		++$sysret;
		return;
	}
	if (defined $force or not -e ${indexes{$type}}->[0]) {
		$res = doc_fetch(
			${indexes{$type}}->[0],
			${indexes{$type}}->[1],
		);
		if (not defined $res) {
			print STDERR "Fetch of $type index failed!\n";
			return unless -e ${indexes{$type}}->[0];
		}
	}

	view_file(${indexes{$type}}->[0]);
}

sub doc_fetch ($$)
{
	my $target = shift;
	my $sourceloc = shift;
	my ($oldmask, $flag, $result, $resultstr);

	if (defined $force and -e $target) {
		rename $target, ".${target}-old";
		$flag = 1;
	}
	if (not -e $target) {
		$oldmask = umask 0333;
		system {$fetchcmd[0]} (@fetchcmd, "${sourceloc}/$target");
		$result = $?; $resultstr = "$!";
		umask $oldmask;

		if ($result != 0) {
			print STDERR "Fetch of '$target' failed: $resultstr\n";
			rename ".${target}-old", $target if defined $flag;
			++$sysret;
		} elsif (-z $target) {
			print STDERR "New file '$target' is empty, deleting\n";
			unlink $target;
			rename ".${target}-old", $target if defined $flag;
			++$sysret;
		} else {
			unlink ".${target}-old" if defined $flag;
			system {$flagsset[0]} (@flagsset, $target)
				unless (not scalar @flagsset) or
					($#flagsset == -1);
			update_indices;
			return 1;
		}
	}
	return undef;
}

sub view_file ($)
{
	my $fn = shift;

	if (-t STDOUT) {
		system {$pager[0]} (@pager, $fn);
		++$sysret if $? != 0;
		return;
	}
	if (not sysopen(CAT, $fn, O_RDONLY)) {
		warn "Internal problem; couldn't open '${fn}': %!\n";
		++$sysret;
		return;
	}
	# Don't consider buffering here - laziness
	while (<CAT>) { print $_; }
	close(CAT);
}

sub usage ($$)
{
	my ($exitval, $stream) = @_;
	my $types = '';

	foreach my $k (keys %sources) {
		$types .= "\n             " . $k;
		$types .= ' [no index]' unless defined $indexes{$k};
		$types .= ' [non-numeric]' unless exists $templates{$k};
	}

	print $stream <<"EOUSAGE";
$0: usage: [-$options] index|DOC_number [index|DOC_number ...]
  -h       this help
  -f       force fresh retrieval
  -t type  handling this Type of DOCument.  Current is '$type'.  Choices:$types
EOUSAGE

	exit($exitval);
}

sub update_indices ()
{
	my $b;

	foreach my $f (@wndexfiles) {
		$b=1 if -e $f;
	}

	if (defined $b) {
		system {$wndexcmd[0]} @wndexcmd if scalar @wndexcmd;
	}
}
