#!/usr/bin/env perl

use strict;
use warnings;
use Text::Table;



my $usage = "Usage: $0 [logfile]\n";
if( exists $ARGV[0] && ($ARGV[0] eq '-h' || $ARGV[0] eq '--help'))
{
    print $usage;
    exit 0;
}



my $table = undef;

# This exists to support interstitial comments that are output without
# alignment. Each chunk is:
#
# - integer index of the line start
# - trailing comment
#
# Lines preceding the legend are stored in the chunk that has index < 0
my @chunks = ( [-1, ''] );
my $Nlines_here = 0;

my @legend;

while(<>)
{
    if( !defined $table )
    {
        if( !/^#[^#!]/ )
        {
            # don't have a legend yet, and this is a ##/#! comment, not a legend
            $chunks[-1][1] .= $_;
        }
        else
        {
            # got legend
            push @chunks, [0,''];
            $Nlines_here = 1;

            chomp;
            s/^# *//;
            @legend = split;

            $legend[0] = "# $legend[0]";

            $table = Text::Table->new(@legend);
        }
        next;
    }

    if( /^#/ || /^\s*$/ )
    {
        # comment. Add to the comment we're accumulating
        $chunks[-1][1] .= $_;
        next;
    }

    # data line
    chomp;
    my @fields = split;
    $table->add(@fields);

    if( length($chunks[-1][1]) == 0 )
    {
        # Data line and we don't have a trailing comment yet. Accumulate
        $Nlines_here++;
    }
    else
    {
        # Our chunk already has a trailing comment, But the new line is a data
        # line. I start a new chunk
        push @chunks, [$chunks[-1][0] + $Nlines_here,
                       ''];
        $Nlines_here = 1;
    }
}

for my $ichunk (0..$#chunks)
{
    my $chunk = $chunks[$ichunk];

    if( $chunk->[0] >= 0)
    {
        # This isn't a comment-only chunk. Those are the pre-legend ##/#! lines
        if($chunk->[0] == 0)
        {
            # Treat the legend specially: I want to center-justify the labels.
            # Can't figure out how to use the library to do that, so I'm doing
            # that manually
            for my $icol(0..$#legend)
            {
                my $textwidth = length($legend[$icol]);
                my ($fieldstart,$fieldwidth) = $table->colrange($icol);

                # I want to center the thing. First column is different
                if($icol == 0 )
                {
                    # line is '# xxx'
                    my ($text) = $legend[$icol] =~ /^# (.*)/;
                    $textwidth -= 2;
                    # margin+textwidth+margin = fieldwidth
                    my $margin0 = int(($fieldwidth - $textwidth) / 2); # rounds down
                    my $margin1 = $fieldwidth - $textwidth - $margin0; # rounds up

                    if($margin1 == 1)
                    {
                        $margin1++;
                        $margin0--;
                    }
                    print( '#' . (' ' x ($margin1-1)) . $text . (' ' x $margin0));
                }
                else
                {
                    # margin+textwidth+margin = fieldwidth
                    my $text = $legend[$icol];
                    my $margin0 = int(($fieldwidth - $textwidth) / 2); # rounds down
                    my $margin1 = $fieldwidth - $textwidth - $margin0; # rounds up
                    print( (' ' x $margin1) . $text . (' ' x $margin0));
                }
                print( ($icol == $#legend) ? "\n" : ' ');
            }

            # done with the legend. Process this chunk from the next line
            $chunk->[0]++;
        }
        print $table->table($chunk->[0],
                            $ichunk != $#chunks ?
                            ($chunks[$ichunk+1][0] - $chunk->[0]) :
                            $Nlines_here);
    }
    print $chunk->[1];
}

__END__

=head1 NAME

vnl-align - aligns vnlog columns for easy interpretation by humans

=head1 SYNOPSIS

 $ cat tst.vnl

 # w x y z
 -10 40 asdf -
 -20 50 - 0.300000
 -30 10 whoa 0.500000


 $ vnl-align tst.vnl

 # w  x   y      z
 -10 40 asdf -
 -20 50 -    0.300000
 -30 10 whoa 0.500000

=head1 DESCRIPTION

The basic usage is

 vnl-align logfile

The arguments are assumed to be the vnlog files. If no arguments are given,
the input comes from STDIN.

This is very similar to C<column -t>, but handles C<#> lines properly:

1. The first C<#> line is the legend. For the purposes of alignment, the leading
   C<#> character and the first column label are treated as one column

2. All other C<#> lines are output verbatim.

=head1 REPOSITORY

https://github.com/dkogan/vnlog/

=head1 AUTHOR

Dima Kogan C<< <dima@secretsauce.net> >>

=head1 LICENSE AND COPYRIGHT

Copyright 2016 California Institute of Technology.
Copyright 2018 Dima Kogan C<< <dima@secretsauce.net> >>

This library is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the Free
Software Foundation; either version 2.1 of the License, or (at your option) any
later version.

=cut
