#!__PERL__
# -*- perl -*-

# Copyright (c) 2002 by Jeff Weisberg
# Author: Jeff Weisberg <argus @ tcp4me.com>
# Date: 2002-Nov-01 11:54 (EST)
# Function: lay paint on canvas. make pretty graphs.
#
# $Id: picasso.pl,v 1.15 2005/04/09 01:22:47 jaw Exp $

# Computers are useless. They can only give you answers.
#   -- Picasso

use lib('__LIBDIR__');
require "conf.pl";
use Chart::Strip;
use GraphData;
use Getopt::Std;
use GD;
getopts('bBc:C:D:gGlL:r:R:s:S:t:Tw:x:y:');

$which = $opt_w;
$size  = $opt_s;
binmode STDOUT;
$| = 1;

my @labels = split /\s+/, $opt_C;

# What is your favorite color?
# Blue.  No yel--  Auuuuuuuugh!
#   -- Monty Python, Holy Grail
my @colors  = qw(00FF00 DD33DD 00FFFF FFAAAA AAFFAA AAAAFF
		 FFCC44 FF44CC 44CC88 88CC44 4488CC 8844CC);
usecolors($opt_c) if $opt_c;

my @imgopts = (
	       transparent  => ($opt_T || 0),
	       draw_border  => ($opt_B || 0),
	       draw_grid    => ($opt_g || 0),
	       binary       => ($opt_b || 0),
	       logscale     => ($opt_l || 0),	# NYI
	       grid_on_top  => ($opt_G || 0),
	       limit_factor => 4,
	       data_label_style => $opt_L,
	       );

if( $size eq 'thumb' ){
    push @imgopts, (width => 160, height => 64);
    push @imgopts, (draw_data_labels => 0, draw_tic_labels => 0 );
}else{
    push @imgopts, (width => 640, height => 192, margin_right => 16);
    push @imgopts, (title => $opt_t) if $opt_t;
    push @imgopts, (x_label => $opt_x) if $opt_x;
    push @imgopts, (y_label => $opt_y) if $opt_y;
}

my $img = Chart::Strip->new( @imgopts );

# mode1: '', minmax, stddev
# mode2: line, filled

if( @ARGV > 1 ){
    $mode2 = 'line';
}else{
    $mode2 = $which eq 'samples' ? 'filled' : 'line';
}
$mode1 = $which eq 'samples' ? '' : $opt_S;
$mode1 = '' if $mode1 eq 'none';


my $colorn = 0;
foreach my $n (@ARGV){
    my $m = GraphData->new($n);
    my $color = color($colorn++);
    my $label = shift @labels;
    
    if( $which eq 'samples' ){
	$m->readsamples( $opt_R );
	$img->add_data( $m->{samples}, {style => $mode2, color => $color, label => $label} );
    }else{
	$m->readsummary( $which, 576, $opt_R );	# max 576 points (~ 3 weeks)

	if( $mode1 eq 'minmax' ){
	    $img->add_data( $m->{samples}, {style => 'range', color => 'blue'} );
	}
	if( $mode1 eq 'stddev' ){
	    foreach my $s ( @{$m->{samples}} ){
		$s->{min} = $s->{ave} - $s->{stdv};
		$s->{max} = $s->{ave} + $s->{stdv};
	    }
	    $img->add_data( $m->{samples}, {style => 'range', color => 'blue'} );
	}
	
	$img->add_data( $m->{samples}, {style => $mode2, color => $color, label => $label} );
    }
}

# ICK - reorder data: put range graphs 1st
my @d;
push @d, grep { $_->{opts}{style} eq 'range' } @{$img->{data}};
push @d, grep { $_->{opts}{style} ne 'range' } @{$img->{data}};
$img->{data} = \@d;

setrange( $img, $opt_r ) if $opt_r;
$img->plot();

if( $size ne 'thumb' ){
    logoize($img);

    if( $mode1 ){
	my $im = $img->gd();
	my $y  = $img->{margin_top} > 12 ? 2 : -2;
	$im->string(gdSmallFont, 4,  $y, "ave",   $img->{color}{green});
	$im->string(gdSmallFont, 24, $y, $mode1,  $img->{color}{blue});
    }
}


#..., then draw the model;
#   -- Shakespeare, King Henry IV
print $img->png();
exit 0;

sub error {
    my $msg = shift;
    my $im;

    print STDERR "picasso: ERROR $msg\n";
    
    $im = new GD::Image(160, 64);
    my $blk = $im->colorAllocate(0,0,0);
    my $red = $im->colorAllocate(0xFF,0x88,0x88);

    $im->filledRectangle(0,0, 159,63, $red);
    $im->rectangle(0,0, 159,63, $blk);
    $im->string(GD::gdMediumBoldFont, 4, 2, 'PICASSO: GRAPH ERROR', $blk);
    my @a = grep {$_ || ()} split /(.{25})/, $msg;
    my $y = (@a > 1) ? 16 : 40;
    foreach (@a){
	s/^\s+//;
	$im->string(GD::gdSmallFont, 4, $y, $_, $blk);
	$y += 10;
    }
    
    print $im->png();

    exit -1;
}

sub color {
    my $n = shift;

    return 'green' if @ARGV == 1;
    $colors[ $n % @colors ];
}

# Nor long the sun his daily course withheld, 
# But added colors to the world reveal'd: 
# When early Turnus, wak'ning with the light, 
#   -- Virgil, Aeneid
sub usecolors {
    my $cs = shift;
    my @c;

    @c = split /\s+/, $cs;
    unshift @colors, @c;
}

# I hear beyond the range of sound,
# I see beyond the range of sight,
# New earths and skies and seas around,
# And in my day the sun doth pale his light.
#   -- Thoreau, Inspiration
sub setrange {
    my $img = shift;
    my $r   = shift;
    my( $l, $h, $x ) = split /\s*-\s*/, $r;

    ($l, $h) = (-$h, $x) if $l eq '';
    $h = -$x if $h eq '';

    $img->set_y_range($l, $h);
}

sub logoize {
    my $img = shift;
    my $im = $img->gd();

    # Aldeborontiphoscophornio! Where left you Chrononhotonthologos?
    #   -- Henry Carey, Chrononhotonthologos
    my @data = ([1, 80, 2], [4, 79, 0], [2, 78, 1], [4, 77, 0], [1, 76, 3], [2, 74, 1], [4, 73, 0],
    [1, 73, 0], [4, 72, 0], [1, 72, 0], [2, 71, 1], [4, 69, 0], [1, 69, 0], [4, 68, 0], [1, 68, 0],
    [4, 67, 0], [1, 67, 0], [2, 66, 1], [1, 63, 1], [1, 62, 1], [3, 59, 0], [1, 59, 0], [3, 58, 1],
    [1, 58, 0], [4, 57, 0], [1, 57, 1], [2, 56, 1], [1, 55, 2], [4, 54, 0], [2, 53, 1], [4, 52, 0],
    [1, 51, 3], [3, 49, 0], [1, 48, 5], [5, 47, 0], [3, 47, 0], [3, 46, 1], [3, 44, 0], [4, 43, 0],
    [2, 43, 0], [4, 42, 0], [2, 42, 0], [0, 41, 4], [4, 39, 0], [1, 39, 0], [4, 38, 0], [1, 38, 0],
    [4, 37, 0], [1, 37, 0], [2, 36, 1], [2, 34, 0], [4, 33, 0], [1, 33, 0], [2, 32, 4], [4, 31, 0],
    [1, 28, 1], [1, 27, 1], [4, 24, 0], [2, 24, 0], [4, 23, 0], [1, 23, 1], [3, 22, 1], [1, 22, 0],
    [3, 21, 0], [1, 21, 0], [1, 19, 3], [2, 18, 0], [1, 17, 0], [2, 16, 2], [1, 14, 3], [4, 13, 0],
    [2, 13, 0], [0, 13, 0], [4, 12, 0], [2, 12, 0], [0, 12, 0], [3, 11, 0],  [3, 9, 0],  [4, 8, 0],
    [3, 7, 0],   [1, 6, 3],  [1, 4, 3],  [4, 3, 0],  [2, 3, 0],  [4, 2, 0],  [1, 2, 0],  [2, 1, 1] );
    
    foreach my $l (@data){
	foreach my $i ($l->[0] .. $l->[0] + $l->[2]){
	    $im->setPixel($img->{width} - 9 + $i, 2 + $l->[1], $img->{color}{gray});
	}
    }
}

