#!/usr/bin/perl -w

###################################################################################################
#	TEMPERATURE_FIGURE.CGI
#	
#	Denne filen behandler data mottatt fra "TEMPERATUR_PAGE.CGI" ( som igjen mottar disse dataene fra 
#	brukerprogrammet SENSOR_FORM.CGI ), og genererer en graf over en gitt tid ut fra disse dataene.
#	Mottatte data er YEAR, MONTH, DAY, PERIODE, MIDDLE, MIN OG MAX.
#	
#	YEAR, MONTH og DAY angir starttid for når grafen skal tegnes. 
#	PERIODE er enten 24_HOURS, WEEK, MONTH eller YEAR og angir hvor langt grafen skal tegnes i
#	forhold til starttid.
#	MIDDLE, MIN OG MAX angir hva som skal tegnes i gitt PERIODE ( en eller flere av disse kan være 
#	valgt av bruker). 
#
#	Programmet består av seks subrutiner
#	
#		- day_data($year, $month, $day, $min, $max, $middle )
#		- week_data($year, $month, $day, $min, $max, $middle )
#		- month_data($year, $month)
#		- year_data($year)
#		- error($x, $y, $string, $string2 )
#		- $drawGraph()
#
#	Avhengig av PERIODE og MIDDLE, MIN og MAX ( når og hva som skal plottes ) vil subrutinene 
#	day_data(..) og week_data(..) plukke ut ønsket data fra databasen HESSDALEN.TEMPERATUR_BEREGNET og
#	legge disse dataene i det globale arrayet @data. Videre vil så subrutinen drawGraph() tegne 
# en graf for disse dataene. Dersom en feil oppstår ( f.eks feil periode - ingen data i db o.l )
#	vil subrutinen error(..) slå til. error(..) genererer et bilde basert på sine fire argumenter, der
#	de to første angir plassering, (x,y), for hvor de siste argumentene ( string og string2 ) skal
#	skrives ut.
#
#	month_data() og year_data() henter ut alleredeeksisterende bilder fra katalogen images.
#
###################################################################################################

use strict;
use CGI ":standard";
use GD::Text;
use GD;
use GD::Graph::lines;
use Pg;
use Time::ParseDate;

my @legends;
my @data;
my $year = url_param('year');
my $day = url_param('day');
my $month = url_param('month');
my $min = url_param('min');
my $middle = url_param('middle');
my $max = url_param('max');
my $title;
my $y_label;
my $x_label;
my $x_label_skip;
my $x_label_vertical;
my $status = 0;
my $correct_width;

if(url_param('periode') eq '24_HOURS'){
	#year, month, day, min, maks, mid
	if(defined(&day_data( $year, $month, $day, $min, $max, $middle ))) {
		&drawGraph();		
	} else {
		&error(10,10, "There are no data registred in the database for this period.", "Try again...");
	}
}elsif(url_param('periode') eq 'WEEK'){
	#year, month, day, min, maks, mid
	if(defined(&week_data( $year, $month, $day, $min, $max, $middle ))) {
		&drawGraph();		
	} else {
		&error(10,10, "There are no data registred in the database for this period.", "Try again...");
	}
}elsif(url_param('periode') eq 'MONTH'){
	#year, month, day, min, maks, mid
	if(defined(&month_data( $year, $month ))) {
		exit;
		#&drawGraph();		
	} else {
		&error(10,10, "There are no data registred in the database for this period.", "Try again...");
	}
}elsif(url_param('periode') eq 'YEAR'){
	#year, month, day, min, maks, mid
	if(defined(&year_data( $year ))) {
		exit;
		#&drawGraph();		
	} else {
		&error(10,10, "There are no data registred in the database for this period.", "Try again...");
	}
	
}else{
	&error(10,10, "There are no data for this length", "Try again");
}


#############################
#
#		SUBRUTINER
#
#############################


#############################
#ERROR-MELDING
#############################
sub error{
		my ($x, $y, $error_message, $error_message2 ) = @_;
		#Dersom det ikke er oppgitt noen ønkset min, maks eller middle 
		#lages et enkelt bilde med feilmelding i.
		my $im = new GD::Image(600,400);
		#Farger
		my $bakgrunn 	= $im->colorAllocate(232,	246,	250);
		my $white		 	= $im->colorAllocate(255,	255,	255);
		my $black 		= $im->colorAllocate(0,		0,		0);
		$im->filledRectangle(1,1,599,399,$bakgrunn);
		
		#Plasserer feilmelding i bildet.
		$im->string(gdMediumBoldFont,$x,$y,$error_message, $black);
		$im->string(gdMediumBoldFont,10,$y+14,$error_message2, $black);
		
		print("Content-type: image/png\n\n");
		print $im->png;
		exit;
}

#############################
#UKES-DATA
#############################
sub week_data {
	#Mottatte data
	my ($from_year, $from_month, $from_day, $usemin, $usemax, $usemid) = @_;
	
	#Dersom bruker ikke har oppgitt ønskede data - returner
	($usemin == 0) && ($usemax == 0) && ($usemid == 0) && return undef;
  
	#Oppkobling til database
	my $dbconn = Pg::connectdb("dbname=hessdalen");

	($dbconn->status == PGRES_CONNECTION_BAD) && return undef;

	my $from_time = parsedate("$from_day.$from_month.$from_year", UK=>1);
	my $to_time = parsedate("+ 1 week", NOW => $from_time);

	my ($to_sec,$to_min,$to_hour,$to_mday,$to_mon,$to_year,$to_wday,$to_yday,$to_isdst) = localtime($to_time);

	my $from = $from_year*10000 + $from_month*100 + $from_day;
	my $to = ($to_year+1900)*10000 + ($to_mon+1)*100 + $to_mday;

	my $res = $dbconn->exec("SELECT aar, maaned, dag, time, minverdi, middelverdi, maksverdi
		FROM temperatur_beregnet
		WHERE aar*10000+maaned*100+dag>=$from AND aar*10000+maaned*100+dag < $to
		ORDER BY aar, maaned, dag, time"
	);
	
	($res->resultStatus != PGRES_TUPLES_OK) && return undef;

	($res->ntuples == 0) && return undef;

	$title		= sprintf ( "Temperature for %02d.%02d.%d - %02d.%02d.%d" , $from_month, $from_day,$from_year, ($to_mon+1), ( $to_mday-1 ), ($to_year+1900) );
	$x_label	= "Time - [ month.day - hour ]";
	$y_label	= "Temperature in Celsius degree";
	$x_label_skip  = 4;
	$x_label_vertical = 1;	
	$correct_width= 1;	

	my @xvalues = ();
	my @mindata = ();
	my @middata = ();
	my @maxdata = ();

	for(my $tup=0, my $i=0; $from_time < $to_time; $i++) {
		my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($from_time);

		my $date = sprintf("%2d.%02d - %2d", ( $mon + 1 ), $mday ,$hour );
		push @xvalues, $date;


		if($tup < $res->ntuples && $res->getvalue($tup, 0) == ($year+1900) &&
			$res->getvalue($tup, 1) == ($mon+1) && $res->getvalue($tup, 2) == $mday &&
			$res->getvalue($tup, 3) == $hour) {	

			push @mindata, $res->getvalue($tup, 4);
			push @middata, $res->getvalue($tup, 5);
			push @maxdata, $res->getvalue($tup, 6);
			$tup++;
		} else {
			push @mindata, undef;
			push @middata, undef;
			push @maxdata, undef;	
		}
	
		$from_time = parsedate("+ 1 hour", NOW => $from_time);
	}

	push @data, [@xvalues];

	($usemin == 1) && push @legends, "Min";
	($usemid == 1) && push @legends, "Mid";
	($usemax == 1) && push @legends, "Max";

	($usemin == 1) && push @data, [@mindata];
	($usemid == 1) && push @data, [@middata];
	($usemax == 1) && push @data, [@maxdata];

	return 1;
}

#############################
#DAG-DATA
#############################
sub day_data {
	#Mottatte data
	my ($from_year, $from_month, $from_day, $usemin, $usemax, $usemid) = @_;
	
	#Dersom bruker ikke har oppgitt ønsket data - returner
	($usemin == 0) && ($usemax == 0) && ($usemid == 0) && return undef;

	#Oppkobling til database
	my $dbconn = Pg::connectdb("dbname=hessdalen");

	($dbconn->status == PGRES_CONNECTION_BAD) && return undef;

	my $res = $dbconn->exec("SELECT time, minverdi, middelverdi, maksverdi
		FROM temperatur_beregnet
		WHERE aar=$from_year AND maaned=$from_month AND dag=$from_day
		ORDER BY time"
	);

	($res->resultStatus != PGRES_TUPLES_OK) && return undef;

	($res->ntuples == 0) && return undef;

	#Globale variabler for graf.
	$title		= sprintf ("Temperature for %02d.%02d.%d", $from_month, $from_day, $from_year );
	$x_label	= "Time - [ hours ]";
	$y_label	= "Temperature in Celsius degree";
	$x_label_skip = 0;
	$x_label_vertical = 0;
	$correct_width= 1;

	#Ønskede intervaller ( fra periode - til periode ) - brukes i sql setning nedenfor.
	my $from_time = parsedate("$from_day.$from_month.$from_year", UK=>1);
	my $to_time = parsedate("+ 1 day", NOW => $from_time);
	
	#Tabeller for dataer som skal vises i graf
	my @xvalues = ();
	my @mindata = ();
	my @middata = ();
	my @maxdata = ();

	for(my $tup=0, my $i=0; $from_time < $to_time; $i++) {
		my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($from_time);
		
		#Push time til @xvalues -> det som vises på x-akse.
		push @xvalues, $hour; 

		#Dersom time i db = ønsket time fra $from_time legges data i @mindata - @maxdata
		#ellers udefinert -> Vises ikke i graf
		if($tup < $res->ntuples && $res->getvalue($tup, 0) == $hour) {	
			push @mindata, $res->getvalue($tup, 1);
			push @middata, $res->getvalue($tup, 2);
			push @maxdata, $res->getvalue($tup, 3);
			$tup++;
		} else {
			push @mindata, undef;
			push @middata, undef;
			push @maxdata, undef;	
		}

		#Øker $fromdata med en time.
		$from_time = parsedate("+ 1 hour", NOW => $from_time);
	}

	#Legger data i den globale tabellen @data. Denne benyttes så for tegning av grafen i drawGraph().
	push @data, [@xvalues];
	
	#Legends - angir "datas tilhørende fargekombinasjon" i grafen.
	($usemin == 1) && push @legends, "Min";
	($usemid == 1) && push @legends, "Mid";
	($usemax == 1) && push @legends, "Max";

	($usemin == 1) && push @data, [@mindata];
	($usemid == 1) && push @data, [@middata];
	($usemax == 1) && push @data, [@maxdata];

	return 1;
}

#############################
#ÅR-DATA
#############################
sub year_data {
	#Mottatte data
	my ($from_year )  = @_;
	
	my $fileref = sprintf( "images/year_%4d.png", $from_year );
	open (PNG, $fileref ) || return undef; 
	my  $yearimg = newFromPng GD::Image(\*PNG) || return undef;
	close PNG;
	print("Content-type: image/png\n\n");
	print $yearimg->png || return undef;		
	
}


#############################
#MÅNEDS-DATA
#############################
sub month_data {
	#Mottatte data
	my ($from_year, $from_month ) = @_;

	my $fileref = sprintf( "images/month_%4d%02d.png", $from_year, $from_month );
	open (PNG, $fileref ) || return undef; 
	my  $monthimg = newFromPng GD::Image(\*PNG) || return undef;
	close PNG;
	print("Content-type: image/png\n\n");
	print $monthimg->png || return undef;		
}

#############################
#SELVE FIGURTEGINGEN
#############################
sub drawGraph{
	
	#Oppretter ny figur - graf bestående av linjer.
	my $graph = GD::Graph::lines->new(600,400);
	
	#Farger og font.
	$graph->set_text_clr('#000000');
	$graph->set_title_font(		'/home/hessdalen/html/ams_ny/vaerstasjon/font/courbd.ttf',14);
	#$graph->set_x_label_font(	'/home/hessdalen/html/ams_ny/vaerstasjon/font/courbd.ttf',10);
	#$graph->set_y_label_font(	'/home/hessdalen/html/ams_ny/vaerstasjon/font/courbd.ttf',10);
	$graph->set_legend_font(	'/home/hessdalen/html/ams_ny/vaerstasjon/font/courbd.ttf',8);
	
	#"Fargesammensetning" for de forskjellige grafene som vises i samme figur - basert på den globale 
	#tabellen @legends.
	$graph->set_legend(@legends);

	#Oppsett av grafen - hvordan den ser ut.
	$graph->set(
		labelclr					=>	'black',
		textclr						=>	'black',
		title							=>	$title,
		transparent				=>	1,
		interlaced				=>	0,
		fgclr							=>	'#4395a5',
		bgclr							=>	'#e8f6fa',
		boxclr						=>	'#e8f6fa',
		borderclrs				=>	'undef',
		t_margin					=>	10,
		r_margin					=>	10,
		l_margin					=>	10,
		b_margin					=>	0,
		tick_length				=>	4,
		long_ticks				=>	1, 
		zero_axis					=>  0, 
		zero_axis_only		=>	0, 
		box_axis					=>	0,
		axis_space				=>	4,
		line_width				=>	2,
		line_types				=>	[1,1,1,1],
	
		x_label_position 	=>	1,
		x_label						=>	$x_label,
		x_label_skip			=>	$x_label_skip,	
		x_all_ticks				=> 	0,
		x_tick_offset			=>  0,
		correct_width			=>	$correct_width,
		x_plot_values			=>	1, 
		x_labels_vertical	=>	$x_label_vertical,
	
		y_label_position	=>	1,
		y_label						=>	$y_label,
		y_tick_number			=>	10,
		y_label_skip			=>	0,
		overwrite					=>	0
	);
	
	#Plotter graf med datasettet @data - inneholder data for enten day_data(), week_data(), month_data()
	#eller year_data() 	
	my $gd = $graph->plot(\@data);
	
	print("Content-type: image/png\n\n");
	print $gd->png;

}
