#!/usr/bin/perl
#use Mooix::Thing;

# I'd like to use Time::Duration, but I don't haveta.
eval "use Time::Duration";
if ($@) {
        *::ago = sub { return shift()." seconds ago" };
        *::duration = sub { return shift()." seconds" };
}

run sub {
	my $this=shift;
	%_=@_;

	my @ret;
	my @fields=$this->logfields;
	my @format;
	for (my $x=0;$x < $#_; $x+=2) {
		if ($_[$x] eq 'reverse') {
			next;
		}
		print STDERR "--$_[$x] $_[$x+1]\n";
		push @format, $_[$x], $_[$x+1];
	}
	@format = $this->defaultformat unless @format;
	my @headers;
	my %headertype;
	while ($#format > -1) {
		my $header=shift @format;
		push @headers, $header;
		$headertype{$header} = shift @format;
	}
	
	my @table = [map { ucfirst $_ } @headers];
	for (my $x = $this->low_watermark; $x <= $this->high_watermark; $x++) {
		my @values=$this->$x;
		my %values;
		foreach my $field (@fields) {
			$values{$field}=shift @values;
		}

		my @line;
		foreach my $header (@headers) {
			my $val=$values{$header};
			if (! length $val) {
				push @line, $val;
				next;
			}
			my ($headertype, $headerparams) = 
				$headertype{$header} =~ /(\w+)(?:\(([^)]+)\))/;
			if ($headertype{$header} eq 'date') {
				$val = scalar localtime $val;
			}
			elsif ($headertype eq 'duration' &&
			       $headerparams eq 'compact') {
				if (int($val) != 0 || $val eq '0') {
					# Roll my own little
					# pretty-printer..
					my @units = qw(d h m s);
					my @sizes = (60 * 60 * 24, 60 * 60, 60, 1);
					my @bits;
					my $gotone=0;
					while (@bits < 2 && @units) {
						my $unit=shift @units;
						my $size=shift @sizes;
						my $num = int($val / $size);
						if ($num > 0) {
							$val -= $num * $size;
							push @bits, $num.$unit;
							$gotone=1;
						}
						elsif ($gotone) {
							# Ignore smaller
							# units.
							last;
						}
					}
					$val=join(' ', @bits);
				}
			}
			elsif ($headertype eq 'duration') {
				# If it doesn't look like a number,
				# don't try to format it.
				if (int($val) != 0 || $val eq '0') {
					$val = duration($val);
				}
			}
			elsif ($headertype eq 'timeago') {
				if (int($val) != 0 || $val eq '0') {
					$val = ago(time - $val);
				}
			}
			elsif ($headertype eq 'boolean') {
				$val = $val ? "yes" : "no";
			}
			elsif ($headertype eq 'string' && $headerparams > 0) {
				# Limited length string.
				$val = substr($val, 0, $headerparams);
			}
			push @line, $val;
		}
		push @table, \@line;
	}

	# Now pretty format the table.
	my @ret;
	foreach my $col (0..$#headers) {
		# Work out longest field for this column.
		my $longest=0;
		for (my $line = 0; $line <= $#table; $line++) {
			if (length $table[$line][$col] > $longest) {
				$longest=length $table[$line][$col];
			}
		}

		$longest += 2; # a little extra padding
		
		# Add this column to @ret, with padding.
		for (my $line = 0; $line <= $#table; $line++) {
			$ret[$line].=$table[$line][$col];
			$ret[$line].=' ' x ($longest - length $table[$line][$col])
		}
	}
	foreach (@ret) {
		s/\s+$//;
	}

	if ($_{reverse}) {
		@ret=reverse @ret;
        	unshift @ret, pop @ret; # put header back on top
	}
	
	return @ret;
}
