#!/usr/bin/perl -w

use strict;

use DateTime;

my ($eventName, $eventLocation, $eventTime, $eventDesc) = (0, "", "", "");
my $slurp = 0;
my $line;
my $uid = 0;

sub icalTime($) {
	my $time = shift;
	my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = gmtime($time);
	return sprintf('%04d%02d%02dT%02d%02d%02dZ', $year+1900, $mon+1, $mday, $hour, $min, $sec);
}

sub icalTextEscape($) {
	my $s = shift;
	# Normalize on 'NIX
	$s =~ s/\r\n/\n/g;
	$s =~ s/\r/\n/g;
	$s =~ s/([\\;,])/\\$1/g;
	# And finally, escape newlines
	$s =~ s/\n/\\n/g;
	return $s;
}

sub icalPrint {
	my $text = shift;
	my $line;
	my $maxlen = 75;
	while (length $text > $maxlen) {
		if ($maxlen == 75) {
			$line = substr($text, 0, $maxlen);
			$maxlen = 74;
		} else {
			print ' ';
			$line = substr($text, 0, $maxlen);
		}
		print $line;
		$text = substr($text, length($line));
		print "\r\n";
	}
	# Print whatever's left
	if ($maxlen < 75) {
		print " ";
	}
	print $text, "\r\n";
}

sub deHTML($) {
	my $s = shift;
	# Step 1: un-HTML it
	$s =~ s/<!--.*?-->//g;
	$s =~ s/&amp;/&/g;
	$s =~ s/[\r\n]//g;
	$s =~ s/\s+/ /g;
	# Reintroduce line breaks as needed
	$s =~ s/<br\s*\/?>/\n/g;
	$s =~ s/<p\s*>/\n\n/g;
	# Finally, kill all remaining tags
	$s =~ s/<[^>]+>//g;
	# And kill any leading/trailing whitespace
	$s =~ s/^\s*|\s*$//g;
	return $s;
}

sub processEvent {
	if ($eventName) {
		if ($eventTime) {
			# Try and parse the time
			if ($eventTime =~ /(Friday|Saturday|Sunday),\s*(\d+):(\d+)\s*(am|pm)\s*-\s*(\d+):(\d+)\s*(am|pm)/) {
				my $day = 11;
				if ($1 eq 'Saturday') {
					$day = 12;
				} elsif ($1 eq 'Sunday') {
					$day = 13;
				}
				my $startHour = $2;
				my $startMin = $3;
				$startHour += 12 if ($4 eq 'pm' and $startHour < 12);
				my $endHour = $5;
				my $endMin = $6;
				$endHour += 12 if ($7 eq 'pm' and $endHour < 12);
				my $startTime = DateTime->new(
						'year' => 2011,
						'month' => 3,
						'day' => $day,
						'hour' => $startHour,
						'minute' => $startMin,
						'time_zone' => 'America/New_York'
					);
				my $endTime = DateTime->new(
						'year' => 2011,
						'month' => 3,
						'day' => $day,
						'hour' => $endHour,
						'minute' => $endMin,
						'time_zone' => 'America/New_York'
					);
				icalPrint("BEGIN:VEVENT");
				icalPrint(sprintf("UID:pax-east-\%04d\@east.paxsite.com", $uid++));
				icalPrint("DTSTAMP:" . icalTime(time()));
				icalPrint("DTSTART:" . icalTime($startTime->epoch()));
				icalPrint("DTEND:" . icalTime($endTime->epoch()));
				icalPrint("SUMMARY:".icalTextEscape(deHTML($eventName)));
				icalPrint("LOCATION:".icalTextEscape($eventLocation)) if $eventLocation;
				icalPrint("DESCRIPTION:".icalTextEscape(deHTML($eventDesc))) if ($eventDesc);
				icalPrint("END:VEVENT");
			} else {
				print STDERR "Unable to parse the event time (", $eventTime, ") for event ", $eventName, "! Leaving it out!\n";
			}
		} else {
			print STDERR "No event time found for event ", $eventName, "! Leaving it out!\n";
		}
		$eventName = 0;
		$eventLocation = "";
		$eventTime = "";
		$eventDesc = "";
	}
}

icalPrint("BEGIN:VCALENDAR");
icalPrint("VERSION:2.0");
icalPrint("PRODID:-//perl/pax-east//NONSGML v1.0//EN");

while ($line = <>) {
	if ($line =~ /<div class="faqhead">(.*)<\/div>/) {
		my $n = $1;
		# Process the current event, if any
		processEvent();
		$eventName = $n;
	} elsif ($line =~ /<div class="news">(.*)<br>/) {
		$eventLocation = $1;
		# Now grab the next line for the time
		while (1) {
			if ($line = <>) {
				next if ($line =~ /^\r?\n?$/);
				if ($line =~ /^\s*(.*)<br>/) {
					$eventTime = $1;
					last;
				} else {
					print STDERR "Unable to parse time for event!\n";
					last;
				}
			} else {
				print STDERR "Missing time for event!\n";
				last;
			}
		}
		$slurp = 1;
	} elsif ($slurp) {
		# See if we should stop
		if ($line =~ /<div style="display: block;/) {
			$slurp = 0;
		} else {
			$eventDesc .= $line;
		}
	}
}
# Process the last event, if any
processEvent();

icalPrint("END:VCALENDAR");
