#! /usr/bin/perl
#  Copyright 2001-2022 Leslie Richardson

#  This file is part of Open Admin for Schools.

#  Open Admin for Schools is free software; you can redistribute it 
#  and/or modify it under the terms of the GNU General Public License
#  as published by the Free Software Foundation; either version 2 of 
#  the License, or (at your option) any later version.

my %lex = ('Main' => 'Main',
	   'View/Download' => 'View/Download',
	   'Custom Classlist' => 'Custom Classlist',
	   'View Log File' => 'View Log File',
	   'Continue' => 'Continue',
	   'Homeroom' => 'Homeroom',
	   'Grade' => 'Grade',
	   'Cell Width' => 'Cell Width',
	   'Maximum' => 'Maximum',
	   'Page' => 'Page',
	   'Students' => 'Students',
	   'Select by' => 'Select by',
	   'Repeat Entry Elements' => 'Repeat Entry Elements',
	   'Classlist' => 'Classlist',
	   'Rm' => 'Rm',
	   'Students' => 'Students',
	   'Paper Size' => 'Paper Size',
	   'Letter' => 'Letter',
	   'Legal' => 'Legal',
	   'A4' => 'A4',
	   'Font Size' => 'Font Size',
	   'Gray Shade' => 'Gray Shade',
	   'Smaller=Darker' => 'Smaller=Darker',
	   'Include' => 'Include',
	   'Student Number' => 'Student Number',
	   'Additional Field' => 'Additional Field',
	   'Error' => 'Error',
	   'Width' => 'Width',
	   'Sort by' => 'Sort by',
	   'Name' => 'Name',
	   'Single Value Only' => 'Single Value Only',
	   'Not Found' => 'Not Found',

	   );

my $self = 'rptcustomclasslist.pl';

use DBI;
use CGI;
use Cwd;

# Configurable settings
my $maxstudents = 28; # maximum students per page.
my $cellwidth = 8;  # default width of columns, 8 mm;
my $extrafieldwidth = 18; # studnum and extra field in mm.
my $defaultgrayshade = '0.90';  # shading for alternate rows

my $entrylimit = 31; # Max entries allowed for rotated text.
my $maxentrysize = 16; # Maximum number of characters for the entry
my $namewidth = 50; # Width of the first 'Name' column in mm.

my $studnumwidth = 12; # Width of local student number in mm.


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

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

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


my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $iddst) = localtime(time);
$year = $year + 1900;
$wday++; $mon++;
my $currdate = "$dow[$wday], $month[$mon] $mday, $year";

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



# Get current dir so know what CSS to display;
if ( getcwd() =~ /tcgi/ ){ # we are in tcgi
    $css = $tchcss;
    $homepage = $tchpage;
}

my $title = qq{$lex{'Custom Classlist'}};
print qq{$doctype\n<html><head><title>$title</title>\n};
print qq{<link rel="stylesheet" href="$css" type="text/css">\n};
print qq{$chartype\n</head><body style="padding:1em 4em;">\n};
print qq{<div>[ <a href="$homepage">$lex{Main}</a> ]</div>\n};

print qq{<h1>$title</h1>\n};


# Get values for Customization, then exit;
# Values passed are width, maxstudents, repeat, entry1 to entry8
if ( not $arr{page} ) {
    showStartPage();
} else {
    delete $arr{page};
}

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


# Setup Extra fields
my ( $studnumfield, $extrafield );
if ( $arr{extrafield} ) {
    $extrafield = $arr{extrafield};
    delete $arr{extrafield};
}

if ( $arr{extrafieldwidth} ) {
    $extrafieldwidth = $arr{extrafieldwidth}; # default defined at top of script
    delete $arr{extrafieldwidth};
}

if ( $arr{studnumfield} ) {
    $studnumfield = 1;
    delete $arr{studnumfield};
}

my ($extrafieldName, %defaultvalues); # default values only for selecthash form type
if ( $extrafield ) {
    my $sth = $dbh->prepare("select fieldname, defaultvalue, formtype from meta 
			    where tableid = 'student' and fieldid = ?");
    $sth->execute( $extrafield );
    if ($DBI::errstr) { print $DBI::errstr; die $DBI::errstr; }
    my ($defaultvalue, $formtype); # these 2 are local
    ($extrafieldName, $defaultvalue, $formtype) = $sth->fetchrow;

    if ( $formtype eq 'selecthash' ) { # we want to display their text equivalent values from meta
	my @temp = split(/\s+/, $defaultvalue);  #split based on spaces
	foreach my $val ( @temp ) {
	    $val =~ s/_/ /g; # strip underscores used as separators
	}
	%defaultvalues = @temp;

    }

    ( $extrafieldName ) = latex_filter( $extrafieldName );

}


# Set Sizes
# Letter paper size is 279mm x 216mm
# 200mm wide - 50mm name, 20mm extra fld, leaves 130mm for columns.
# a4 paper is 297mm x 210mm; legal is 356mm x 216mm

# The tabcolsep of 1mm leaves 128 mm where each col is $width + 1mm wide.
my $fontsize = $arr{fontsize}. 'pt';

my ( $papersize, $textwidth, $textheight );

if ( $arr{papersize} eq 'letter' ) {
    $papersize = 'letterpaper';
    $textwidth = $g_letterpaper_textwidth;
    $textheight = $g_letterpaper_textheight;

} elsif ( $arr{papersize} eq 'legal' ) {
    $papersize = 'legalpaper';
    $textwidth = $g_legalpaper_textwidth;
    $textheight = $g_legalpaper_textheight;

} elsif ( $arr{papersize} eq 'a4' ) {
    $papersize = 'a4paper';
    $textwidth = $g_a4paper_textwidth;
    $textheight = $g_a4paper_textheight;

} 


# Restrict Gray Shading values
if ( $arr{grayshade} > 1 ) { $arr{grayshade} = 1; }
if ( $arr{grayshade} < 0.5 ) { $arr{grayshade} = 0.5; }

my $wi = $arr{cellwidth} - 1; # width of each col desired (in mm)
# take away 1 for 1mm tabcolsep.

my $availablesize = $textwidth - $namewidth;

# Set column count after shrinking available size
if ( $studnumfield ) { $availablesize -= $studnumwidth; }
if ( $extrafield ) { $availablesize -= $extrafieldwidth; }


my $colcount = $availablesize / $arr{cellwidth};
$colcount = int $colcount + 1; # truncate

# print "Paper: $textwidth Count:$colcount Available: $availablesize<br>\n";

# Filter for Passed values that might crash LaTeX 
foreach my $key ( keys %arr ) {
    ( $arr{$key} ) = latex_filter( $arr{$key} );
}

if ( $arr{maxstudents} ) {
   $maxlines = $arr{maxstudents};
} else {
   $maxlines = $maxstudents;
}

# push entry text into array.
for (1..$entrylimit){
    my $entryname = 'entry'.$_;
    if ($arr{$entryname}){ # if it exists...push into array
	push @entry,$arr{$entryname};
    }
}
my $entrysize = $#entry + 1;
#print qq{Entry size: $entrysize\n};

if ($arr{repeat} and $entrysize){
    $repeatcount = $colcount / $entrysize;
    $repeatcount = int $repeatcount;

} elsif ($entrysize){
    $repeatcount = 1; # only do it once if not repeat.

} else { $repeatcount = 0;}
#print qq{Repeat Count: $repeatcount\n};


my ($select, $grouptype, @group);
if ( $arr{homeroom} ) {
    if ( $arr{homeroom} eq 'all' )  {
	my @homerooms;
	my $sth = $dbh->prepare("select distinct homeroom from student 
				where homeroom is not NULL and homeroom != '';");
	$sth->execute;
	if ($DBI::errstr) { print $DBI::errstr; die $DBI::errstr; }
	while ( my $hr = $sth->fetchrow ) {
	    push @homerooms, $hr;
	}
	@group = sort {$a <=> $b} @homerooms;
	
    } else { # one homeroom
	# my $grpvalue = $dbh->quote( $arr{homeroom} );
	push @group, $arr{homeroom};
    } 
    $grouptype = 'homeroom';

    
} elsif ( $arr{grade} )  {
    if ( $arr{grade} eq 'all' ) {
	my @grades;
	my $sth = $dbh->prepare("select distinct grade from student 
				where grade is not NULL and grade != '';");
	$sth->execute;
	if ($DBI::errstr) { print $DBI::errstr; die $DBI::errstr; }
	while ( my $grade = $sth->fetchrow ) {
	    push @grades, $grade;
	}
	@group = sort {$a <=> $b} @grades;

    } else { # one grade only
	# my $grpvalue = $dbh->quote( $arr{grade} );
	# $select = "where grade = $grpvalue";
	push @group, $arr{grade}
    }
    $grouptype = 'grade';

} else { # Error; no selection
    print qq{</h3>No Homeroom or Grade selected.</h3>\n};
    print qq{</body></html>\n};
    exit;
}


# Start TeX Document
my $shortname = "cclasslist$$";
my $filename = "$shortname.tex";

open(TEX,">$filename") || die "Can't open tex file";

print TEX "\\documentclass[$fontsize,$papersize ]{article}
\\usepackage{array,newcent,rotating,colortbl,inputenc}
$a_latex_header
\\pagestyle{empty}
\\setlength{\\textwidth}{$textwidth}
\\setlength{\\textheight}{$textheight}

\\setlength{\\hoffset}{-40mm}
\\setlength{\\voffset}{-36mm}
\\addtolength{\\evensidemargin}{0mm}
\\addtolength{\\oddsidemargin}{0mm}
\\setlength{\\tabcolsep}{0.5mm}
\\setlength{\\extrarowheight}{2mm}
\\newcolumntype{G}{>{\\columncolor[gray]{1.00}}p{$namewidth mm}}\n";
# Note above... a columncolor of 1.00 means white, smaller number is darker.

print TEX "\\begin{document}\n";


# Set sorting order
my $sortorder = 'order by lastname, firstname';

my $teachername;

foreach my $graderoom ( @group ) { # grade or homeroom

    my $sth = $dbh->prepare("select lastname, firstname, grade, homeroom, studnum from student 
			    where $grouptype = ? order by lastname, firstname");
    $sth->execute( $graderoom ); # grade or homeroom
    if ($DBI::errstr) { print $DBI::errstr; die $DBI::errstr; }

    # Get Teacher name, if any
    my $sth1 = $dbh->prepare("select sal, lastname from staff as s, staff_multi as sm
			     where s.userid = sm.userid and field_name = 'homeroom' and 
			     field_value = ?");
    $sth1->execute( $graderoom );
    if ($DBI::errstr) { print "Teacher Error: $DBI::errstr"; die $DBI::errstr; }
    $teachrows = $sth1->rows;
    $teachername = '';
    for ( 1..$teachrows ){ 
	my ($sal, $lastname) = $sth1->fetchrow;
	$teachername .= " $sal~$lastname";
    }
    # end of teacher name

    my $first = 1; 
    my $linecount = $studcount = 0;
    
    while ( my ( $lastname, $firstname, $grade, $homeroom, $studnum ) = $sth->fetchrow ) {

	if ( $first ) { # print header to start
	    prHeader($teachername, $graderoom );
	    $first = 0;
	}

	$linecount++;
	$studcount++;
	if ( $linecount > $maxlines ) { # We'll print a new page header here
	    # New Page Header
	    $linecount = 0;
	    if ( $i != 1 ) { print TEX "\\end{tabular}\\\\ \\newpage\n"; }
	    prHeader($teachername, $graderoom );
	}
	
	# Print Normal Record.
	prRecord($lastname, $firstname, $studnum);
    }

    # now do bottom of page
    prStudCount();
    print TEX "\n\\end{tabular} \n\n \\newpage \n";

}  # End of Loop for all groups


print TEX "\n\\end{document}";
close TEX;

# Solve download location issues with cgi vs tcgi..
# Get current dir so know what CSS to display;
if (getcwd() =~ /tcgi/){ # we are in tcgi
    $downloaddir = $tchdownloaddir;
    $webdownloaddir = $tchwebdownloaddir;
}

system("$pdflatex $filename >pdflog$$.txt");
system("mv $shortname.pdf $downloaddir");
system("mv pdflog$$.txt $downloaddir");
system("rm -f $shortname.*");

print qq{<h1><a href="$webdownloaddir/$shortname.pdf">};
print qq{$lex{'View/Download'} $lex{'Custom Classlist'}</a></h1>\n};
print qq{<p>[ <a href="$homepage">$lex{Main}</a> |\n <a href="$webdownloaddir/pdflog$$.txt">};
print qq{$lex{'View Log File'}</a>\n ]</p>};

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



#----------------
sub showStartPage { # Entry Values for Custom Script
#----------------

    # Read student fields, and defaults into a @fields and %fieldname hash.
    my $sth = $dbh->prepare("select fieldid, fieldname from meta where 
			    tableid = 'student' order by fieldname");
    $sth->execute;
    if ($DBI::errstr) { print $DBI::errstr; die $DBI::errstr; }
    
    my @fields;
    my %fieldnames;
    while ( ( my $fieldid, $fieldname ) = $sth->fetchrow ) {
#	$fieldname =~ s/\(//g;
#	$fieldname =~ s/\)//g; # strip parenthese. (sp?)
	push @fields, $fieldid;
	$fieldname{ $fieldid } = $fieldname;
    }

    # Get Grades
    my @grades;
    my $sth = $dbh->prepare("select distinct grade from student 
			    where grade is not NULL and grade != '';");
    $sth->execute;
    if ($DBI::errstr) { print $DBI::errstr; die $DBI::errstr; }
    while ( my $grade = $sth->fetchrow ) {
	push @grades, $grade;
    }
    @grades = sort {$a <=> $b} @grades;


    # Get Homerooms
    my @homerooms;
    my $sth = $dbh->prepare("select distinct homeroom from student 
			    where homeroom is not NULL and homeroom != '';");
    $sth->execute;
    if ($DBI::errstr) { print $DBI::errstr; die $DBI::errstr; }
    while ( my $hr = $sth->fetchrow ) {
	push @homerooms, $hr;
    }
    @homerooms = sort {$a <=> $b} @homerooms;

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

    print qq{<table cellpadding="3" cellspacing="0" border="0" style="float:left;">\n};
    print qq{<tr><td></td><td><input type="submit" value="$lex{Continue}"></td></tr>\n};

    # Student By Grade
    print qq{<tr><td class="ra">$lex{'Select by'} $lex{Grade}</td>};
    print qq{<td><select name="grade"><option></option>};
    print qq{<option value="all">All Grades</option>\n};
    foreach my $gr ( @grades ) {
	print qq{<option>$gr</option>};
    }
    print qq{</select></td></tr>\n};

    # OR
    print qq{<tr><td class="bra">OR</td><td></td></tr>\n};

    # Student by Homeroom
    my $sth = $dbh->prepare("select lastname, firstname from staff s, staff_multi sm 
			    where s.userid = sm.userid and field_name = 'homeroom' 
			    and field_value = ?");

    print qq{<tr><td class="ra">Homeroom</td><td>};
    print qq{<select name="homeroom"><option></option>};
    print qq{<option value="all">All Homerooms</option>\n};
    foreach my $hr ( @homerooms ) {
	$sth->execute($hr);
	if ($DBI::errstr){ print $DBI::errstr; die $DBI::errstr; }
	my ($lastname, $firstname) = $sth->fetchrow;
	my $hrname = $hr;
	if ( $lastname ) { $hrname = "$hr - $firstname $lastname"; }
	
	print qq{<option value="$hr">$hrname</option>\n};
    }
    print qq{</select></td></tr>\n};
    

    # Use Legal Name, if present
    print qq{<tr><td class="ra">Use Legal Name (if present)</td>};
    print qq{<td><input type="checkbox" name="uselegal"  value="1"></td></tr>\n};
    
    # Cell Width
    print qq{<tr><td class="ra">$lex{'Cell Width'}</td>\n<td>};
    print qq{<input type="text" style="width:4ch;" name="cellwidth" value="$cellwidth"> mm. };
    print qq{Skinnier cells = More Cells up to 31 max (4.5mm)</td></tr>\n};

    # Font size
    print qq{<tr><td class="ra">$lex{'Font Size'}</td><td>\n};
    print qq{<select  name="fontsize">};
    print qq{<option>11</option><option>12</option><option>10</option>\n};
    print qq{</select></td></tr>\n};

    # Gray Shade
    print qq{<tr><td class="ra">$lex{'Gray Shade'}</td><td>\n};
    print qq{<input type="text"  name="grayshade" value="$defaultgrayshade" size="5">};
    print qq{ (0-1) $lex{'Smaller=Darker'}</td></tr>\n};

    # Paper
    print qq{<tr><td class="ra">$lex{'Paper Size'}</td><td>};
    print qq{ <select name="papersize"><option value="letter">$lex{Letter}</option>\n};
    print qq{<option value="legal">$lex{Legal}</option>};
    print qq{<option value="a4">$lex{A4}</option></select></td></tr>\n};

    # Include Student Number
    print qq{<tr><td class="ra">$lex{Include} $lex{'Student Number'}</td>};
    print qq{<td><input type="checkbox" name="studnumfield"  value="1"></td></tr>\n};

    # Additional/Extra Field
    print qq{<tr><td class="ra">$lex{'Additional Field'}</td>\n};
    print qq{<td><select name="extrafield"><option></option>\n};
    foreach my $fld ( @fields ) {
	print qq{<option value="$fld">$fieldname{$fld} ($fld)</option>\n};
    }
    print qq{</select></td></tr>\n};

    # Additional/Extra Field Width
    print qq{<tr><td class="ra">$lex{'Additional Field'} $lex{Width}</td>\n};
    print qq{<td><input type="text" name="extrafieldwidth" style="width:4ch;" };
    print qq{value="$extrafieldwidth"> mm</td></tr>\n};
    # $extrafieldwidth is set at top of script as a default value.

    # Max Students / Page
    print qq{<tr><td class="ra">$lex{Maximum} $lex{Students}/$lex{Page}</td>\n<td>};
    print qq{<input type="text" name="maxstudents" style="width:4ch;" value="$maxstudents">};
    print qq{</td></tr>\n};

    # Continue
    print qq{<tr><td></td><td><input type="submit" value="$lex{Continue}"></td></tr>\n};
    
    # New table
    print qq{</table>\n};
    print qq{<table cellpadding="3" cellspacing="0" border="0" style="float:left;">\n};
    
    print qq{<tr><td class="ra">$lex{'Repeat Entry Elements'}?</td>\n};
    print qq{<td><input type="checkbox" name="repeat"></td></tr>\n};

    for ( 1..$entrylimit ) {
	my $entrytxt = "entry$_";
	print qq{<tr><td class="ra">Entry $_</td>\n};
	print qq{<td><input type="text" name="$entrytxt" }; 
	print qq{size="$maxentrysize" maxlength="$maxentrysize"></td></tr>};
	print qq{\n};
    }

    print qq{<tr><td></td><td><input type="submit" value="$lex{Continue}"></td></tr>\n};
    print qq{</table></form></body></html>\n};

    exit;

}


#-----------
sub prHeader {
#-----------

    my ($teachername,$group) = @_;

    # Done at the start of a new page.
    print TEX "\\begin{tabular}{G|";
    if ( $studnumfield ) { print TEX "p{ $studnumwidth mm}|"; }
    if ( $extrafield ) { print TEX "p{ $extrafieldwidth mm}|"; }
    for (1..$colcount){	print TEX "p{$wi mm}|"; }
    print TEX "}\n";

    print TEX "\\raggedright\\bf $schoolname ". $lex{Classlist};
    if ( $studnumfield ) { print TEX "& "; }
    if ( $extrafield ) { print TEX "& "; }
    for ( 1..$colcount ){ print TEX "& ";}
    print TEX "\\\\ \n";

    print TEX "\\small\\raggedright $currdate\n\\bigskip ";
    if ( $studnumfield ) { print TEX "& "; }
    if ( $extrafield ) { print TEX "& "; }
    for ( 1..$colcount ){ print TEX "& ";}
    print TEX "\\\\ \n";

    # Print Grade or Homeroom, if not sorting by name
    # if ( not $group ) { $group = $lex{'Not Found'}; }

    if ( $grouptype eq 'grade' ){
	print TEX "\\Large\\raggedright $lex{Grade} $group ";
    } else { # homeroom
	print TEX "\\bf\\raggedright $teachername ";
	print TEX $lex{Rm}. " $group ";
    }


    if ( $studnumfield ) { print TEX "& "; }
    if ( $extrafield ) { 
	print TEX "&\\hfil\\rule{6pt}{0pt}\\begin{rotate}{90}$extrafieldName";
	print TEX "\\end{rotate}\\hfil";
    }

    my $remainder = $colcount - ($repeatcount * $entrysize);

    if ( $repeatcount ){
	for (1..$repeatcount){ # times to loop to print rotated text.
	    foreach my $txt ( @entry ) {
		print TEX "&\\hfil\\rule{6pt}{0pt}\\begin{rotate}{90}$txt";
		print TEX "\\end{rotate}\\hfil";
	    }
	}
    }
    for (1..$remainder){ print TEX "& ";}
    print TEX "\\\\ \\hline\n";

} # End of prHeader



#-----------
sub prRecord { # print normal record (ie. line)
#-----------
    my ( $lastname, $firstname, $studnum ) = @_;

    my ($youngest, $sex, $efield);
    my $fields = 'youngest, sex, legal_lastname, legal_firstname ';
    if ( $extrafield ) {
	$fields .= ", $extrafield"; 
    }
    my $sth1 = $dbh->prepare("select $fields from student where studnum = ?");
    $sth1->execute( $studnum );
    if ($DBI::errstr) { print $DBI::errstr; die $DBI::errstr; }
    ( $youngest, $sex, $legal_lastname,$legal_firstname, $efield ) = $sth1->fetchrow;
    ( $efield ) = latex_filter( $efield );
    if ( $youngest ) { $youngest = $lex{Y}; } 

    if ( $arr{uselegal} ) {
	my $fi = substr($firstname, 0, 1);
	my $li = substr($lastname, 0, 1);
	
	if ( $legal_lastname ) {
	    $lastname = "$li$fi ". $legal_lastname. "{\\bf\\tiny{a}}";
	}
	if ( $legal_firstname ) {
	    $firstname = $legal_firstname. "{\\bf\\tiny{a}}";
	}
    }
    

    if ( $alternatingcolor == 0 ) {
	print TEX "\\rowcolor[gray]{". $arr{grayshade}. "}";
	$alternatingcolor = 1;
    } else { $alternatingcolor = 0;}



    print TEX "\\raggedright $lastname, $firstname";
    if ( $studnumfield ) { 
	my $snfld = $studnum. $youngest. $sex;
	print TEX "&\\footnotesize{$snfld}"; 
    }

    
    if ( $extrafield ) {
	if ( %defaultvalues and $efield ) {
	    my $tmp = $efield; # store original value
	    $efield = $defaultvalues{$efield}; # display text equivalent
	    $efield .= qq{ ($tmp)};
	}
	
	print TEX "&\\hfil\\footnotesize{$efield}\\hfil"; 
    }

    for (1..$colcount){ print TEX "& ";}
    print TEX "\\\\\\hline\n";
}


#--------------
sub prStudCount {
#--------------

    #if ($alternatingcolor == 0){ # continue color from above...
    my $grayval = $arr{grayshade} - 0.08; # make it darker, slightly
    print TEX "\\rowcolor[gray]{$grayval}";
    #}
    print TEX $lex{Students}. ": $studcount";
    if ( $studnumfield ) { print TEX "& "; }
    if ( $extrafield ) { print TEX "& "; }
    for (1..$colcount){ print TEX "& ";}
    print TEX "\\\\\\hline\n";
}

