#!/usr/bin/perl

use strict;
use DBI;
use CGI;

my @output = ();
my $q = new CGI;
my $dbh = DBI->connect("DBI:mysql:database=fhrating;host=127.0.0.1;", "fhrating", "fhratte");

my $template_page = '
<p class="pagecount">%s</p>
<form method="post">
<input type="hidden" name="page" value="%s">
<input type="hidden" name="user" value="%s">

<!-- Page Text -->
<div class="pagelead"><center><i>Die Umfrage ist seit dem 3. April 2004 zu Ende. Die Fragen sind hier 
zur Referenz weiterhin abrufbar; neue Daten werden nicht mehr gespeichertH.</i></center></div>
<div class="pagelead">%s</div>

<!-- Questions -->
<div class="questionoverall">
%s
</div>

<!-- Buttons -->
<table width="100%%">
<tr>
<td align="left">%s</td>
<td align="right">%s</td>
</tr>
</table>

</form>
';

my $template_question = '<div class="question"><i>Frage %s</i>: %s</div>';
my $template_answer = '<div class="answer">%s</div><hr />';

my $template_dummy =  '<input type="hidden" name="dummy" value="1">';
my $template_button = '%s<input type="submit" name="%s" value="%s">';

my $template_thankyou = '<div class="pagelead">%s</div>';
my $template_error = '<div class="pagelead">Vielen Dank für Ihre Mithilfe beim Fachhochschulrating.<br />
<a href="http://www.fhzh.ch/">Weiter zur Webseite der Hochschule für Wirtschaft und Verwaltung Zürich</a></div>';


# Dummy mode = set tblUsers.uok to 2
my $dummyuser = $q->param('dummy');
if ( $dummyuser eq '' ) {
	undef $dummyuser;
}

# $page contains the current page number (tblSeite.seite). 
# The variable may be changed during script execution, e.g.
# if a user pressed "previous" or "next".
my $page_first_cache = &page_first();
my $page = $q->param('page');

if ($page eq '') {
	$page = $page_first_cache;
}

# $action contains the value of the button
# pressed.
my $action = &find_action();

&output_header();

# $user contains tblUser.uid
my $user = $q->param('user');
if ( !($user eq '') ) {
	if (&IsNumeric($user) eq 0) {
		push(@output, "Fehler.");
		&output_footer();
		&send_output();
		exit 1;
	}
}

	 

# $stackpos contains tblUserStack.order
my $stackorder = $q->param('stackorder');



if ( &user_check() == 1 ) {

	&page_save();

	if ($page == $page_first_cache) {
		&page_begin();
		
	} elsif ( $action eq 'next' ) {
		&page_next();
		if ($page eq &page_last()) {
			&user_save();
			&page_thankyou();
		} else {
			&page_show();
		}
		
	} elsif ( $action eq 'prev' ) {
		&page_prev();
		if ($page == $page_first_cache) {
			&page_begin();
		} else {
			&page_show();
		}
		
	} 

} else {
	&page_error();
	
}

&output_footer();
&send_output();

# # # End of Main


#
# Page / Answer functions
#
sub find_action {
	my $t;
	my $s;
	my $res;
	
	$t = $q->param('next');
	$s = $q->param('prev');

	if (defined($t)) {
		$res = 'next';
	} elsif (defined($s)) {
		$res = 'prev';
	} else {
		$res = 'null';
	}

	return $res;
}

sub page_first {

	my $sql = "select min(page) from tblPages";
	my $sth = $dbh->prepare($sql);
	$sth->execute;
	my ($firstpage) = $sth->fetchrow_array;
	$sth->finish;
	return $firstpage;
}

sub page_last {

	my $sql = "select max(page) from tblPages";
	my $sth = $dbh->prepare($sql);
	$sth->execute;
	my ($lastpage) = $sth->fetchrow_array;
	$sth->finish;
	return $lastpage;
}

sub page_next {
	# Caluclate the next page number -> the
	# next-higher to $page in tblPages

	# FIXME: Add rules to jump to a non-consecutive next-page
	my $sql = "select page from tblPages where page > $page";
	my $sth = $dbh->prepare($sql);
	$sth->execute;
	($page) = $sth->fetchrow_array;
	$sth->finish;
	
	$sql = "insert into tblUserStack (uid, page) values ($user, $page)";
	$dbh->do($sql);

}

sub page_prev {
	# Return the previous page visited by this
	# user from the stack at tblUserStack

	my $sql = "select max(page) from tblUserStack where (uid=$user) and (page < $page) order by page";
	my $sth = $dbh->prepare($sql);
	$sth->execute;
	my @row = $sth->fetchrow_array;
	$sth->finish;
	$page = $row[0];
}

sub page_show {
	# Show all questions on page $page, filling
	# in eventual previous answers by this user
	
	# Add the page shown to tblUserStack
	
	my $sql = "select pagetext from tblPages where page=$page";
	my $sth = $dbh->prepare($sql);
	$sth->execute;
	(my $pagetext) = $sth->fetchrow_array;
	$sth->finish;
	
	my $d;
	if ( defined( $dummyuser ) ) {
		$d = $template_dummy;
	}
	
	my $next_button = sprintf($template_button, $d, 'next', 'Nächste Seite');
	my $prev_button = sprintf($template_button, '', 'prev', 'Vorherige Seite');

	$sql = "select 
				questid, 
				questtext, 
				questtype
			from 
				tblQuestions 
			where 
				page=$page
			order by 
				pageorder";
				
	$sth = $dbh->prepare($sql);
	$sth->execute;
	my $allq;
	my $qcount = 1;
	while (my @question = $sth->fetchrow_array) 
	{
		my $rq = sprintf($template_question, $qcount, $question[1]);
		$allq = $allq . $rq;
		
		$sql = "select 
					questid, 
					value, 
					valuetext,
					position 
				from 
					tblQuestionValues 
				where 
					questid=$question[0]
				order by 
					position";
		my $vsth = $dbh->prepare($sql);
		$vsth->execute;
		
		$sql = "select
					value,
					answer
				from
					tblAnswers
				where
					uid = $user and
					questid = $question[0]";

		my $asth = $dbh->prepare($sql);
		$asth->execute;
		my ($previousvalue, $previousanswer) = $asth->fetchrow_array;
		
		my $valuestring;
		my $sel;
		
		if ( $question[2] eq '1' ) {
		
			# QuestionType 1 -> Radiobuttons
			$sql = "select count(questid) from tblQuestionValues where questid=$question[0]";
			my $nextsth = $dbh->prepare($sql);
			$nextsth->execute;
			my ($count_values) = $nextsth->fetchrow_array;
			my $tdwidth = int(100 / $count_values);
			$nextsth->finish;
			
			
			$valuestring = $valuestring . '<table width="100%">';

			my $titlestring;
			my $valuesstring;
			while (my @values = $vsth->fetchrow_array) {
				if ( $values[1] eq $previousvalue ) {
					$sel = ' checked="checked"';
				} else {
					$sel = '';
				}
				$titlestring = $titlestring . "<td width=\"$tdwidth%\" align=\"center\">$values[2]</td>\n";
				$valuesstring = $valuesstring . "<td width=\"$tdwidth%\" align=\"center\"><input type=\"radio\" name=\"question_$question[0]\" value=\"$values[1]\"$sel></td>\n";
			}
			
			$valuestring = $valuestring . '<tr>' . $titlestring . '</tr><tr>' . $valuesstring . '</tr></table>';
			
		} elsif ($question[2] eq '2') {
		
			# QuestionType 2 -> Dropdown Combobox
			
			$valuestring = "<select name=\"question_$question[0]\">\n";
			
			while (my @values = $vsth->fetchrow_array) {
				if ( $values[1] eq $previousvalue ) {
					$sel = ' selected';
					
				} else {
					$sel = '';
				}
				$valuestring = $valuestring . "<option value=\"$values[1]\"$sel>$values[2]\n";
			}
			
			$valuestring = $valuestring . "</select>\n";
			
		} elsif ($question[2] eq '3') {
		
			# QuestionType 3 -> Text entry field
			# my @values = $vsth->fetchrow_array;
			$previousanswer =~ s/</&lt;/g;
			$previousanswer =~ s/>/&gt;/g;
			$valuestring = "<textarea name=\"question_$question[0]\" cols=\"51\" rows=\"5\">$previousanswer</textarea>\n";
			
		} else {
		
			push(@output, "page_show: Whoops, this should never happen (possibly wrong question type in question $question[0]?)<br>");
		}
		
		$vsth->finish;
		$asth->finish;

		$valuestring = sprintf($template_answer, $valuestring);		
		$allq = $allq . $valuestring;
		
		$qcount++;
	}
	
	
	my $pagestring = &get_pagestring();
	my $renderedpage = sprintf($template_page, $pagestring, $page, $user,  $pagetext, $allq, $prev_button, $next_button);
	push(@output, $renderedpage);
	
}

sub page_save {
	# Save all answers on this page for the 
	# current user

	my $sql = "select 
				questid, 
				questtype
			from 
				tblQuestions 
			where 
				page=$page
			order by 
				pageorder";
				
	my $sth = $dbh->prepare($sql);
	$sth->execute;
	while (my @question = $sth->fetchrow_array) {
		my $value = $q->param("question_$question[0]");
		
		$sql = "delete from tblAnswers where uid=$user and questid=$question[0]";
		$dbh->do($sql);
		
		if ( !( $value eq '' ) )
		{
			if ( !(&IsNumeric($value) ) ) 
			{
				$value =~ s/\'/\&\#039/g;
				$value =~ s/\"/\&\#034/g;
				$value =~ s/;/\&\#059/g;
				# $value =~ s/\#/\&\#035/;
				$sql = "insert into tblAnswers (uid, questid, answer) VALUES ($user, $question[0], '$value')";
			} else {
				$sql = "insert into tblAnswers (uid, questid, value) VALUES ($user, $question[0], $value)";
			}
			$dbh->do($sql);
		}
	}
	$sth->finish;

}

sub page_begin {
	# Show a "let's start" page. The text is taken from
	# the first page description (which should not contain
	# questions
	my $sql = "select pagetext from tblPages where page=$page";
	my $sth = $dbh->prepare($sql);
	$sth->execute;
	my @row = $sth->fetchrow_array();
	$sth->finish;
	
	my $d;
	if ( defined( $dummyuser ) ) {
		$d = $template_dummy;
	}
	my $button = sprintf($template_button, $d, 'next', 'Umfrage starten');
	my $renderedpage = sprintf($template_page, &get_pagestring, $page+1, $user, $row[0], '', '', $button);
	push(@output, $renderedpage);
	
	$sql = "insert into tblUserStack (uid, page) values ($user, $page)";
	$dbh->do($sql);

}

sub page_thankyou {
	# Show a thank you page - it's somewhat different
	# from regular question pages and thus deserves
	# it's own function

	my $sql = "select pagetext from tblPages where page=$page";
	my $sth = $dbh->prepare($sql);
	$sth->execute;
	my @row = $sth->fetchrow_array();
	$sth->finish;

	my $renderedpage = sprintf($template_thankyou, $row[0]);
	push(@output, $renderedpage);	
}

sub page_error {
	# Show an error indicating that the user has
	# already filled in everything and may proceed
	# wanking again.

	push(@output, $template_error);
}

sub get_pagestring {

	my $pagecountsql = "select count(page) from tblPages";
	my $csth = $dbh->prepare( $pagecountsql );
	$csth->execute;
	my ($pagecount) = $csth->fetchrow_array;
	$csth->finish;
	
	my $pagecurrentsql = "select count(page) from tblPages where page <= $page order by page";
	$csth = $dbh->prepare( $pagecurrentsql );
	$csth->execute;
	my ($pagecurrent) = $csth->fetchrow_array;
	$csth->finish;
	
	return "Seite $pagecurrent/$pagecount";

}

#
# User functions
#
sub user_check {
	# If we already have a user, see whether
	# he can still answer stuff. 
	
	# If we don't have a user yet, create one
	# and add the variable

	my $sql;
	my $sth;
	
	if ($user eq '') {
		while ($user eq '') {
			my $id = 10000 + int(rand(90000));
			$sql = "select uid from tblUsers where uid=$id";
			$sth = $dbh->prepare($sql);
			$sth->execute;
			my @row = $sth->fetchrow_array();
			$sth->finish;
			if ($row[0] eq '')
			{
				$user = $id;
			}
		}

		my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
		$year += 1900;
		my $today = sprintf("%4d%02d%2d", $year, $mon, $mday);
		
		my $d;
		if ( defined( $dummyuser ) ) {
			$d = '2';
		} else {
			$d = '0';
		}
		
		# FIXME - uok = 3 seit dem 3.4.2004
		$d = '3';
		
		$sql = "insert into tblUsers (uid, udatum, uip, uok) values 
				($user, \"$today\", \"$ENV{REMOTE_ADDR}\", $d)";
		$dbh->do($sql);
		
		return 1;
		
	} else {
	
		$sql = "select uok from tblUsers where uid=$user";
		$sth = $dbh->prepare($sql);
		$sth->execute;
		my @row = $sth->fetchrow_array();
		$sth->finish;
		if ($row[0] eq '') {
			return 0;
		} elsif ($row[0] eq '1') {
			return 0;
		} elsif ($row[0] eq '0') {
			return 1;
		} elsif ($row[0] eq '2') {
			return 1;
		# FIXME - uok = 3 seit dem 3.4.2004
		} elsif ($row[0] eq '3') {
			return 1;
		} else {
			push(@output, "user_check: Whoops, should never come here<br>");
		}
	}
}

sub user_save {
	# Mark that the current user has answered
	# everything and is not allowed to come
	# back.

	if ( ! defined( $dummyuser ) ) {
		my $sql = "update tblUsers set uok=3 where uid=$user";
		$dbh->do($sql);
	}
	
}


#
# Output Functions
#
sub output_header {
	my $d;
	if ( defined( $dummyuser ) ) {
		$d = ' - <b>TESTLAUF</b>';
	}
	
	push(@output, "Content-Type: text/html\n\n");
	push(@output, "
	<html>
	<head>
		<title>Rating Fachhochschulen</title>
		<link rel=stylesheet type=\"text/css\" href=\"/fhrating.css\">
	    <meta http-equiv=\"Content-Type\" content=\"text/html; charset=iso-8859-1\">
	    <meta name=\"author\" content=\"Myriam Leisi\">
	</head>
	<body>
	<table width=\"100%\">
	<!-- Kopfzeile -->
<!--	<tr>
		<td width=\"20%\">&nbsp;</td>
		<td align=\"center\"><p class=\"pagecount\">Rating Fachhochschulen$d</p></td>
		</td width=\"20%\">&nbsp;</td>
	</tr> -->
	
	<tr>
		<td width=\"20%\" valign=\"top\" style=\"border-top-style: dotted; border-top-width: thin; border-top-color: black;
			border-right-style: dotted; border-right-width: thin; border-right-color: black;\"><!-- linke Spalte --><p class=\"titlestring\">Rating Fachhochschulen</p></td>
		<td style=\"border-bottom-style: dotted; border-bottom-width: thin; border-bottom-color:black;\">
	");
}

sub output_footer {
	my $last = &page_last();
	
	my $debug = "
		<!-- Page: $page<br>
		Firstpage: $page_first_cache<br>
		Lastpage: $last<br>
		Action: $action<br>User: $user --></td>
";
	push( @output, "
	</td> <!-- Ende Content -->
	<td width=\"20%\" valign=\"bottom\">
	$debug
	</tr>
	</body></html>
	" );
}

sub send_output {

	for ( my $i = 0; $i < @output; $i++ ) {
		print $output[$i];
	}
}

#
# Utility Functions
#
sub IsNumeric {
    my $InputString = shift;
	 
    if ($InputString !~ /^[0-9|.|,]*$/) {
    	return 0;
	} else {
		return 1;
	}
}

