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

#  This file is part of Open Admin for Schools.

# Set the daybook timetable for homeroom teachers.
# Note: we should likely have a setting for which timetable to use for this: highschool or homeroom.


my %lex = ('Main' => 'Main',
	   'Error' => 'Error',
	   'Timetable Entry' => 'Timetable Entry',
	   'Timetable' => 'Timetable',
	   'Grade' => 'Grade',
	   'Term' => 'Term',
	   'Terms' => 'Terms',
	   'Day' => 'Day',
	   'Save' => 'Save',
	   'Period' => 'Period',
	   'Add Backings' => 'Add Backings',
	   'Records Stored' => 'Records Stored',
	   'Contact' => 'Contact',
	   'Separate with Spaces' => 'Separate with Spaces',
	   'Additional Subjects' => 'Additional Subjects',
	   'Continue' => 'Continue',
	   'Teacher' => 'Teacher',
	   'Or' => 'Or',
	   'Either' => 'Either',
	   'No Terms Found' => 'No Terms Found',
	   'Number of Periods' => 'Number of Periods',
	   'Same Day/Period; More Than 1 Subject' => 'Same Day/Period; More Than 1 Subject',
	   'No Terms' => 'No Terms',
	   'Course' => 'Course',
	   'Exists' => 'Exists',
	   'Skipping' => 'Skipping',
	   'Per' => 'Per',
	   'Current' => 'Current',

	   'User Id' => 'User Id',
	   'Password' => 'Password',
	   'Not Found' => 'Not Found',
	   'Cookie Duration' => 'Cookie Duration',
	   'Please Log In' => 'Please Log In',
	   'Set' => 'Set',
	   'Select' => 'Select',
	   'Add' => 'Add',
	   'Delete' => 'Delete',
	   
	   );


use DBI;
use CGI;
use CGI::Session;


my $self = "timetableset.pl";
my $maxbackings = 6; # maximum number of backed classes per cycle.


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


my $q = CGI->new;
my %arr = $q->Vars;

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



my $sth = $dbh->prepare("select datavalue from conf_system where dataname = ?");
foreach my $var ( qw( doctype chartype charset tchcss tchpage g_MTrackTerm
  g_AttendanceEntryMethod g_DaysPerCycle)) {
    $sth->execute( $var );
    my $datavalue = $sth->fetchrow;
    eval $datavalue;
    if ( $@ ) {
	print "$lex{Error}: $@<br>\n";
	die "$lex{Error}: $@\n";
    }
}

print $q->header( -charset, $charset );

my $userid = $ENV{'REMOTE_USER'};


# print page header.
my $title = "$lex{Set} Homeroom $lex{Timetable}";
print qq{$doctype\n<html><head><title>$title</title>\n};
print qq{<link rel="stylesheet" href="$tchcss" type="text/css">\n};
print qq{$chartype\n</head><body style="margin:1em;">\n};

print qq{[ <a href="$tchpage">$lex{Main}</a> ]\n};
print qq{<h1>$title</h1>\n};



# Starting Page
if ( not $arr{page} ){
    showStartPage();

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

} elsif ( $arr{page} == 2 ) {
    delete $arr{page};
    updateRecords(); # Write Records
}


#---------------
sub setTimetable {
#---------------

    # foreach my $key ( sort keys %arr ) { print "K:$key V:$arr{$key}<br>\n"; }
    # Passed: periods, various terms: term1, term2, etc.

    
    # parse passed values for termX elements. Extract X.
    my @terms;
    foreach my $key ( keys %arr ) {
	if ( $key =~ m/term(\d*)/ ) { push @terms,$1; }
    }
    my @terms = sort { $a <=> $b } @terms;

    if ( not @terms ) {
	print qq{<h3>$lex{'No Terms'}</h3>\n};
	print qq{</body></html>\n};
	exit;
    }

    my $periods = $arr{periods};
    if ( not $periods ) {
	print qq{<h3>No Periods</h3>\n};
	print qq{</body></html>\n};
	exit;
    }
	
    
    # Load Courses
    $sth = $dbh->prepare("select description, smdesc, subjsec from subject where teacher = ?");
    my (%course,%sort);
    $sth->execute($userid);
    if ( $DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; }
    while ( my ( $description,$smdesc, $subjsec ) = $sth->fetchrow ){
	$sort{"$description$subjsec"} = $subjsec;
	$course{$subjsec} = $description;
    }

    my @course; # need a sorted list of courses for display 
    foreach my $key ( sort keys %sort ) {
	push @course, $sort{$key};
    }
    

    # Load Activities
    my (%activity,%asort, @activity);
    $sth = $dbh->prepare("select * from dbkactivity where userid = ?");
    $sth->execute($userid);
    if ( $DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; }
    while ( my $ref = $sth->fetchrow_hashref ){
	my %r = %$ref;
	$asort{"$r{title}$r{id}"} = $r{id};
	$activity{$r{id}} = $ref;
    }
    foreach my $key ( sort keys %asort ) {
	push @activity, $asort{$key};
    }
    
    
    # Print Teacher
    print qq{<table cellpadding="6" cellspacing="0" border="0" };
    print qq{style="border:1px solid gray;margin:1em;">\n};
    print qq{<style>td.big { font-size:150%; }</style>\n};
    print qq{<tr>};

    my $sth = $dbh->prepare("select lastname, firstname from staff where userid = ?");
    $sth->execute( $userid );
    if ( $DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; }
    my ( $lastname, $firstname ) = $sth->fetchrow;

    print qq{<td class="big"><b>$lex{Teacher}</b></td><td class="big">$firstname $lastname</td>\n}; 

    # Print Terms
    my $terms = join(',',@terms);
    print qq{<td class="big"><b>$lex{Terms}</b></td><td class="big">$terms</td></tr>\n} ;
    print qq{</table>\n};


    print qq{<div style="font-weight:bold;font-size:120%;">};
    print qq{$lex{Current} $lex{Timetable}</div><hr style="width:40ch;margin-left:0;">\n};
    
    foreach my $trm ( @terms ) {
	printTimetable($userid,$trm );
    }
    print qq{<div style="clear:both;"></div>\n};


    my %current; # current{day}{period} = ( list of courses, activities (ACTIV-id)
    $sth = $dbh->prepare("select * from dbktimetable where userid = ?");
    $sth->execute( $userid );
    if ( $DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; }
    while ( my $ref = $sth->fetchrow_hashref ) {
	my %r = %$ref;
	push @{ $current{ $r{day} }{ $r{period} } }, $ref # course subjsec or a:id
    }



    # Print Main Layout Table
    print qq{<div style="font-weight:bold;font-size:120%;margin-top:1.5em;">};
    print qq{Add/Delete Timetable Entries</div>\n};
    
    print qq{<form action="$self" method="post">};
    print qq{<input type="submit" value="$lex{Save} Updates">\n};
    
    print qq{<input type="hidden" name="page" value="2">\n};
    print qq{<input type="hidden" name="terms" value="$terms">\n};

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

    # Set Days and Periods
    my $days = $g_DaysPerCycle;
    if ( $days eq 'w' or $days eq 'W' ) { $days = 5; } # weekly timetable.


    # Print Header Row
    print qq{<tr><th></th>};
    for my $d ( 1 .. $days ){
	print qq{<th>$lex{Day} $d</th>}; 
    }
    print qq{</tr>\n};

    
    # Print Each Row (period) then each Column (Day) in Term
    for my $per ( 1..$periods ) {
	print qq{<tr>};
	for my $day ( 0..$days ) {
	    if ($day == 0) { 
		print qq{<td class="bcn">$lex{Period} $per</td>\n};
	    } else {
		print qq{<td>};
		# display current courses/activities on this period.
		foreach my $ref ( @{ $current{$day}{$per} } ) {
		    my %r = %$ref;
		    my ($type,$id) = split('-', $r{courseact});
		    if ( $type eq 'ACTIV' ) {
			print qq{<b>Activity</b> $activity{ $id }->{title} Term $r{term}<br>\n};
			print qq{<input type="checkbox" value="1" name="DEL:$r{id}">$lex{Delete}<br>\n};
		    } else { # we have a course
			print qq{$course{$r{courseact}} ($r{courseact}) Term $r{term}\n};
			print qq{<input type="checkbox" value="1" name="DEL:$r{id}">$lex{Delete}<br>\n};
		    }
		}
		
		print qq{<b>$lex{Add}</b> <select name="$day:$per"><option value=""></option>\n};
		foreach my $subjsec ( @course ) {
		    print qq{<option value="$subjsec">$course{$subjsec} ($subjsec)</option>};
		}
		foreach my $id ( @activity ) {
		    print qq{<option value="ACTIV-$id" title="$activity{$id}->{description}">};
		    print qq{ACT $activity{$id}->{title}</option>};
		}
		print qq{</select></td>\n};

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

    my $span = $days + 1;
    print qq{</table><input type="submit" value="$lex{Save} Updates">\n};

=head
    # Now do backings...
    print qq{<p><b>$lex{'Add Backings'}</b> ($lex{'Same Day/Period; More Than 1 Subject'})</p>\n};
    print qq{<table cellpadding="3" cellspacing="0" border="1">\n};
    print qq{<tr><th>$lex{Course}</th><th>$lex{Day}</th><th>$lex{Period}</th></tr>\n};

    for ( 1..$maxbackings ){
	print qq{<tr><td><select name="b$_"><option></option>\n};
	foreach my $subjsec ( @course ) { 
	    print qq{<option value="$subjsec">$course{$subjsec} ($subjsec)</option>}; 
	}
	print qq{</select></td>\n};

	print qq{<td><input type="text" name="bd$_" size="6"></td>\n};
	print qq{<td><input type="text" name="bp$_" size="6"></td>\n};
	print qq{</tr>\n};
    }

    print qq{</table><input type="submit" value="$lex{Save}"> All Save Buttons work the same!\n};
=cut

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

    exit;

    
} # end of setTimetable



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

    # Load terms from school year configuration
    my %terms;
    foreach my $key ( sort keys %g_MTrackTerm ) {
	foreach my $t ( sort keys %{ $g_MTrackTerm{$key}} ) {
	    $terms{$t} = 1;
	}
    }

    if ( not %terms ) {
	print qq{<h1>$lex{'No Terms Found'}</h1>\n};
	print qq{</body></html>\n};
	exit;
    }


    # Get Current Teacher Name (from userid)
    my $sth = $dbh->prepare("select lastname, firstname from staff where userid = ?");
    $sth->execute( $userid );
    if ( $DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; }
    my ($lastname, $firstname ) = $sth->fetchrow;


    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" };
    print qq{style="border:1px solid gray;padding:0.4em;">\n};

    print qq{<tr><td class="bra">$lex{Select} $lex{Terms} <br>(for your timetable)</td>\n};
    print qq{<td class="la">};
    foreach my $trm ( sort {$a <=> $b} keys %terms ){
	print qq{<input type="checkbox" name="term$trm" value="1">$lex{Term} $trm<br>\n};
    }
    print qq{</td></tr>\n};


    # Load current periods values, if any.
    # load staff record for this user and get periods field, then eval it.
    my $sth = $dbh->prepare("select dbkperiods from staff where userid = ?");
    $sth->execute( $userid );
    if ( $DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; }
    my $periods = $sth->fetchrow;
#    print "PERIODS:$periods<br>\n";
    
    eval $periods;
    if ( $@ ) {
	print $lex{Error}. " for Teacher Periods: $@<br>\n";
	exit;
    }

    my $periodcount = keys %periods;
    
    
    print qq{<tr><td class="bra">$lex{'Number of Periods'}</td>};
    print qq{<td><input type="text" name="periods" size="2" value="$periodcount" style="width:20px;"> };
    print qq{(from your set periods)</td></tr>\n};
    
    print qq{<tr><td></td><td class="la"><input type="submit" value="$lex{Continue}"></td></tr>\n};
    print qq{</table></form>\n};

    
    # Display Current Timetables
    
    print qq{<div style="font-weight:bold;font-size:120%;margin:1em;">};
    print qq{$lex{Current} $lex{Timetable}</div><hr style="width:40ch;margin-left:0;">\n};

    foreach my $trm ( sort {$a <=> $b} keys %terms ){
	printTimetable($userid,$trm );
    }
    print qq{<div style="clear:both;"></div>\n};
    print qq{<hr style="width:40ch;margin-left:0;">\n};
    
    print qq{</body></html>\n};

    exit;
}


#----------------
sub updateRecords { # Write the records to dbktimetable table.
#----------------

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

    
    # Get Terms
    my @terms = split(',',$arr{terms}); # same for all
    delete $arr{terms};

    # Delete timetable entries (Activity or Course/Term)
    my $sth = $dbh->prepare("delete from dbktimetable where id = ?");
    foreach my $key ( keys %arr ) {
	my ( $type, $id ) = split(':', $key );
	if ($type eq 'DEL' ) {
	    $sth->execute( $id );
	    if ( $DBI::errstr ){ print $DBI::errstr; die $DBI::errstr; }
	    delete $arr{$key};
	}
    }

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

    # Setup to Add timetable entries.
    
    my $sth = $dbh->prepare("insert into dbktimetable (userid, term, day, period, courseact ) 
      values (?,?,?,?,?)");

    my $sth1 = $dbh->prepare("select count(*) from dbktimetable where 
       day = ? and period = ? and courseact = ? and  term = ?");

    my $sth2 = $dbh->prepare("select description from subject where subjsec = ?");


    foreach my $key ( keys  %arr ) {

	my ($day, $period) = split(':',$key );

	if ( $day and $arr{$key} and @terms ) { # filled entry
#	    print qq{K: $key V: $arr{$key} Day: $day Period: $period<br>\n};
    
	    my $courseact = $arr{$key};

	    foreach my $trm ( @terms ) {

		# Check if this record already exists;
		$sth1->execute( $day, $period, $courseact, $trm );
		if ( $DBI::errstr ){ print $DBI::errstr; die $DBI::errstr; }
		my $count = $sth1->fetchrow;
		if ( $count ) { # get description and skip
		    $sth2->execute( $courseact );
		    if ( $DBI::errstr ){ print $DBI::errstr; die $DBI::errstr; }
		    my $desc = $sth2->fetchrow;
		    print qq{<div><b>$lex{'Timetable Entry'} $lex{Exists}</b>: $desc ($subjsec) };
		    print qq{$lex{Term}:$trm  $lex{Day}:$day  $lex{Period}:$period - };
		    print qq{<b>Skipping!</b></div>\n};
		    next; # term
		}

#		print qq{D:$day P:$period S:$courseact  T:$trm<br>\n};
		$sth->execute( $userid, $trm, $day, $period, $courseact );
		if ( $DBI::errstr ){ print $DBI::errstr; die $DBI::errstr; }

	    }


	} elsif ( $arr{$key} and $key =~ m/b(\d)/){ # one of the backups...

	    my $di = "bd$1"; my $pi = "bp$1";

	    if ( not $arr{$di} ) { 
		print qq{<div style="color:red;"><b>$lex{Error}</b> - };
		print qq{Missing <b>Day</b> value for $arr{$key}. Skipping!</div>\n}; 
	    }
	    if ( not $arr{$pi} ) { 
		print qq{<div style="color:red;"><b>$lex{Error}</b> - Missing };
		print qq{<b>Period</b> value for $arr{$key}. Skipping!</div>\n}; 
	    }
	    
#	    print qq{Backup K:$key V:$arr{$key} T:$1 Day: $arr{$di} Period: $arr{$pi}<br>\n};

	    my $subjsec = $arr{$key};

	    if ( $arr{$di} and $arr{$pi} ) { # must have day and period, too.

		foreach my $trm ( @terms ){

		    # Check if this record already exists;
		    $sth1->execute( $arr{$di}, $arr{$pi}, $subjsec, $trm );
		    if ( $DBI::errstr ){ print $DBI::errstr; die $DBI::errstr; }
		    my $count = $sth1->fetchrow;
		    if ( $count ) { # get description and skip
			$sth2->execute( $subjsec );
			if ( $DBI::errstr ){ print $DBI::errstr; die $DBI::errstr; }
			my $desc = $sth2->fetchrow;
			print qq{<div>$lex{'Timetable Entry'} $lex{Exists}: $desc ($subjsec) };
			print qq{$lex{Term} $trm  $lex{Day} $arr{$di}  $lex{Period} $arr{$pi} - };
			print qq{<b>Skipping!</b></div>\n};
			next; # term
		    }

#		    print qq{BACKUP D:$arr{$di} P:$arr{$pi} S:$subjsec T:$trm<br>\n};
		    $sth->execute( $arr{$di}, $arr{$pi}, $subjsec, $trm );
		    if ( $DBI::errstr ){ print $DBI::errstr; die $DBI::errstr; }

		}

	    } # end of "if day and period, too".

	} # if backup

    } # end of for loop


    if ( not $DBI::errstr ) {
	print qq{<h3>$lex{Timetable} $lex{'Records Stored'}</h3>};

    } else {
	print qq{<h3><b>$lex{Error}</b> $DBI::errstr<br>\n};
	print qq{$lex{Contact} $adminname <a href="mailto:$adminemail">$adminemail</a></h3>\n};
    }
    
    print qq{<p>[ <a href="$schpage">$lex{Timetable}</a> ]<p>\n};
    print qq{</body></html>\n};

    exit;
}


#-----------------
sub printTimetable { # print timetable for one teacher for 1 term.
#-----------------

    my ($teacher, $term ) = @_;

    # Get Teacher Name
    my $sth = $dbh->prepare("select lastname, firstname from staff where userid = ?");
    $sth->execute( $teacher );
    my ($lastname, $firstname) = $sth->fetchrow;

    
    # Get Subjects and Activities from dbktimetable.
    my $sth = $dbh->prepare("select day, period, courseact from dbktimetable  
      where term = ? and userid = ?
      order by period, day");
    $sth->execute( $term, $teacher );
    my %courseact;  # courseact{period}{day}{courseact} = 1;
    while ( my ($day, $period, $courseact) = $sth->fetchrow ) {
#	print "Day:$day Period:$period CRS:$courseact<br>\n";
	$courseact{$period}{$day}{$courseact} = 1;
    }

    
    if ( not %courseact ) { # no timetable
	print qq{<div>No Timetable for Term $term</div>\n};
	return;
    }
    
    my $sth = $dbh->prepare("select description from subject where subjsec = ?");
    my $sth1 = $dbh->prepare("select title from dbkactivity where id = ?");

    # Find max days and periods for table.
    my ($maxperiod, $maxday);
    foreach my $period ( sort keys %courseact ) {
	foreach my $day ( sort keys %{ $courseact{$period} } ) {
	    if ( $period > $maxperiod ) { $maxperiod = $period; }
	    if ( $day > $maxday ) { $maxday = $day; }
	}
    }

    
    # print heading
    print qq{<table cellpadding="3" cellspacing="0" border="1" style="float:left;margin:0.4em;">\n};
    print qq{<caption style="font-size:120%;font-weight:bold;">$firstname $lastname - };
    print qq{$lex{Term} $term</caption>\n};

    print qq{<tr><th></th>};
    
    foreach my $day (1..$maxday){ print qq{<th>$lex{Day} $day</th>}; }
    print qq{</tr>\n};
    
    # Main body of table.
    for $period (1..$maxperiod){
	print qq{<tr><td>$lex{Per} $period</td>};
	
	foreach my $day (1..$maxday ) {
	    
	    if ( %{ $courseact{$period}{$day}}  ) {

		print qq{<td>};
		# Loop through each course/activity and print title/desc
		foreach my $crsact ( keys %{ $courseact{$period}{$day} } ) {
		    
#		    print "CRSACT:$crsact Day:$day Period:$period<br>\n";
		    
		    my $desc; # description (course) or title (activity)
		    my ($type, $id) = split('-', $crsact );
		    
		    if ( $type eq 'ACTIV' ) { # an activity
			$sth1->execute( $id );
			if ($DBI::errstr){ print $DBI::errstr; die $DBI::errstr; }
			$desc = $sth1->fetchrow;
			$desc = "<b>ACT</b> $desc";
			
		    } else { # a course (with course code)
			$sth->execute( $crsact );
			if ($DBI::errstr){ print $DBI::errstr; die $DBI::errstr; }
			$desc = $sth->fetchrow;
			$desc .= ($crsact);
		    }
			
		    print qq{$desc<br>\n};
		}
		print qq{</td>};
		
	    } else {
		print qq{<td style="color:green;">$lex{'No Value'}</td>};
	    }
	}
	print qq{</tr>\n};
    }
    print qq{</table>\n};

    return;

}
