package trace_draw;

use strict;
use GD;
use POSIX;
use Class::Struct;

sub DrawTrace() {
    my $TracePts = $_[0];
    my $NumBases = $_[1];

    my @Traces = @{$_[2]};

    my @BasePos = @{$_[3]};
    my @Bases = @{$_[4]};

    my $OutFile = $_[5];

    my $SegmentHeight = $_[6];
    my $SegmentWidth = $_[7];
    
    my $Verbose = $_[8];

    my @Trace1 = @{$Traces[0]};
    my @Trace2 = @{$Traces[1]};
    my @Trace3 = @{$Traces[2]};
    my @Trace4 = @{$Traces[3]};

    if ($Verbose) {print "TracePoints: $TracePts\n";}
    
#    my $SegmentWidth = 700;
    my $TotalWidth = $TracePts;
    my $Width = $SegmentWidth + 20; 
    my $Segments = $TotalWidth / $SegmentWidth;
    $Segments = ceil($Segments);
#    my $SegmentHeight = 120;
    my $Height = ($SegmentHeight * $Segments) + $SegmentHeight;
    
    my $TracePts_per_Segment = $TracePts / $Segments;
    $TracePts_per_Segment = floor($TracePts_per_Segment);

    if ($Verbose) {print "SegmentWidth: $SegmentWidth \n";}
    if ($Verbose) {print "TotalWidht: $TotalWidth \n";}
    if ($Verbose) {print "Width: $Width \n";}
    if ($Verbose) {print "Segments: $Segments\n";}
    if ($Verbose) {print "SegmentHeight: $SegmentHeight\n";}
    if ($Verbose) {print "Height: $Height\n";}
    if ($Verbose) {print "TracePoints: $TracePts\n";}
    if ($Verbose) {print "TracePoints per Segment: $TracePts_per_Segment\n";}
    

    my ($max_height,$mh1,$mh2,$mh3,$mh4)=(0,0,0,0,0);
    for (my $i=0;$i<$TracePts;$i++) {
	if ($mh1 < $Trace1[$i]) {
	    $mh1 = $Trace1[$i];
	}
	if ($mh2 < $Trace2[$i]) {
	    $mh2 = $Trace2[$i]; 
	}
	if ($mh3 < $Trace3[$i]) {
	    $mh3 = $Trace3[$i];
	}
	if ($mh4 < $Trace4[$i]) {
	    $mh4 = $Trace4[$i];
	}

	if ($mh1 > $mh2) {
	    $max_height = $mh1;
	} else {
	    $max_height = $mh2;

	}

	if ($max_height < $mh3) {
	    $max_height = $mh3;
	}

	if ($max_height < $mh4) {
	    $max_height = $mh4;
	}
    }


    if ($Verbose) {print "Max Height: " . $max_height . "\n";}
    my $HeightScale = $SegmentHeight / ($max_height+50);

    my $WidthScale = $SegmentWidth / $TracePts_per_Segment;

    my $im = new GD::Image($Width,$Height);
    my $white = $im->colorAllocate(255,255,255);
    my $red = $im->colorAllocate(255,0,0);
    my $green = $im->colorAllocate(0,255,0);
    my $blue = $im->colorAllocate(0,0,255);
    my $black = $im->colorAllocate(0,0,0);
    my $Magenta = $im->colorAllocate(255,0,255);
    my $Yellow = $im->colorAllocate(51,153,204);

    my %color_by_base = (
			 "A" => $green,
			 "C" => $blue,
			 "G" => $black,
			 "T" => $red,
			 "N" => $black,
			 );

    my ($x, $y);
    my ($x1,$y1,$x2,$y2);
    my $color;
    my $base;

    for (my $j=0;$j<@Traces;$j++) {
	for(my $i=0;$i<$TracePts-1;$i++) {
	    $x1 = $i * $WidthScale;
	    $x2 = ($i+1) * $WidthScale;
	    
	    $x1 %= $SegmentWidth;
	    $x2 %= $SegmentWidth;
	    
	    $y1 = ${$Traces[$j]}[$i] * $HeightScale;
	   $y2 = ${$Traces[$j]}[$i+1] * $HeightScale;
    
    $y1 = $SegmentHeight - $y1;
    $y2 = $SegmentHeight - $y2;
    
    $y1 += (int($i / $TracePts_per_Segment) * $SegmentHeight);
    $y2 += (int(($i+1) / $TracePts_per_Segment) * $SegmentHeight);
    
    if ($j == 0) {$color = $black;}
    elsif ($j == 1) {$color = $green;}
    elsif ($j == 2) {$color = $red;}
    else {$color = $blue;}
	
	    if ( (int($i / $TracePts_per_Segment) == int(($i+1) / $TracePts_per_Segment)) and ($x2 > $x1)) {

	$im->line($x1,$y1,$x2,$y2,$color);
	    }
	    $im->setPixel($x1,$y1,$color);
	}
    }
    
    for (my $i=1;$i<=$NumBases;$i++) {
	$x = $BasePos[$i];
	$x *= $WidthScale;
	$x %= $SegmentWidth;

	$y = int($BasePos[$i] / $TracePts_per_Segment) * $SegmentHeight;

	$base = chr($Bases[$i]);

	$color = $color_by_base{$base};

	$im->string(gdSmallFont, $x, $y, $base, $color);

	if (($i % 10) == 0) {
	    $im->string(gdSmallFont, $x, $y+10, $i, $Yellow);
	}

    }

    my $png_data = $im->png;
    unless ($OutFile) {$OutFile = "out.png";}
    open (FILEOUT,">$OutFile") || die "Can't open output file: $OutFile";
    binmode FILEOUT;
    print FILEOUT $png_data;
    close FILEOUT;


}


return 1;
