#!/usr/bin/perl
use GD;
use Time::Local;
require "../cgi-lib.pl";
ReadParse(*params);

$cachedir = "/home/dave/lego/top_sellers/imgcache";
$cachefile = "tps.$params{min_time}.$params{max_time}.$params{hscale}.$params{vscale}.$params{highlight}.$params{raw}.png";
if(open(CACHE,"$cachedir/$cachefile")) {
    print "Content-Type: image/png\n\n";
    binmode STDOUT;
    while(<CACHE>) { print; }
    close CACHE;
    exit(0);
}
#if($ENV{'REMOTE_ADDR'} =~ /198.183.141.65/) {
#    #idc is ok
#    $params{password} = 1;
#}
if(!$params{password} && $ENV{HTTP_REFERER} !~ /top_sell_form.cgi/) {
#    if($ENV{HTTP_REFERER}) {
	$str = "BAD REF: $ENV{HTTP_REFERER}";
	$img = new GD::Image(10+5*(length $str),15,1);
	$img->fill(10,5,color(223,223,223));
	$img->string(gdTinyFont,5,4,$str,color($c,$c,$c));
	print "Content-Type: image/png\n\n";
	binmode STDOUT;
	print $img->png;
	exit(0);
#    } else {
	print "Content-Type: image/gif\n\n";
	open(FILE,"/home/dave/public_html/images/spacer.gif");
	while(<FILE>) { print; }
	close FILE;
	exit(0);
#    }
}
if($params{max_time}) {
    my(@lt_max) = localtime($params{max_time});
    my(@lt_now) = localtime(time());
    if($lt_max[3] == $lt_now[3] && $lt_max[4] == $lt_now[4] && $lt_max[5] == $lt_now[5]) {
	$cacheme = 0;
    } else {
	$cacheme = 1;
    }
}

my($dir) = '/home/dave/lego/top_sellers';
$hscale = $params{hscale} || 3;
$vscale = $params{vscale} || 15;

my($min) = 0;
if($params{min_time}) { $usrmint = $params{min_time}; $min = $usrmint; }
if($params{max_time}) { $usrmaxt = $params{max_time}; $max = $usrmaxt; }
# First, pull the raw data, and assign it in %data.
opendir(D,$dir);
my(@files) = readdir(D);
foreach my $f (@files) {
    next unless($f =~ /^top\.(\d+)$/);
    my($time) = $1;
    next if($usrmint && $time < $usrmint);
    next if($usrmaxt && $time > $usrmaxt);
    if(!$min || $time < $min) { $min = $time; }
    if($time > $max) { $max = $time; }
    my($timestamp) = tstamp($time);
    $valid_times{$timestamp}++;
    open(F,"$dir/$f");
    while(<F>) {
	chomp;
	my($pos,$id,$name) = split /\t/;
	$data{$id}{place}{$timestamp} = $pos;
	$data{$id}{name} = $name;
    }
    close F;
}
# Now, fill in all the holes from where we don't have data.
# Assume that any empty (but valid) time slot should be populated
# with the previous time slot's data.
$t = $min;
$timestamp = tstamp($t);
#$maxt = tstamp($max);
if(!$usrmaxt) {
    $maxt = tstamp(time());
} else {
    $maxt = tstamp($max);
}
my($testid) = (keys %data)[0];
while($timestamp<=$maxt) {
    foreach my $id (keys %data) {
	if(!$data{$id}{place}{$timestamp}) {
	    if($valid_times{$timestamp}) {
		$data{$id}{place}{$timestamp} = -1; #off the charts!
	    } else {
		$data{$id}{place}{$timestamp} = $last_place{$id};
	    }
	}
	$last_place{$id} = $data{$id}{place}{$timestamp};
    }
    $t += (60*60);
    $timestamp = tstamp($t);
}

#$total_times = scalar(keys %{$data{'10182'}{place}});
$total_times = scalar(keys %{$data{$testid}{place}});
$color = 255;
#$img = new GD::Image(($total_times * $hscale + 150),27*$vscale+30,1);
$img = new GD::Image(($total_times * $hscale + 150),27*$vscale+100,1);
#$img->fill(10,10,color(64,96,192));
$img->fill(10,10,color(223,223,223));
$x = 0;
#Draw the key
#foreach my $ts (sort {$a<=>$b} (keys %{$data{'10182'}{place}})) {
foreach my $ts (sort {$a<=>$b} (keys %{$data{$testid}{place}})) {
    my($y,$m,$d,$h) = unpack('A4A2A2A2',$ts);
    my($mon) = ('Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec')[$m-1];
    #print key
    if($h == 0) {
	my(@tl) = localtime(timelocal(0,0,12,$d,$m-1,$y-1900));
	my($c) = 127;
	if($tl[6] == 6 || $tl[6] == 0) { $c = 0; }
	$img->line($x*$hscale,0,$x*$hscale,$vscale*26,color(191,191,191));
	$img->string(gdTinyFont,$x*$hscale+25,$vscale*26+5,"$mon $d",color($c,$c,$c));
    }
    $x++;
}


@colors = (
	   [255,0,0],
	   [255,63,0],
	   [255,127,0],
	   [255,191,0],
	   [255,255,0],
	   [191,191,0],
	   [127,191,0],
	   [63,191,63],
	   [0,191,127],
	   [0,191,191],
	   [0,191,255],
	   [0,127,255],
	   [0,63,255],
	   [63,0,255],
	   [127,0,255],
	   [191,0,255],
	   [255,0,255],
	   [191,0,191],
	   [127,0,127],
	   [63,0,63],
	   [63,63,63],
	   [95,95,95],
	   [127,127,127],
	   [159,159,159],
	   [191,191,191],
	   [255,255,255],
	   [255,255,255],
	   [255,255,255],
	   [255,255,255],
	   [255,255,255],
	   [255,255,255],
	   [255,255,255],
	   [255,255,255],
	   [255,255,255],
	   [255,255,255],
	   [255,255,255],
	   [255,255,255],
	   [255,255,255],
	   [255,255,255],
	   [255,255,255],
	   [255,255,255],
	   [255,255,255],
	   [255,255,255],
	   [255,255,255],
	   [255,255,255],
	   [255,255,255],
	   [255,255,255],
	   [255,255,255],
	   [255,255,255],
	   [255,255,255],
	   [255,255,255],
	   [255,255,255],
	   [255,255,255],
	   [255,255,255],
	   [255,255,255],
	   [255,255,255],
	   [255,255,255],
	   [255,255,255],
	   );
	   
foreach my $id (keys %data) {
    my(@stats) = ();
    my(@tss) = ();
    foreach my $ts (sort {$a<=>$b} (keys %{$data{$id}{place}})) {
	if($data{$id}{place}{$ts} < 0) {
	    push @stats,26;
	} else {
	    push @stats,$data{$id}{place}{$ts};
	}
	push @tss,$ts;
    }
    $data{$id}{final} = $data{$id}{place}{$maxt};
    my($i,$tot,$cnt);
    for($i=0;$i<@stats;$i++) {
	$tot=0;
	$cnt=0;
	$cnt+=3;
	$tot=3*$stats[$i];
	if($i-1>=0) {
	    $cnt+=2;
	    $tot+=2*$stats[$i-1];
	    if($i-2>=0) {
		$cnt++;
		$tot+=$stats[$i-2];
	    }
	}
	if($i+1<=$#stats) {
	    $cnt+=2;
	    $tot+=2*$stats[$i+1];
	    if($i+2<=$#stats) {
		$cnt++;
		$tot+=$stats[$i+2];
	    }
	}
	$data{$id}{place}{$tss[$i]} = $tot/$cnt unless($params{raw} || $i == $#stats);
    }
}
foreach my $id (sort {
    if($data{$a}{place}{$maxt} < 0) { return 1; }
    if($data{$b}{place}{$maxt} < 0) { return -1; }
    return $data{$a}{place}{$maxt}<=>$data{$b}{place}{$maxt}
} (keys %data)) {
    my($fade) = 0;
    my($bold) = 0;
    if($params{highlight} && $id ne $params{highlight}) {
	$fade = 1;
    } elsif($params{highlight} && $id eq $params{highlight}) {
	$bold = 1;
    }
    #row name
    #$data{$id}{name}
    my($x) = 0;
    my $last_place = undef;
    my @c = @{$colors[$q++]};
    my($q2) = ($q>25) ? $q : ($q+10) % 26;
    my @c2 = @{$colors[$q2]};
#    next if($q > 3);
    if($bold) { $c[0] = 255; $c[1] = 0; $c[2] = 0;
		$c2[0] = 255; $c2[1] = 0; $c2[2] = 0; }
    elsif($q >= 26) { $c[0] = 255; $c[1] = 255; $c[2] = 255;
		      $c2[0] = 255; $c2[1] = 255; $c2[2] = 255; }
    my($str1) = $data{$id}{name};
    my($str2) = $str1;
    for($str_pos=0;$str_pos < length $str2;$str_pos+=2) {
	substr($str2,$str_pos,1) = " ";
    }
    if($fade) {
	$img->filledRectangle($total_times*$hscale,$data{$id}{final}*$vscale-3,$total_times*$hscale+7,$data{$id}{final}*$vscale+4,fade_color($c[0],$c[1],$c[2]));
	if(!($q % 2)) {
	    $img->filledRectangle($total_times*$hscale+4,$data{$id}{final}*$vscale-3,$total_times*$hscale+7,$data{$id}{final}*$vscale,fade_color($c2[0],$c2[1],$c2[2]));
	    $img->filledRectangle($total_times*$hscale,$data{$id}{final}*$vscale+1,$total_times*$hscale+3,$data{$id}{final}*$vscale+4,fade_color($c2[0],$c2[1],$c2[2]));
	}
	$img->string(gdTinyFont,$total_times*$hscale+10,$data{$id}{final}*$vscale-3,$str1,fade_color($c[0],$c[1],$c[2]));
    } else {
	$img->filledRectangle($total_times*$hscale,$data{$id}{final}*$vscale-3,$total_times*$hscale+7,$data{$id}{final}*$vscale+4,color($c[0],$c[1],$c[2]));
	if(!($q % 2)) {
	    $img->filledRectangle($total_times*$hscale+4,$data{$id}{final}*$vscale-3,$total_times*$hscale+7,$data{$id}{final}*$vscale,color($c2[0],$c2[1],$c2[2]));
	    $img->filledRectangle($total_times*$hscale,$data{$id}{final}*$vscale+1,$total_times*$hscale+3,$data{$id}{final}*$vscale+4,color($c2[0],$c2[1],$c2[2]));
	}
	$img->string(gdTinyFont,$total_times*$hscale+10,$data{$id}{final}*$vscale-3,$str1,color($c[0],$c[1],$c[2]));
    }
    my($last_flag) = 1;
    foreach my $ts (sort {$a<=>$b} (keys %{$data{$id}{place}})) {
	my($on_flag);
	if($data{$id}{place}{$ts} < 0 || $data{$id}{place}{$ts} == 26) {
	    $data{$id}{place}{$ts} = 26;
	    $on_flag = 0;
	} else {
	    $on_flag = 1;
	}
	my(@curc) = (!($q%2) && $x%2) ? @c2 : @c;
	if(defined($last_place)) {
	    if($fade) {
		$img->line(
			   ($x-1)*$hscale,
			   $vscale*26-$vscale*(26-$last_place),
			   $x*$hscale,
			   $vscale*26-$vscale*(26-$data{$id}{place}{$ts}),
			   fade_color($curc[0],$curc[1],$curc[2]));
	    } elsif($bold) {
		$img->line(
			   ($x-1)*$hscale,
			   $vscale*26-$vscale*(26-$last_place),
			   $x*$hscale,
			   $vscale*26-$vscale*(26-$data{$id}{place}{$ts}),
			   color($curc[0],$curc[1],$curc[2]));		
		$img->line(
			   ($x-1)*$hscale+1,
			   $vscale*26-$vscale*(26-$last_place),
			   $x*$hscale+1,
			   $vscale*26-$vscale*(26-$data{$id}{place}{$ts}),
			   color($curc[0],$curc[1],$curc[2]));		
		$img->line(
			   ($x-1)*$hscale-1,
			   $vscale*26-$vscale*(26-$last_place),
			   $x*$hscale-1,
			   $vscale*26-$vscale*(26-$data{$id}{place}{$ts}),
			   color($curc[0],$curc[1],$curc[2]));		
		$img->line(
			   ($x-1)*$hscale,
			   $vscale*26-$vscale*(26-$last_place)+1,
			   $x*$hscale,
			   $vscale*26-$vscale*(26-$data{$id}{place}{$ts})+1,
			   color($curc[0],$curc[1],$curc[2]));		
		$img->line(
			   ($x-1)*$hscale,
			   $vscale*26-$vscale*(26-$last_place)-1,
			   $x*$hscale,
			   $vscale*26-$vscale*(26-$data{$id}{place}{$ts})-1,
			   color($curc[0],$curc[1],$curc[2]));		
		
	    } else {
		$img->line(
			   ($x-1)*$hscale,
			   $vscale*26-$vscale*(26-$last_place),
			   $x*$hscale,
			   $vscale*26-$vscale*(26-$data{$id}{place}{$ts}),
			   color($curc[0],$curc[1],$curc[2]));		
	    }
	}
	$last_place = $data{$id}{place}{$ts};
	if(!$on_flag && $last_flag && ($last_place{$id} == 26 || $last_place{$id} == -1)) {
	    #Mark things that go off the list
	    my($str) = "$id $data{$id}{name}";
	    $len = length($str);
	    $img->stringUp(gdTinyFont,($x-1)*$hscale,26*$vscale+10+($len*5),"$str",fade_color($c[0],$c[1],$c[2]));
	}
	$x++;
	$last_flag = $on_flag;
    }
}

if($cacheme && open(CACHE,"> $cachedir/$cachefile")) {
    binmode CACHE;
    print CACHE $img->png;
    close CACHE;
}
print "Content-Type: image/png\n\n";
binmode STDOUT;
print $img->png;

sub tstamp {
    my($time) = @_;
    my(@lt) = localtime($time);
    $lt[5]+=1900;
    $lt[4]++;
    return sprintf("%04d%02d%02d%02d",$lt[5],$lt[4],$lt[3],$lt[2]); #Don't care about minutes/seconds
}

sub get_rgb_value {
    my($min,$mid,$max,$val,$color) = @_;
    
    my($lowr,$midr,$highr) = (255,127,0); #Grey
    if($color eq "r") {    $lowr =  51; $midr = 230; $highr = 204; } #Red
    elsif($color eq "g") { $lowr = 153; $midr = 197; $highr =  51; } #Green
    elsif($color eq "b") { $lowr =  51; $midr =  42; $highr =  34; } #Blue

    #Calculate value
    my($color) =  ((($val-$mid)*($val-$max))/(($min-$mid)*($min-$max)))*$lowr;
    $color += ((($val-$min)*($val-$max))/(($mid-$min)*($mid-$max)))*$midr;
    $color += ((($val-$min)*($val-$mid))/(($max-$min)*($max-$mid)))*$highr;

    #Normalize
    $color = int $color;
    $color = $lowr if($val < $min);
    $color = $highr if($val > $max);
    $color = 255 if($color > 255);
    $color = 0 if ($color < 0);
    return $color;
}

sub fade_color {
    my($r,$g,$b) = @_;
    if(!defined($fpal{"$r\_$g\_$b"})) {
	my($avg) = ($r+$g+$b)/3;
	$fpal{"$r\_$g\_$b"} = color($r+($avg-$r)/2,$g+($avg-$g)/2,$b+($avg-$b)/2);
    }
    return $fpal{"$r\_$g\_$b"};
}

sub color {
    my($r,$g,$b) = @_;
    if(!defined($pal{"$r\_$g\_$b"})) {
        $pal{"$r\_$g\_$b"} = $img->colorAllocate($r,$g,$b);
    }
    return $pal{"$r\_$g\_$b"};
}
