#! /usr/bin/perl -w
#This program calculates the page of the "Women of the East Side" Calendar
#that most resembles the current month, or the month specified in the
#command-line arguments.
require POSIX;
use strict;
my @monthlengths=(31,28,31,30,31,30,31,31,30,31,30,31);
#$sum=0;for(@monthlengths){$sum+=$_}print$sum,"\n";
my @startday;my @monthcal;my @yearcal;my @human_readable;my @pages=(0..16);
&initialize();

my @timevec=localtime(time()) or die;
my $curmonth=$timevec[4];
my $curday=$timevec[3];
my $curweek=$timevec[6];
my $curyear=$timevec[5];
if(@ARGV){
  die if @ARGV>2;
  # we accept a month and optionally a year (default this year)
  # if we want the calendar for a different month than the current month
  die unless $ARGV[0]=~/^\d+$/;
  $curmonth=$ARGV[0]-1;
  die unless $curmonth>=0;
  die unless $curmonth<12;
  if($ARGV[1]){
    die unless $ARGV[1]=~/^\d+$/;
    $curyear=$ARGV[1]-1900;
  }
  $curday=1;
  #because tzset is NOT called, there should not be an UTC vs EST skew
  my $tt=POSIX::mktime(0,0,0,$curday,$curmonth,$curyear)
    or die; # year not between 1902..2038

  @timevec=localtime($tt);
  die unless $curmonth==$timevec[4];
  die unless $curday==$timevec[3];
  die unless $curyear==$timevec[5];
  $curweek=$timevec[6];
}
if (0){
$curmonth=3;
$curday=12;
$curweek=6;
}
die unless $curmonth>=0;
die unless $curmonth<12;
die unless $curday>=1;
die unless $curday<=31;
die unless $curweek>=0;
die unless $curweek<7;
print "Today is ",POSIX::strftime("%A, %B %d, %Y",0,0,0,$curday,$curmonth,$curyear,$curweek),".\n";

my $first=($curweek-$curday+71)%7;
# plus 1, plus an even multiple of 7 to avoid negative

print "The 1st of the month was a ",&get_day_of_week($first),".\n";

my $exact=0;
for(@pages){
  #print "page $_\n";
  if($startday[$_]==$first){
    if ($monthlengths[$monthcal[$_]]==$monthlengths[$curmonth]){
      print "EXACT MATCH: $human_readable[$_]\n";
      $exact=1;
    }
  }
}

# remove the 0 to omit close matches if an exact match is found.
unless ($exact && 0){
  for(@pages){
    #print "page $_\n";
    if($startday[$_]==$first){
      if ($monthlengths[$monthcal[$_]]!=$monthlengths[$curmonth]){
	#number of days in the month is wrong
	print "Close match: $human_readable[$_]\n";
      }
    }
  }
}

sub initialize {
  # February 2006 starts on a Wednesday
  my $mcount=1; #Jan=0, Feb=1
  my $wcount=3; #Sun=0, ... Wed=3
  my $ycount=106;
  for(@pages){
    push @startday,$wcount;
    push @monthcal,$mcount;
    push @yearcal,$ycount;
    push @human_readable,POSIX::strftime("%B %Y",0,0,0,1,$mcount,$ycount);


    my $days_in_month=$monthlengths[$mcount];
    $wcount=($wcount+$days_in_month)%7;
    $mcount=($mcount+1)%12;
    if($mcount==0){
      $ycount++;
    }
  }
}

=pod

for(@pages){
  print "",(1+$monthcal[$_]),"/",1900+$yearcal[$_];
  #," ",$startday[$_],"\n";
  $str=&get_day_of_week($startday[$_]);
  print " $str\n";
}

=cut

sub get_day_of_week {
  my $x=shift;
  POSIX::strftime("%A", 0, 0, 0, 0,0,0,$x);
}
