#!/usr/athena/bin/perl
#
# $Id: today.pl,v 1.9 93/03/08 20:43:06 tompalka Exp Locker: tompalka $
#
# tompalka@mit.edu
#
# read the ~/.tc files generated by xcal or xtc, and print out
# today's appointments.
# 
# $Log:	today.pl,v $
# Revision 1.9  93/03/08  20:43:06  tompalka
# took out "username" from usage, and fixed the whoami name
# 
# Revision 1.8  93/03/06  18:02:33  tompalka
# can take date as 9/1/93 or 9/1/1993. 
# 
# Revision 1.7  93/03/02  14:27:27  tompalka
# appointments are now output in sorted order..
# 
# Revision 1.6  93/03/01  16:01:10  tompalka
# support reading multiple dates in the .tc file (i wasn't aware
# of that before).  
#
#

if( $0 =~ /\// ) {
    ($WHOAMI) = ( $0 =~ /^[^ ]*\/([^\/]*)$/ );
} else {
    $WHOAMI = $0;
}

@daysofweek=("sunday", "monday", "tuesday", "wednesday", "thursday", 
	     "friday", "saturday", "sunday");

# setup the default arguments.  user's .tc file, and 3 days ahead
$tc    = $ENV{"HOME"}."/.tc";
$ndays = 3;

# parse the arguments.  the valid arguments are:
# username -> check username's idea
# number   -> display that many days in advance
# "12/23"  -> display that day's appointments
#

foreach $arg (@ARGV) {

    # username
    if($arg =~ /^[a-zA-Z]*$/) {
	@w = split(' ',`hesinfo $arg filsys`);
	$tc = $w[1]."/.tc";
	print "\n---- $arg ----\n";
	next;
    }

    # ndays ahead
    if($arg =~ /^\d+$/) {
	$ndays = $arg;
	next;
    }
    
    # specific date?
    if($arg =~ /\d+\/\d+\/\d+/) {
	# if the year is just .., prepend it with current century, to
	# make it XX..
	$arg =~ /\/..$/ && do {
	    $year = 1900+(localtime(time))[5];
	    $century = int($year/100);
	    $arg =~ s:/(..)$:/$century$1:;
	};
	$arg_date = $arg;
	next;
    }

    # invalid arg, spit out usage
    die <<EOU;
usage: $WHOAMI [numdays] [date]

All of the arguments are optional, and can be used in any order.
numdays  - display appts for the following numdays days (default: 3).
date     - display the appt for that particular date.

examples:
    $WHOAMI "01/14/1993"   -> display appt on 14 jan 1993
    $WHOAMI 30             -> display appts for the next 30 days.

comments/bugs to tompalka\@mit.edu
EOU
    ;

}

local($day) = 0;

# initialize the global %CALENDAR alist with contents of .tc
&slurp_tcfile($tc);

# now do the thing that the user wants.  if $arg_date is set, then
# we just want to see that particular date. otherwise, do it
# for ndays ahead.

if( $arg_date ) {
    $appts = $CALENDAR{$arg_date} || "no appointments";

    @cal = sort { $a<=>$b } split('\n',$appts);
    print $arg_date,":\n";
    print join("\n",@cal),"\n\n";

}
else 
{
    while($day < $ndays) {
	$iday = time + (3600*24) * $day;
	
	($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$is) = localtime($iday);
	$mon++;
	$year+=1900;
	$iday = "$mon/$mday/$year";

	$appts = $CALENDAR{$iday} || "";

	if( $appts ) {
	    @cal = sort { $a<=>$b } split('\n',$appts);

	    print @daysofweek[$wday]," ($mon/$mday):\n";
	    print join("\n",@cal),"\n\n";
	} 
	$day++;
    }
}

exit;

# ----------------------------------------


# take the $from and $to time, as well as the whole data, and 
# return a nicely formatted string.
#
sub getline {
    local($from,$to,$_) = @_;

    $allday = "[^0:\t ]";
    $from =~ s/:0$//;
    $from =~ s/:0$/:00/;
    $to   =~ s/:0$//;
    $to   =~ s/:0$/:00/;

    if( $from !~ /$allday/ && $to !~ /$allday/ ) {
	return sprintf("%13s: %s","all day    ",$_);
    } 
    return sprintf("%5s - %5s:  %s",$from,$to,$_);
}



# ----------------------------------------

# parse_tcfile takes two arguments -- the filename to parse, and 
# 
sub slurp_tcfile {
    local($tc)=@_;

    open(TC,$tc) || die "cannot read $tc: $!\n";
    while(<TC>) {
	local(@starlines,$appt);

	/^[^\*]/ && next;

	# get all the lines that start with a * (i.e. date lines)
	# into the @starlines array.
	while(/^\* /) {
	    push(@starlines,$_);
	    $_=<TC>;
	}
	
	# this line must contain the appointment
	s/^\#//;
	$appt = $_;

	foreach (@starlines) {
	    ($date,$from, $to) = ( $_ =~ /^\* (\S+) (\S+) (\S+)/ );

	    if( $date =~ /\{/ ) {
		($month,$days,$year) = ($date=~/^(\d+)\/([^\/]*)\/(\d+)$/);
		$days =~ s/\}//g;
		$days =~ s/\{//g;


		# if days are separated by dashes, then they
		# represent a range of dates.  i assume that
		# they are in the same month.
		if( $days =~ /-/ ) {
		    ($d_from,$d_to) = ($days=~/^(\d+)-(\d+)$/);
		    while($d_from <= $d_to) {
			# $ndate is the current day in this dateline
			$ndate = $month ."/". $d_from ."/". $year;
			$CALENDAR{$ndate} .= &getline($from,$to,$appt);
			$d_from++;
		    }
		} else {
		    # days are separated by commas, and specify
		    # separate days for the same appointment.
		    foreach $day (split(',',$days)) {
			# $ndate is the current day in this dateline
			$ndate = $month ."/". $day ."/". $year;
			$CALENDAR{$ndate} .= &getline($from,$to,$appt);
		    }
		}
	    } else {
		$CALENDAR{$date} .= &getline($from,$to,$appt);
	    }
	}
	next;
    }
    close TC;
}

