#!/usr/bin/perl -w
use strict;
use Term::Size;
use integer;
my ($HORIZ, $Y, $MAX);

while(@ARGV)
{
    $_=shift;
    if (/^-h|--horizontal$/) { $HORIZ=1 }
    elsif (/-y|--y-size$/)
    {
        $_=shift and /^(\d+)$/
            or die "-y requires a positive numeric argument.\n";
        $1<=1024 or die "Such an --y-size would be insane.\n";
        $Y=$1;
    }
    elsif (/-m|--max$/)
    {
        $_=shift and /^(\d+)$/
            or die "-m requires a positive numeric argument.\n";
        $MAX=$1;
    }
    else { die "Unknown argument '$_'.\n" };
}

my @data=();
my $max=0;
while (<>)
{
    chomp;
    /^\s*(\d+)\s*$/ or die "Not a number: '$_'\n";
    push @data, (defined $MAX && $1>$MAX) ? $MAX : $1;
    $max=$1 if $1>$max;
}
my $sx = $#data+1;
$sx or die "No data provided.\n";
$max=$MAX if defined $MAX;
$max=1 if !$max; # Accept all-zero data.
$sx<=1024 or die "Sanity check failed: data series more than 1024 wide.\n";
my $sy = $Y ? $Y : $max;
$sy<=1024 or die "Sanity check failed: data above 1024 tall.  Rescale!\n";
$sy = $HORIZ ? ($sy+1)&~1 : ($sy+3)&~3;
my ($ix,$iy) = $HORIZ ? ($sy,$sx) : ($sx,$sy);

if (my $tx=Term::Size::chars *STDOUT{IO})
{
    $ix<=$tx*2 or die "Graph won't fit on your terminal; |cat to ignore.\n";
}

my $bitmap = "";

sub setpix($$)
{
    die "bitmap access out of range\n" if $_[0]>=$ix || $_[1]>=$iy;
    vec($bitmap, $_[0]+$ix*$_[1], 1) = 1;
}

for my $x (0..$#data)
{
    my $v = $data[$x];
    $v=$v*$Y/$max if $Y;
    for my $y (1..$v)
    {
        $HORIZ ? setpix($y-1,$x) : setpix($x,$sy-$y);
    }
}

sub pix($$)
{
    return 0 if $_[0]>=$ix || $_[1]>=$iy;
    return vec($bitmap, $_[0]+$ix*$_[1], 1);
}

sub do_char($$)
{
    my ($x,$y) = @_;
    $x*=2; $y*=4;
    my $g = 0;
    $g+=  1 if pix($x  ,$y  );
    $g+=  8 if pix($x+1,$y  );
    $g+=  2 if pix($x  ,$y+1);
    $g+= 16 if pix($x+1,$y+1);
    $g+=  4 if pix($x  ,$y+2);
    $g+= 32 if pix($x+1,$y+2);
    $g+= 64 if pix($x  ,$y+3);
    $g+=128 if pix($x+1,$y+3);
    # print Unicode codepoint 0x2800+$g, as UTF-8.
    printf("%c%c%c", 0xe2, 0xa0+$g/64, 0x80+$g%64);
}

for my $cy (0..($iy-1)/4)
{
    for my $cx (0..($ix-1)/2)
    {
        do_char($cx, $cy);
    }
    print "\n";
}
