#!/usr/bin/perl -w

our $tikzinterval_x;
our $tikzinterval_y;

$tikzlen_x = "0.2cm";
$tikzlen_y = "0.2cm";
$labelspace_x = "0.3cm";
$labelspace_y = "0.3cm";

sub set_data_bounds_from_data {
	my $values = shift;

	foreach $aref ( @$values ) {
		my $x = @$aref[0];
		my $y = @$aref[1];
		if(!defined($minx)) {
			$minx = $maxx = $x;
			$miny = $maxy = $y;
		}
		$minx = $x if $x < $minx;
		$maxx = $x if $x > $maxx;
		$miny = $y if $y < $miny;
		$maxy = $y if $y > $maxy;
	}
}

sub set_data_bounds {
	($minx, $miny, $maxx, $maxy) = @_;
}

sub setup_transforms {
	$addx = -$minx;
	$addy = -$miny;
	$scalex = $box_width / ($maxx - $minx);
	$scaley = $box_height / ($maxy - $miny);
}

sub set_picture_size {
	($box_width, $box_height) = @_;
}

sub outputcoord {
	my $x = shift;
	my $y = shift;
	my $optional = shift;

	$x = ($x + $addx) * $scalex;
	$y = ($y + $addy) * $scaley;
	print("(");
	if(defined($optional)) {
		print("[$optional]");
	}
	print(" $x, $y)");
}

sub outputpoint {
	my $x = shift;
	my $y = shift;
	$x = ($x + $addx) * $scalex;
	$y = ($y + $addy) * $scaley;
	print "\\pgfpoint{${x}cm}{${y}cm}";
}

sub outputbox {
	my ($tikzinterval_x, $tikzinterval_y) = @_;
	setup_transforms();
print <<__EOF__;
	\\begin{scope}
		\\draw (0, 0) rectangle +($box_width, $box_height);
__EOF__

	my $t;
	for($t = $minx; $t < $maxx; $t += $tikzinterval_x) {
		print "\t\t\\node at ";
		outputcoord($t, $miny, "yshift=-$labelspace_x");
		print " { $t };\n";
		print "\t\t\\draw ";
		outputcoord($t, $miny);
		print "\t-- ";
		outputcoord($t, $miny, "yshift=$tikzlen_x");
		print ";\n";
	}

	for($t = $miny; $t < $maxy; $t += $tikzinterval_y) {
		print "\t\t\\node at ";
		outputcoord($minx, $t, "xshift=-$labelspace_y");
		print " { $t };\n";
		print "\t\t\\draw ";
		outputcoord($minx, $t);
		print "\t-- ";
		outputcoord($minx, $t, "xshift=$tikzlen_y");
		print ";\n";
	}

	print <<__EOF__;
	\\end{scope}
__EOF__
}

sub plot {
	my $values = shift;

	print <<__EOF__;
	\\pgfplotstreamstart
__EOF__

	VALUE: foreach $aref ( @$values ) {
		my $x = @$aref[0];
		my $y = @$aref[1];
		next VALUE if !defined($x) || !defined($y);
		next VALUE if $x < $minx or $x >= $maxx or $y < $miny or $y >= $maxy;

		print "\t\t\\pgfplotstreampoint{";
		outputpoint($x, $y);
		print "}\n";
	}

	print <<__EOF__;
	\\pgfplotstreamend
__EOF__
}

sub draw_regression {
	# see http://de.wikipedia.org/wiki/Regressionsanalyse#Berechnung_der_Regressionsgeraden
	my $values = shift;
	my $style  = shift;
	my $start_x = shift;
	my $end_x   = shift;

	if (!defined($start_x)) { $start_x = $minx; }
	if (!defined($end_x)) { $end_x = $maxx; }

	my $avg_x = 0.0;
	my $avg_y = 0.0;
	my $count = 0.0;
	V1: foreach $aref (@$values) {
		my $x = @$aref[0];
		my $y = @$aref[1];
		next V1 if (!defined($x) || !defined($y));

		if ($minx <= $x && $x <= $maxx && $miny <= $y && $y <= $maxy) {
			$avg_x += $x;
			$avg_y += $y;
			$count++;
		}
	}
	$avg_x /= $count;
	$avg_y /= $count;

	my $nominator   = 0.0;
	my $denominator = 0.0;
	V2: foreach $aref (@$values) {
		my $x = @$aref[0];
		my $y = @$aref[1];
		next V2 if (!defined($x) || !defined($y));

		if ($minx <= $x && $x <= $maxx && $miny <= $y && $y <= $maxy) {
			$nominator   += ($x - $avg_x) * ($y - $avg_y);
			$denominator += ($x - $avg_x) * ($x - $avg_x);
		}
	}
	my $b = $nominator / $denominator;
	my $a = $avg_y - $b * $avg_x;

	print "\t\\draw[$style] ";
	outputcoord($start_x, $a + $start_x * $b);
	print "\t-- ";
	outputcoord($end_x, $a + $end_x * $b);
	print ";\n";
}
