#!/usr/bin/perl
#  Copyright 2001-2020 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.

use DBI;
use CGI;
use Time::JulianDay;

my %lex = ('View' => 'View',
	   'Eoy' => 'Eoy',
	   'Main' => 'Main',
	   'Dates' => 'Dates',
	   'School Year' => 'School Year',
	   'School Start' => 'School Start',
	   'School End' => 'School End',
	   'Term' => 'Term',
	   'Date' => 'Date',
	   'Type' => 'Type',
	   'Description' => 'Description',
	   'Track' => 'Track',
	   'Error' => 'Error',
	   'Day' => 'Day',
	   'Grade' => 'Grade',
	   'Default' => 'Default',
	   'Fraction' => 'Fraction',
	   'Cycle' => 'Cycle',
	   'Day' => 'Day',
	   'No' => 'No',
	   'Yes' => 'Yes',
	   'Closed' => 'Closed',
	   'Open' => 'Open',
	   'Start' => 'Start',
	   'End' => 'End',
	   'Total' => 'Total',

	   );

my %dowclosed = ('0' => 1, '6' => 1); # Day 0 is Sunday, Day 6 is Saturday

my $self = 'dateView.pl';

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

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

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



# populate jdclosed with dates from dates table; used by calcTermDays;
my %jdclosed;
my $sth = $dbh->prepare("select date, dayfraction from dates 
  where date is not NULL and date != ''");
$sth->execute;
if ($DBI::errstr) { print $DBI::errstr; die $DBI::errstr; }

while ( my ( $date, $dayfraction ) = $sth->fetchrow ) {
    my $jd = julian_day( split( '-', $date ) );
    $jdclosed{$jd} = $dayfraction;
}


my $title = "$lex{View} $lex{Dates}";
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>\n};

print qq{[ <a href="$homepage">$lex{Main}</a> | \n};
print qq{<a href="$eoypage">$lex{Eoy}</a> ]\n};

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


# Print School Year, Term Dates stored in configuration system.
print qq{<div style="float:left;">\n}; # float first 2 tables together.

print qq{<table cellpadding="4" border="0" cellspacing="0" style="border:1px solid gray;};
print qq{margin-bottom:1em;padding:0.5em;margin:0.5em;">\n};
print qq{<tr><td class="ra">$lex{'School Year'}</td><td class="bla">$schoolyear</td></tr>\n};
print qq{<tr><td class="ra">$lex{'School Start'}</td><td class="bla">$schoolstart</td></tr>\n};
print qq{<tr><td class="ra">$lex{'School End'}</td><td class="bla">$schoolend</td></tr>\n};
print qq{</table>\n};


# Print Terms 
# Loop through all tracks.
foreach my $trk ( sort keys %g_MTrackTerm ) {

    print qq{<table cellpadding="3" border="0" cellspacing="0" };
    print qq{style="border:1px solid gray;padding:0.5em;margin:0.5em;">\n};

    print qq{<tr><td colspan="3" class="bcn">$lex{Track} $trk - $g_TrackDisplay{$trk}</td></tr>\n};
    print qq{<tr><td colspan="3" class="bcn">$lex{Grade} };
    foreach my $grade ( sort {$a <=> $b} keys %g_MTrackTermType ) {
	if ( $g_MTrackTermType{$grade} eq $trk ) { print qq{$grade } }
    }
    print qq{</td></tr>\n};


    # Print Terms in this Track
    my $totaldays;
    print qq{<tr><th></th><th>$lex{Start}</th><th>$lex{End}</th>};
    print qq{<th>$lex{Open}</th><th>$lex{Closed}</th></tr>\n};
    foreach my $trm ( sort keys %{ $g_MTrackTerm{$trk} } ) {

	print qq{<tr><td class="bla">$lex{Term} $trm ($g_TermDisplay{$trk}{$trm})</td>};
	print qq{<td class="la">$g_MTrackTerm{$trk}{$trm}{start}</td>};
	print qq{<td class="la">$g_MTrackTerm{$trk}{$trm}{end}</td>\n};

	my $val = calcTermDays($g_MTrackTerm{$trk}{$trm}{start},
			       $g_MTrackTerm{$trk}{$trm}{end}, \%jdclosed );
	my ($open,$closed) = split(':', $val);
	$totaldays += $open;
	print qq{<td class="cn">$open</td><td class="cn">$closed</td></tr>\n};

    }
    
    print qq{<tr><td colspan="3" class="bra">$lex{Total}</td>};
    print qq{<td class="bcn">$totaldays</td><td></td></tr>\n};
    print qq{</table>\n};
}



# Print the Stored Dates (in Dates Table)
print qq{<table cellpadding="3" border="1" cellspacing="0" style="margin:0.5em;">\n};
print qq{<caption style="font-size:130%;font-weight:bold;">$lex{Dates} $lex{Closed}</caption>\n};

print qq{<tr><th>$lex{Date}</th><th>$lex{Day}</th><th>$lex{Type}</th>\n};
print qq{<th>$lex{Description}</th><th>$lex{Cycle}<br>$lex{Day}</th>};
print qq{<th>$lex{Fraction}<br>Closed</th><th>Periods<br>Closed</th></tr>\n};


my $sth = $dbh->prepare("select * from dates order by date");
$sth->execute;
if ($DBI::errstr) { print $DBI::errstr; die $DBI::errstr; }

my $sth1 = $dbh->prepare("select grades, period from dates_periods 
   where date = ? order by grades, period");


while ( my ( $id, $date, $type, $desc1, $desc2, $dayincycle, $dayfraction ) = $sth->fetchrow ) {
    my ($year, $month, $day ) = split('-', $date);
    my $newdate = $year .'-'. $s_month[$month]. q{-}. $day;
    my $jd = julian_day( split( '-', $date ) );
    my $dow = day_of_week($jd);

    # add periods closed for this date
    my %periods;
    $sth1->execute($date);
    if ($DBI::errstr) { print $DBI::errstr; die $DBI::errstr; }
    while ( my ($grades,$period) = $sth1->fetchrow ) {
	push @{ $periods{$grades} }, $period;
    }

    if ( not $dayincycle ) { 
	$dayincycle = $lex{No}; 
    } else { 
	$dayincycle = $lex{Yes};
    }

    if ($dayfraction eq '1.000' ) {
	$dayfraction = 'All Day';
    } else {
	$dayfraction = '<b>Partial</b>';
    }
    
    print qq{<tr><td>$newdate</td><td>$dowstd[$dow]</td><td>$type</td><td>$desc1</td>\n};
    print qq{<td class="cn">$dayincycle</td><td>$dayfraction</td>};

    print qq{<td>};
    foreach my $gr ( sort keys %periods ) {
	my $per = join(',', @{ $periods{$gr} });
	print qq{<b>$gr</b> $per<br>\n};
    }
    print qq{</td></tr>\n};

}

print qq{</table>\n};
print qq{</div><!-- End of Float for first 3 tables -->\n};


# end of left div here, start right div
#print qq{</div><div>\n};

# now print each of the calendar months in a table.


my @tmp = split('-', $schoolstart);
my $startyear = $tmp[0];
my $count;
foreach my $mo ( $tmp[1]..12 ) {
    showMonthCalendar( $startyear, $mo);
    $count++;
    if ( $count % 2 == 0 ) { print qq{\n<br clear="left">\n}; }
}
print qq{<br clear="left">\n}; 

my $nextyear = $startyear + 1;
foreach my $mo ( 1..6 ) {
    showMonthCalendar( $nextyear, $mo);
    if ( $mo % 2 == 0 ) { print qq{\n<br clear="left">\n}; }
}


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


#---------------
sub calcTermDays {
#---------------

    # passed a start date and an end date for a term, and a ref to a
    # hash storing the closure dates in julian day format, it will
    # return a count of the days open in the month.

    # outline: convert start/end dates to jd. Loop over all days. Use modulus function to ident weekend days.

    my ($startdate, $enddate, $closeref ) = @_;
    my %jdclosed = %$closeref;

=head
    print qq{JDClosed<br>\n";
    foreach my $key ( sort keys %jdclosed ) {
	print qq{K:$key V:$jdclosed{$key}<br>\n";
    }
    print qq{End JDClosed<br>\n";
=cut

    my $startjd = julian_day(split('-',$startdate));
    my $endjd = julian_day(split('-',$enddate));

    my %modclosed; # modulus for days closed
    foreach my $inc ( 0..6 ) {
	my $testjd = $startjd + $inc;
	my $dow = day_of_week($testjd);
	if ( $dowclosed{$dow} ) { # $testjd is a closed dow
	    my $mod = $testjd % 7;
	    $modclosed{$mod} = 1;
	}
    }

#    foreach my $d ( sort keys %modclosed ) {
#	print qq{Closed Mod: $d<br>\n";
#    }

    my ($daysopen, $daysclosed);
    foreach my $jd ( $startjd..$endjd ) {

	my $dow = day_of_week( $jd );
	my $mod = $jd % 7;

	if ( $modclosed{$mod} ) { # closed for weekend
	    next;
	}

	# check if a day closed
	my $cl = $jdclosed{ $jd };
	if ( $cl  ) { # this gives us the fraction closed
	    $daysclosed += $cl;
	    # only add on the fraction of day open
	    $daysopen += (1 - $cl );
	} else {
	    $daysopen += 1;
	}


    }

    # print qq{ST:$startdate END:$enddate  Count:$daycount<br>\n";

    return "$daysopen:$daysclosed";

}


#--------------------
sub showMonthCalendar {
#--------------------

    # passed year-month value
    my ($yr,$mo) = @_;
    if ( length $mo == 1 ) { $mo = '0'. $mo; }
    
#    print "Y:$yr M:$mo<br>\n";
    
    # Find dow for first of the month
    my $startdate = "$yr-$mo-01";
    my $startjd = julian_day( split('-', $startdate) );
    my $startdow = day_of_week($startjd);

    # Find last day of the month (eomday)
    my $nextmonth = $mo + 1;
    my $tempyear = $yr;
    if ( $nextmonth == 1 ) { $tempyear++; }
    my $eomjd = julian_day($tempyear,$nextmonth,'1');
    my @temp = inverse_julian_day( $eomjd - 1 );
    my $eomday = $temp[2];

    # Set number of rows in the calendar
    my $rowcount = 5; # 5 rows in the calendar.
    my $totalcells = $eomday + $startdow; # total cells required in calendar.
    if ( $totalcells > 36 ) { $rowcount = 6; }  # to accomodate all the dates in the month.
    

    # Add Style settings for calendar
    print qq{<style>\n.caldate { font-size:140%;font-weight:bold; }</style>\n};

    
    # Get the days closed (>0.999) in the month.
    my %dayclosed;
    my $sth = $dbh->prepare("select * from  dates where month(date) = ? and  year(date) = ?");
    $sth->execute( $mo, $yr );
    if ( $DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; }
    while ( my $ref = $sth->fetchrow_hashref ) {
	my $date = $ref->{date};
	if ( exists $dayclosed{$date} ) { # Error;
	    print qq{<h3>Error: Duplicate Date Record: $date</h3>\n};
	}
	$dayclosed{$date} = $ref;
    }


  
    # Calendar Table
    print qq{<table cellspacing="0" border="1" cellpadding="4" };
    print qq{style="border:1px solid gray;margin:0.5em;margin-bottom:1em;float:left;">\n};
    print qq{<caption style="font-size:144%;font-weight:bold;">};
    print qq{$month[$mo], $yr - <span style="font-size:70%;">Hover to see fraction closed</span></caption>\n};

    
    # Days of the Week Header
    print qq{<tr>};
    foreach my $da (0..6) { # day 1 (Sunday) and 7 (Saturday) not used, of course.
	print qq{<th>$dow[$da + 1]</th>};
    }
    print qq{</tr>\n};

    my ($calday, $caldate); # set and updated through the month.
    foreach my $row (1..$rowcount) {
	print qq{<tr>};
	foreach my $col (0..6) {

	    # Set the starting calendar day
	    if ($row == 1 and $col == $startdow ) {
#		print qq{Row:$row  COL:$col StartDOW:$startdow<br>\n};
		$calday = 1; 
	    }
	    my $tempday = $calday;
	    if ( length $tempday == 1 ) { $tempday = '0'. $tempday; }
	    if ( $calday ) { $caldate = qq{$yr-$mo-$tempday}; }
	    
#	    print "CALDATE:$caldate<br>\n";
	    
	    if ( $col == 0 or $col == 6 ) { # a weekend or closed
		print qq{<td style="background-color:#DDD;">};
		print qq{<span>$calday</span></td>\n};
		
	    } else { # a week day
		
		print qq{<td><span class="caldate">$calday</span><br>};

		if ( $dayclosed{$caldate} ) {
		    my %r = %{ $dayclosed{$caldate}};
		    print qq{<span style="background-color:#AFA;padding:0.2em;border:1px solid gray;" };
		    print qq{title="$r{dayfraction} closed">};
		    print qq{$r{type} - $r{desc1}</span>\n};
		}

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

	    if ($calday) { $calday++; }
	    if ( $calday > $eomday ) { $calday = ''; $caldate = ''; }
	}
	print qq{</tr>\n};
    }
    
    print qq{</table>};

    


}
