#!/usr/bin/perl
#  Copyright 2001-2019 Leslie Richardson
#  This file is part of Open Admin for Schools.

use DBI;
use CGI;
use XML::Writer;
use XML::Writer::String;
use Data::UUID;
# use IO;
use HTTP::Request::Common qw(POST); 
use HTTP::Headers; 
use LWP::UserAgent; 
use XML::LibXML;
use Number::Format qw(round);


my $self = 'sendmarks.pl';

# Used for Filename Date
my @smonth = ('', 'JAN','FEB','MAR','APR','MAY','JUN','JUL','AUG','SEP','OCT','NOV','DEC');

my %lex = ( 'Main' => 'Main',
	    'Error' => 'Error',
	    );


eval require "../../etc/admin.conf";
if ( $@ ) {
    print $lex{Error}. " $@<br>\n";
    die $lex{Error}. " $@\n";
}

eval require "slxmllibNew.pl";
if ( $@ ) {
    print $lex{Error}. " $@<br>\n";
    die $lex{Error}. " $@\n";
}

my $q = CGI->new;
my %arr = $q->Vars;
print $q->header( -charset, $charset ); 

my $dsn = "DBI:$dbtype:dbname=$dbase";
my $dbh = DBI->connect($dsn,$user,$password);
$dbh->{mysql_enable_utf8} = 1;


my @tim = localtime(time);
my $year = $tim[5] + 1900;
$tim[4]++;
$tim[6]++; # wday; not used.

# For Filename
my $fyear = $year - 2000;
my $filecurrdate = $tim[3]. $smonth[ $tim[4] ]. $fyear;
my $filecurrtime = $tim[2]. $tim[1];
# End of filename specific time

for (0..4){if (length($tim[$_]) == 1){ $tim[$_] = '0'.$tim[$_];}}
my $currdate = "$year-$tim[4]-$tim[3]";
my $currtime = "$tim[2]:$tim[1]:$tim[0]";


print qq{$doctype\n<html><head><title>Submit Student Marks</title>\n};
print qq{<link rel="stylesheet" href="$css" type="text/css">$chartype\n};
print qq{</head><body>[ <a href="$reppage">Report Card</a> |\n};
print qq{<a href="$exppage">Export</a> ]\n};
print qq{<h1>Submit Student Marks</h1>\n};

if ( not $arr{page} ) {
    showStartPage();

} elsif ( $arr{page} == 1 ) {
    delete $arr{page};
    selectStudents();

} elsif ( $arr{page} == 2 ) {
    delete $arr{page};
    sendMarks();
}



#----------------
sub showStartPage {
#----------------

    print qq{<form action="$self" method="post">\n};
    print qq{<input type="hidden" name="page" value="1">\n};

    print qq{<table cellpadding="3" border="1" cellspacing="0">\n};

    print qq{<tr><td colspan="6">};
    print qq{<input type="submit" value="Continue">};
    print qq{<input type="checkbox" name="checked" value="checked">Check Next Page\n};
    print qq{</td></tr>\n};

    print qq{<tr><th>Subject</th><th>Code-Sec</th><th>Terms</th><th>Teacher</th>};
    print qq{<th>Grade</th><th>Select</th></tr>\n};

    my $sth1 = $dbh->prepare("select count(*) from eval where subjcode = ?");

    my $sth = $dbh->prepare("select description, grade, teacher, subjsec, startrptperiod, endrptperiod from subject 
     where grade = '10' or grade = '11' or grade = '12' order by startrptperiod, endrptperiod, grade, description");
    $sth->execute;
    if ( $DBI::errstr ){ print $DBI::errstr; die $DBI::errstr; }

    my ($currterms, $prevterms);


    while ( my ( $description, $grade, $teacher, $subjsec, $startterm, $endterm ) = $sth->fetchrow ) {


	$prevterms = $currterms;
	$currterms = "$startterm-$endterm";

	if ( $prevterms and $prevterms ne $currterms ) { 
	    print qq{<tr><td colspan="6" style="background-color:#888;"></td></tr>\n};
	}
	

	$sth1->execute( $subjsec );
	if ( $DBI::errstr ){ print $DBI::errstr; die $DBI::errstr; }
	my $count = $sth1->fetchrow;
	if ( not $count ) { next; }; # skip if no enrollments.


	if ( not $teacher ){ $teacher = "<font color=red>No Teacher</font>"; }
	print qq{<tr><td>$description</td><td>$subjsec</td><td>$startterm-$endterm</td><td>$teacher</td>\n};
	print qq{<td>$grade</td><td><input type="checkbox" name="$subjsec" value="1" $checked></td></tr>\n};
	
    }

    
    print qq{<tr><td colspan="6">};
    print qq{<input type="submit" value="Continue">};
    print qq{<input type="checkbox" name="checked" value="checked">Check Next Page\n};
    print qq{</td></tr>\n};

    print qq{</table></form>\n};
    print qq{</body></html>\n};

    exit;

}


#-----------------
sub selectStudents {
#-----------------
    
    # passed a list of subjects to submit marks for.
    my $checked;
    if ( $arr{checked} ) {
	$checked = qq{checked = "checked"};
    }
    delete $arr{checked};

    # foreach my $key ( sort keys %arr ) { print "K:$key V:$arr{$key}<br>\n"; }

    print qq{<form action="$self" method="post">\n};
    print qq{<input type="hidden" name="page" value="2">\n};

    # Batch File / Real Time setting.
#    print qq{<div style="width:40%;border:1px solid black;padding:0.4em;text-align:center;font-size:130%;">\n};
#    print qq{Create <b>Batch File</b> for Upload to Sask Ed ? \n};
#    print qq{<input type="checkbox" name="filemode" value="1">\n};
#    print qq{<br>No Real Time Transfers will be done.</div>\n};

    print qq{<div style="font-size:120%;font-weight:bold;margin:0.3em;">};
    print qq{Override Term End Date (yyyy-mm-dd): };
    print qq{<input type="text" size="12" name="newenddate"></div>\n};

    
    print qq{<div>Debug (only for Programmers)<input type="checkbox" name="debug" value="1"></div>\n};

    print qq{<p><input type="submit" value="Send Selected Student Marks"></p>\n};


    foreach my $subjsec ( sort keys %arr ){

	# Get Subject Name
	my $sth = $dbh->prepare("select description, endrptperiod from subject where subjsec = ?");
	$sth->execute( $subjsec );
	if ($DBI::errstr) { print $DBI::errstr; die;}
	my ($subjectname, $endterm) = $sth->fetchrow;

	# Get Enrolled Students List
	$sth = $dbh->prepare("select distinct eval.studnum,studentall.lastname,
         studentall.firstname from eval,studentall where
         studentall.studnum = eval.studnum and eval.subjcode = ?
         order by studentall.lastname, studentall.firstname");

	$sth->execute( $subjsec );
	if ($DBI::errstr) { print $DBI::errstr; die $DBI::errstr; }
	my $rows = $sth->rows;
	if ($rows < 1){ next;}

	print qq{<h3>$subjectname ($subjsec)</h3>\n};
	print qq{<table cellpadding="3" cellspacing="0" border="1">\n};
	print qq{<tr><th>Name</th><th>Mark</th><th>Select</th></tr>\n};

	# Prep for checking existence in table.
	my $sth1 = $dbh->prepare("select count(studid) from studentwd where studnum = ?");
	my $sth2 = $dbh->prepare("select a1 from eval where studnum = ? and subjcode = ? and term = ?");

	
	while ( my ( $studnum,$lastname,$firstname ) = $sth->fetchrow ) {

	    # Check if enrolled!
	    $sth1->execute( $studnum );
	    if ($DBI::errstr) { print $DBI::errstr; die $DBI::errstr; }
	    my $count = $sth1->fetchrow;
	    my $wd;
	    if ( $count ) { $wd = qq{<span style="color:red;font-weight:bold;">WD</span>\n}; }

	    # Get mark to be sent
	    $sth2->execute( $studnum, $subjsec, $endterm );
	    if ($DBI::errstr) { print $DBI::errstr; die $DBI::errstr; }
	    my $mark = $sth2->fetchrow;

	    $mark =~ s/\%//; # strip any percent signs;
	    my $hasletters = 0; # if the mark contains no A-Z letters;
	    if ( $mark =~ m/[a-zA-Z]/ ) {
		$hasletters = 1;  # it HAS letters in it.
	    }
	    
	    print qq{<tr><td class="la">$wd <b>$lastname,</b> $firstname</td><td>$mark</td>\n<td>};
	    if ( $mark and not $hasletters ) {
		print qq{<input type="checkbox" name="$subjsec:$studnum" value="1" $checked>};
	    }
	    print qq{</td></tr>\n};


	}
	print qq{</table>\n};
    }

    print qq{<p><input type="submit" value="Send Selected Student Marks"></p>\n};
    print qq{</form></body></html>\n};

    exit;

} # end of selectStudents



#------------
sub sendMarks {
#------------

    # foreach my $key ( sort keys %arr ) { print "K:$key V:$arr{$key}<br>\n"; }
    
    my $debug = $arr{debug};
    delete $arr{debug};

    my $newenddate;
    if ( $arr{newenddate} ) { $newenddate = $arr{newenddate}; };
    delete $arr{newenddate};

    
    # Filemode only.
    my $filemode = $arr{filemode};
    delete $arr{filemode};

    if ( $filemode ) { $maxfilesize = '1000000'; } 

    # foreach my $key (keys %arr) { print "K:$key V:$arr{$key}<br>\n"; }


    # now get the number of records (ie. size of %arr);
    my $donecount = 1;
    my $reccount = keys %arr;
    my $xfercount = 1; # Counter for message headers (to make unique).

    my $filename;
    if ( $filemode ) { # open the file for writing.
	$filename = 'MARKS_'. $schoolnumber. '_'. $filecurrdate. '_'. $filecurrtime. '.xml';
	open(FH,">$filename") or die "Cannot Open XML file\n";
    }


    while ( $donecount <= $reccount ) {

	# Create a new user agent
	my $ua = LWP::UserAgent->new();
	$ua->agent("OpenAdmin");

	# Create Writer Instance
	my $output = XML::Writer::String->new();
	my $datamode = 0;
	if ($debug){$datamode = 1;}

	$wr = new XML::Writer(OUTPUT => $output, DATA_MODE => $datamode, 
			      DATA_INDENT => '2');
	# Data Mode 1 turns on pretty output, Data Mode 0 is more condensed.


	# Set XML Header and write Root Element
	$wr->xmlDecl("UTF-8");
	$wr->startTag('SL_Message','xmlns' =>$xmlns, 
		      'xmlns:xsi' =>$xmlnsxsi, 
		      'xsi:schemaLocation' => $xsischemaLocation);

	$wr->startTag('SL_Event');
	
	mkSL_Header($currdate,$currtime, $schoolnumber,$xfercount);

	$xfercount++;
	if ($xfercount > 99){ $xfercount = 1;}

	$wr->startTag('SL_ObjectData');

	$wr->startTag('SL_EventObject',
		      'ObjectName' => 'StudentClassMark', 
		      'Action' => 'Add');

	my $filesize = 0;


	# Main Loop - once for each student-subject.
STUDENT:
	foreach my $key ( sort keys %arr ) {

	    my ( $subjsec, $studnum ) = split ':',$key;

	    # Get Student Bdate and ProvNum, and Name
	    $sth = $dbh->prepare("select lastname, firstname, provnum,birthdate 
              from studentall where studnum = ?");
	    $sth->execute( $studnum );
	    if ($DBI::errstr) { print $DBI::errstr; die $DBI::errstr; }
	    my ($lastname, $firstname, $provnum,$bdate) = $sth->fetchrow;
	    my $name = "<b>$lastname</b>, $firstname ($studnum)";

	    # Get Subject Data
	    my $sth = $dbh->prepare("select subjcode, description, subjsec, 
             startrptperiod, endrptperiod, grade from subject where subjsec = ?");
	    $sth->execute( $subjsec );
	    if ( $DBI::errstr ){ print $DBI::errstr; die $DBI::errstr; }
	    my ( $subjcode, $description, $subjsec, $startterm, $endterm, $grade ) = $sth->fetchrow;

	    my $subject = "$description ($subjsec)";
	    my $classid = $subjsec; # Subject-Section id.
	    my $courseid = $subjcode; # Subject code.


	    # Get Dates for this subject, checking based on track info.
	    my $track = $g_MTrackTermType{$grade};
	    my $startdate = $g_MTrackTerm{$track}{$startterm}{'start'};
	    my $enddate = $g_MTrackTerm{$track}{$endterm}{'end'};

	    # Use Newenddate to override end date for dept exams if necessary.
	    # print "New End Date:$newenddate<br>\n";
	    if ( $newenddate ) { $enddate = $newenddate; }
	    
#	    print qq{Track:$track Start:$startdate  End:$enddate<br>\n};

	    if ( not $startdate or not $enddate ){
		print "Subject $description ($subjsec) does not have start/end";
		print " dates correctly defined. ";
		print "(or term start/end dates defined)\n";
		print " Terminating.\n"; 
		die "Subject $subject[2] ($subject[9]) dates not correct";
	    }

	    # Get Mark Information
	    # Need subject/section (subjsec), studnum, and end term ($subject[33])
	    $sth = $dbh->prepare("select a1 from eval where subjcode = ? and term = ? and studnum = ?");
	    $sth->execute( $subjsec, $endterm, $studnum );
	    if ($DBI::errstr) { print $DBI::errstr; die $DBI::errstr; }
	    my $mark = $sth->fetchrow;

	    if ( not $mark ) {
		$donecount++; # since we _have_ done this one...
		my $sth1 = $dbh->prepare("select lastname, firstname from studentall where studnum = ?");
		$sth1->execute($studnum);
		if ($DBI::errstr) { print $DBI::errstr; die $DBI::errstr; }
		my ($lastname, $firstname) = $sth1->fetchrow;

		print "<b>No Mark found</b>";
		print " for: <b>$firstname $lastname ($studnum)</b> in subject ";
		print "<b>$subject</b><br>\n";
		next STUDENT;
	    }

	    # Get rid of spaces and any percent symbols.
	    $mark =~ s/\%//;
	    $mark =~ s/^\s+//;
	    $mark =~ s/\s+$//;

    
	    my $refid = "$subjsec-$studnum"; # Subjsec-StudentNumber - refid #
	    $studsubj{$refid} = "$name:$subject:$mark";

	    my $correction = ''; # A 'Yes' or 'No' to note any corrections; not yet.

	    mkStudentClassMark($schoolnumber,$refid, $provnum, $bdate, $classid, $startdate,
			       $enddate,$mark, $correction);

	    $donecount++; # increment counter for all utagged records

	    $filesize = length($output->value); # Get the new larger size.
	    if ($filesize >= $maxfilesize){ last;} # break out of loop. 
	    #print "$donecount:", $filesize,"<br>\n";

	} # End of this student-subjsec


	$wr->endTag('SL_EventObject');
	$wr->endTag('SL_ObjectData');
	$wr->endTag('SL_Event');
	$wr->endTag('SL_Message');
	$wr->end();


	# Write all data to batch file.
	if ( $filemode ) {
	    my $temp = $output->value;
	    print FH $temp;
	}


	# show output sent to Sask Ed if set via debug mode
	if ( $debug ){
	    my $temp = $output->value;
	    $temp =~ s/</&lt;/g;
	    $temp =~ s/>/&gt;/g;
	    print "<div style=\"color: blue;\">\n";
	    print "<h1>DEBUG - Request sent to Sask Ed</h1>\n";
	    print "<pre>",$temp,"</pre></div><p></p>\n";
	}

	if ( not $filemode ) {

	    $filesize = length($output->value)/1000; # Get Final Filesize.
	    print "<p>The filesize is ", round( $filesize, 1), "KB (Limit: 32KB)</p> \n";


	    # Create the https post request 
	    my $req = POST $url, [ XML=> $output->value ];

	    $req->content_type('application/xml;charset="utf-8"');
	    $req->authorization_basic($sds_userid, $sds_password); 
	    
	    # Issue the request and receive a response
	    $res = $ua->request($req);
	    
	    # Check the status of the transfer (NOT result of xml transactions)
	    if ($res->is_success) {

		# For Debugging ....
		if ( $debug ){
		    print "<h1>DEBUG - Sask Ed XML Response</h1>\n";
		    print "<div style=\"color:green;\">\n";
		    my $temp = $res->content;
		    $temp =~ s/</&lt;/g;
		    $temp =~ s/>/&gt;/g;
		    print "<pre>",$temp,"</pre></div>\n";
		}


		# Parse returned XML.
		# This does most of the screen printing (and table layout).
		parseResponse(); # response results if errors, update student provnum

	    } else {
		my $err = $res->status_line;
		print "<h1>Transfer Error: $err</h1>";
		print "<pre>",$res->content,"</pre>\n";
		die;
	    }

	} # end of Not File mode.

    } # End of the Counted loop for all student-subjsec marks


    if ( $filemode ) { # Filemode here (ie. file upload )

	close FH;

	# File upload stuff here.
	system("mv $filename $downloaddir");

	print qq{<h1>$lex{'View/Download'} $lex{'Enrollment File'}</h1>\n};
	print qq{<p>[ <a href="$webdownloaddir/$filename">$filename</a> ]</p>\n};
	
    } 

    
    print qq{</body></html>\n};

    exit;

}


#----------------
sub parseResponse {
#----------------

    # parse response from SaskEd, display errors (if any), update provnum in 
    # student table,  print to error logs.

    # Parse the response.
    my $parser = XML::LibXML->new();

    eval {$doc = $parser->parse_string($res->content)};
    if ( $@ ) {
	print "Sask Ed Error:\n<pre>$@<br>";
	print $res->content,"</pre><br>\n";
	print "</body></html>\n"; die;
    }	

    #print "XMLns:",$xmlns,"<br>\n";

    $doc->setEncoding('UTF-8');

    my $root = $doc->getDocumentElement;
    $root->setNamespace($xmlns,'sl',1);

    my $status = $root->findvalue('//sl:SL_Status/sl:SL_StatusCode');
    my $statusMsg = $root->findvalue('//sl:SL_Status/sl:SL_StatusMsg');

    # Print table heading for table of results.
    print "<table cellpadding=\"3\" cellspacing=\"0\" border=\"1\">\n";
    print "<tr><th>Name</th><th>Subject</th><th>Mark</th><th>Message</th></tr>\n";

    my $currsubj = -1;
    my $oldsubj;

    if ($status eq 'Errors' or 
	$status eq 'Successful' or 
	$status eq 'Warnings') { 

	my @errors = $root->findnodes('//sl:SL_Error');
	foreach my $error (@errors){  # loop through all student marks
	    
	    my $refid = $error->getAttribute('RefId');
	    my $errcode = $error->findvalue('sl:SL_ErrorCode');
	    my $errmsg = $error->findvalue('sl:SL_ErrorMsg');
	    #print "Ref:$refid V: $studsubj{$refid}<br>\n";
	    
	    my ($nm,$sub,$mark) = split ':', $studsubj{$refid};
	    $oldsubj = $currsubj;
	    $currsubj = $sub;
	    if ($oldsubj ne $currsubj) {
		print "<tr><td colspan=\"4\" ";
		print "style=\"background-color:#DDD;font-size:130%;\">\n";
		print "<b>$currsubj</b></td></tr>\n";
	    }

	    print "<tr><td>$nm</td><td>$sub</td><td align=\"center\">$mark</td>";
	    if ($errcode) { # if not zero, we have an error....
		print "<td style=\"color:red;\">$errmsg ($errcode)</td></tr>\n";
	    } else {
		print "<td>$errmsg</td></tr>\n";
	    }

	} # End of printing of response loop


    } elsif ( $status eq 'Invalid' ) { # Print out errors
	print "<div style=\"font-size: 200%; font-weight: bold;\">";
	my @errors = $root->findnodes('//sl:SL_Error');
	foreach my $error ( @errors ) {
	    my $refid = $error->getAttribute('RefId');
	    my $errcode = $error->findvalue('sl:SL_ErrorCode');
	    my $errmsg = $error->findvalue('sl:SL_ErrorMsg');
	    print "Error: $errmsg ($errcode) ";
	}
	print "</div>\n";

    } else {
	print "<p><b>Weird result</b> - Status: $status<br></p>\n";
	exit;
    }

    print "</table><p></p>\n";
    return undef;


} # End of parseResponse
