#!/usr/bin/perl
#
# Catch22 (llama@osoal.org.nz)
# One Short Of A Llama [http://web.osoal.org.nz]

# create table pollquestions
# (
#    pid      tinytext,
#    question tinytext,
#    votes    int unsigned default 0,
#    time     int unsigned
# );
#
# create table pollanswers
# (
#    pid    tinytext,
#    aid    int unsigned,
#    answer tinytext,
#    votes  int unsigned default 0
# );
#
# create table pollvotes
# (
#    pid    tinytext,
#    ipaddr varchar(15),
#    aid    int unsigned
# );

#
use strict;
use DBI;
use OneShortOfALlama;

#
my($load);

#
$load = 20;

#
sub current_poll
{
	my($pid, $dbh);

	$dbh = shift(@_);
	$pid = $dbh->selectrow_array('select pid from osoal.pollquestions order by time desc limit 1');

	return ($pid);
}

sub print_poll
{
	my($dbh, $gid, $pid, $sth, $width, $question, $param, $i,
	   $qvotes, $answer, $avotes, $percent, $aid, $voted, $current);

	#
	foreach $i ($dbh, $gid, $param)
	{
		$i = shift(@_);
	}

	$pid = $dbh->quote($param->{'pid'});

	($question, $qvotes)
		= $dbh->selectrow_array("select question, votes 
                                 from osoal.pollquestions where (pid = $pid)");

	unless ($question)
	{
		print('Invalid Poll');
		return ();
	}

	#
	$current = current_poll($dbh);

	#
	print('<br>
           <div align="center">', "\n\n");

	#
	print('[ ');

	if ($param->{'pid'} eq $current)
	{
		print('<a href="', $ENV{'SCRIPT_NAME'}, '?select=Vote&pid=', $param->{'pid'}, '"><b>Vote</b></a>');
	}
	else
	{
		print('<a href="', $ENV{'SCRIPT_NAME'}, '?pid=', $current, '"><b>Current Poll</b></a>');
	}

	if ($gid == 1)
	{
		print(' | <a href="', $ENV{'SCRIPT_NAME'}, '?select=Modify&pid=', $param->{'pid'}, '"><b>Modify</b></a>
                | <a href="', $ENV{'SCRIPT_NAME'}, '?select=Delete&pid=', $param->{'pid'}, '"><b>Delete</b></a>');
	}

	#
	print(' | <a href="', $ENV{'SCRIPT_NAME'}, '"><b>Poll Archive</b></a>
            | <a href="/search.pl?location=Polls"><b>Search</b></a> ]<br>
           <br>', "\n\n");

	#

	$voted = $dbh->selectrow_array("select aid from osoal.pollvotes
                                  where (pid = $pid && ipaddr = '$ENV{'REMOTE_ADDR'}')");

	#
	if ($param->{'aid'} =~ m/^\d+$/)
	{
		if (!$voted)
		{
			if ($param->{'pid'} eq $current)
			{
				if ($param->{'aid'} < 1 ||
					$param->{'aid'} > $dbh->selectrow_array("select count(*) from osoal.pollanswers
                                                             where (pid = $pid)"))
				{
					print('Vote out of range');
				}
				else
				{
					$dbh->do("update osoal.pollquestions set votes = votes + 1
                              where (pid = $pid)");

					$dbh->do("update osoal.pollanswers set votes = votes + 1
                              where (pid = $pid && aid = $$param{'aid'})");

					$dbh->do("insert into osoal.pollvotes (pid, ipaddr, aid)
                              values ($pid, '$ENV{'REMOTE_ADDR'}', $$param{'aid'})");

					$qvotes++;

					print('Your vote has been registered');
					$voted = $param->{'aid'};
				}
			}
			else
			{
				print('You may not vote in this poll');
			}
		}
		else
		{
			print('You have already voted');
		}
	}

	print('<br>
           <br>
           <font size="+2"><em><b>', $question, '</b></em></font>
           </div>
           <br>', "\n\n");

	
	#
	$sth = $dbh->prepare("select aid, answer, votes from osoal.pollanswers
                          where (pid = $pid) order by aid");
	$sth->execute();

	#
	print('<table width="600">', "\n\n");

	while (($aid, $answer, $avotes) = $sth->fetchrow_array())
	{
		if ($voted == $aid)
		{
			$answer = "<b>$answer</b>";
		}

		print('<tr>
               <td width="250" align="right">', $answer,
			  ' (', $avotes, '&nbsp;vote', ($avotes == 1 ? '' : 's'), ')</td>', "\n");

		#
		if ($qvotes)
		{
			$percent = sprintf("%.1f", ($avotes / $qvotes) * 100);
			$width   = int($percent * 3);
		}
		else
		{
			$percent = '0.0';
			$width   = 5;
		}

		print('<td width="350" align="left">
                   <img src="/pics/misc/vote.jpg"
                        height="20" width="', $width, '" alt=""> ', $percent, '%</td>
               </tr>', "\n\n");
	}

	#
	print('</table>
           <br>
           <div align="center">
           <font size="+1"><b>', $qvotes, ' vote', ($qvotes == 1 ? '' : 's'), '</b></font>
           </div>', "\n\n");
}

sub list_polls
{
	my($dbh, $pid, $load, $gid, $question, $votes, $time, $sth, $i);

	#
	foreach $i ($dbh, $gid, $load)
	{
		$i = shift(@_);
	}

	#
	print('<form method="GET" action="', $ENV{'SCRIPT_NAME'}, '">
           <div align="center">
           [ <a href="', $ENV{'SCRIPT_NAME'}, '?pid=', current_poll($dbh), '"><b>Current Poll</b></a>
           | <b>Display</b> <input type="text" name="load" value="', $load, '" size="3">
             <b>Polls</b>');

	#
	if ($gid == 1)
	{
		print(' | <a href="', $ENV{'SCRIPT_NAME'}, '?select=Create"><b>Create</b></a>');
	}

	print(' | <a href="/search.pl?location=Polls"><b>Search</b></a> ]
           </div>
           </form>', "\n\n");

	#
	$sth = $dbh->prepare('select pid, question, votes, from_unixtime(time, "%D %M, %Y")
                          from osoal.pollquestions
                          order by time desc' . ($load > -1 ? " limit $load" : ''));
	$sth->execute();

	unless ($sth->rows())
	{
		return ();
	}

	$sth->bind_columns(undef(), \$pid, \$question, \$votes, \$time);

	while ($sth->fetch())
	{
		$question =~ s/<[^>]*>//g;

		print('<li><a href="', $ENV{'SCRIPT_NAME'}, '?pid=', $pid, '"><b>', $question, '</b></a>
                (', $votes, ' vote', ($votes == 1 ? '' : 's'), ') on ', $time, '</li><br>', "\n");
	}
}

sub input_poll
{
	my($select, $pid, $question, $answers, $i, $sth, $dbh, $param);

	#
	$dbh   = shift(@_);
	$param = shift(@_);
	
	#
	print('<form method="POST" action="', $ENV{'SCRIPT_NAME'}, '">');

	#
	if ($param->{'select'} eq 'Modify')
	{
		$pid = $dbh->quote($param->{'pid'});
		print('<input type="hidden" name="pid" value="', $param->{'pid'}, '">');


		$question = $dbh->selectrow_array("select question from osoal.pollquestions
                                           where (pid = $pid)");

		$sth = $dbh->prepare("select answer from osoal.pollanswers
                              where (pid = $pid) order by aid asc");
		$sth->execute();

		while ($i = $sth->fetchrow_array())
		{
			$answers .= ($answers ? "\n$i" : $i);
		}
	}

	#
	print('<table align="center">

           <tr>
           <td align="left">PID</td>
           <td align="right"><input type="text" name="');

	if ($param->{'select'} eq 'Modify')
	{
		print('new');
	}

	print('pid" value="', $param->{'pid'}, '" size="50">
           </td>
           </tr>

           <tr>
           <td align="left">Question</td>
           <td align="right"><input type="text" name="question" value="', quote($question), '" size="50"></td>
           </tr>

           <tr>
           <td align="left">Answers</td>
           <td align="right">
              <textarea name="answers" cols="48" rows="4" wrap="virtual">', $answers, '</textarea></td>
           </tr>

           <tr>
           <td align="left">
               <div align="center">
               <input type="submit" name="select" value="');

	#
	if ($param->{'select'} eq 'Create')
	{
		print('Submit');
	}
	elsif ($param->{'select'} eq 'Modify')
	{
		print('Apply');
	}

	print('">
           </div>
           </td>
           <td align="right"><img src="/pics/icons/oneshortofallama.png" alt=""></td>
           </tr>
           </table>

           </form>', "\n\n");
}

sub submit_poll
{
	my($dbh, $pid, $question, $i, $aid, @answers, $param);

	#
	$dbh   = shift(@_);
	$param = shift(@_);

	#
	unless ($param->{'pid'} && $param->{'question'} && $param->{'answers'})
	{
		print('Insufficent arguments to create poll');
		return (0);
	}

	#
	$pid = $dbh->quote($param->{'pid'});
	$question = $dbh->quote($param->{'question'});

	$param->{'answers'} =~ s/\r//g;
	@answers = split("\n", $param->{'answers'});

	#
	if ($dbh->selectrow_array("select question from osoal.pollquestions where (pid = $pid)"))
	{
		print('That poll already exists');
		return (0);
	}

	#
	$dbh->do("insert into osoal.pollquestions (pid, question, time)
              values ($pid, $question, unix_timestamp())");

	#
	for ($i = 0; $i < scalar(@answers); $i++)
	{
		$answers[$i] = $dbh->quote($answers[$i]);

		$dbh->do("insert into osoal.pollanswers (pid, aid, answer)
                  values ($pid, $i + 1, $answers[$i])");
	}

	#
	return (1);
}

sub apply_poll
{
	my($dbh, $pid, $newpid, $question, @answers, $param, $aid, $i);

	#
	$dbh   = shift(@_);
	$param = shift(@_);

	#
	unless ($param->{'pid'} && $param->{'question'} && $param->{'answers'})
	{
		print('Insufficent arguments to modify poll');
		return (0);
	}

	#
	$pid      = $dbh->quote($param->{'pid'});
	$newpid   = $dbh->quote($param->{'newpid'});
	$question = $dbh->quote($param->{'question'});

	$param->{'answers'} =~ s/\r//g;
	@answers = split("\n", $param->{'answers'});

	foreach $i (@answers)
	{
		$i = $dbh->quote($i);
	}

	#
	if ($newpid ne $pid)
	{
		for $i ('questions', 'answers', 'votes')
		{
			$dbh->do("update osoal.poll$i set pid = $newpid where (pid = $pid)");
		}

		$pid = $newpid;
	}

	#
	$dbh->do("update osoal.pollquestions set
              question = $question where (pid = $pid)");

	$aid = $dbh->selectrow_array("select count(*) from osoal.pollanswers where (pid = $pid)");

	#
	for ($i = 0; $i < scalar(@answers); $i++)
	{
		unless ($i < $aid)
		{
			$aid = $dbh->selectrow_array("select max(aid) from osoal.pollanswers
                                          where (pid = $pid)");

			for (; $i < scalar(@answers); $i++)
			{
				$aid++;
				$dbh->do("insert into osoal.pollanswers (pid, aid, answer)
                          values ($pid, $aid, $answers[$i])");
			}

			last;
		}

		$dbh->do("update osoal.pollanswers set answer = $answers[$i]
                  where (pid = $pid && aid = $i + 1)");
	}

	#
	$dbh->do("delete from osoal.pollanswers where (pid = $pid && aid > $i)");
	$dbh->do("delete from osoal.pollvotes where (pid = $pid && aid > $i)");

	#
	return (1);
}

sub delete_poll
{
	my($dbh, $pid);
	
	#
	$dbh = shift(@_);
	$pid = $dbh->quote(shift(@_));

	#
	$dbh->do("delete from osoal.pollquestions where (pid = $pid)");
	$dbh->do("delete from osoal.pollanswers where (pid = $pid)");
	$dbh->do("delete from osoal.pollvotes where (pid = $pid)");
}

sub voting_form
{
	my($dbh, $sth, $pid, $aid, $answer, $question, $param);

	#
	$dbh   = shift(@_);
	$param = shift(@_);

	#
	unless ($param->{'pid'} = current_poll($dbh))
	{
		print('You may not vote in this poll');
		return ();
	}

	#
	$pid      = $dbh->quote($param->{'pid'});
	$question = $dbh->selectrow_array("select question from osoal.pollquestions
                                       where (pid = $pid)");

	unless ($question)
	{
		print('Invalid poll');
		return ();
	}
	
	#
	print('<form method="GET" action="', $ENV{'SCRIPT_NAME'}, '">
           <input type="hidden" name="pid" value="', $param->{'pid'}, '">
           <table width="170" cellspacing="3" cellpadding="0" border="0">

           <tr>
           <td>
               <em>', $question, '</em></td>
           </tr>', "\n\n");

	#
	$sth = $dbh->prepare("select aid, answer from osoal.pollanswers
                          where (pid = $pid) order by aid asc");
	$sth->execute();

	while (($aid, $answer) = $sth->fetchrow_array())
	{
		print('<tr>
               <td>
                   <input type="radio" name="aid" value="', $aid, '"');

		if ($aid == 1)
		{
			print(' checked');
		}

		print('> ', $answer, '</td>
               </tr>', "\n");
	}

	#
	print('<tr>
           <td>
               <small><input type="submit" value="Vote"></small>
               [ <a href="', $ENV{'SCRIPT_NAME'}, '?pid=', $param->{'pid'}, '"><small>Results</small></a>
               | <a href="', $ENV{'SCRIPT_NAME'}, '"><small>Polls</small></a> ]</td>
           </tr>

           <tr>
           <td>
               <hr noshade></td>
           </tr>

           </table>
           </form>', "\n\n");

}

#
#
#

sub main
{
	my($param, $cookie, $dbh, $uid, $gid);

	#
	$param       = variables();
	$cookie      = cookie('osoal');
	($uid, $gid) = authenticate($cookie->{'nickname'}, $cookie->{'passwd'});

	#
	header('Vote', 'vote.png', '/');
	print('<div align="center">
           <table width="600" cellpadding="0" cellspacing="0" border="0">
           <tr>
           <td align="left">', "\n\n");

	#
	if ($dbh = DBI->connect("dbi:mysql:$MySQLserver;database=osoal",
				$MySQLuser, $MySQLpasswd))
	{
		unless ($param->{'load'} =~ m/^\d+$/ || $param->{'load'} == -1)
		{
			$param->{'load'} = $load;
		}

		#
		if ($param->{'select'})
		{
			if ($gid == 1)
			{
				if ($param->{'select'} eq 'Create')
				{
					input_poll($dbh, $param);
				}

				elsif ($param->{'select'} eq 'Submit')
				{
					if (submit_poll($dbh, $param))
					{
						print_poll($dbh, $gid, $param);
					}
				}

				elsif ($param->{'select'} eq 'Modify')
				{
					input_poll($dbh, $param);
				}

				elsif ($param->{'select'} eq 'Apply')
				{
					if (apply_poll($dbh, $param))
					{
						print_poll($dbh, $gid, $param);
					}
				}

				elsif ($param->{'select'} eq 'Delete')
				{
					delete_poll($dbh, $param->{'pid'});
					list_polls($dbh, $gid, $param->{'load'});
				}
			}

			if ($param->{'select'} eq 'Vote')
			{
				voting_form($dbh, $param);
			}
		}

		else
		{
			if ($param->{'pid'} =~ m/^\w+$/)
			{
				print_poll($dbh, $gid, $param);
			}
			else
			{
				list_polls($dbh, $gid, $param->{'load'});
			}
		}

		$dbh->disconnect();
	}

	#
	print('</td>
           </tr>
           </table>
           </div>', "\n\n");
	footer();
}

#
main();
