#!/usr/bin/perl -w

package main;

use strict;
use warnings;

# Modules
use Data::ICal::DateTime;
use Data::ICal::Entry::Event;
use DateTime;
use DateTime::Span;
use Mail::Sender;

# Constants
use constant kCalendarFile => 'example.ics';
use constant kDurationInHours => 24;
use constant kMailServer => 'smtp.example.com';
use constant kMailFrom => 'Upcoming Events <from@example.com>';
use constant kMailTo => 'Recipient <to@example.com>';


# retrieve from the calendar the events in our time window
sub get_events($)
{
	my ($now) = @_;
	
	my $cal = Data::ICal->new(filename => kCalendarFile);
	my $span = DateTime::Span->from_datetime_and_duration(start => $now, hours => kDurationInHours);
	my @events  = $cal->events($span);
	
	return \@events;
}


#determine the category to which an event belongs
sub event_category($$$)
{
	my ($start, $end, $now) = @_;
	my $category = '';
	
    if (DateTime->compare($start, $now) <= 0)
    {
    	if (DateTime->compare($end, $now) < 0)
    	{
    		$category = "Past";
    	}
    	else
    	{
    		$category = "Current";
    	}
    }
    else
    {
    	$category = "Upcoming";
    }
    
    return $category;
}


# describe events in our time window
sub describe_events($)
{
	my ($now) = @_;

	my $desc_of_events = '';
	my $event_list_ref = get_events($now);
	
	$desc_of_events .= "\nCurrent Time: " . $now->mdy('/') . " " . $now->hms . " " . $now->time_zone->short_name_for_datetime($now) . "\n";
	$desc_of_events .= "Window: " . kDurationInHours . " hours\n\n";
	
	# sort all the events into order
	my @sorted_events = sort { $a->start->epoch <=> $b->start->epoch } @{$event_list_ref};
	if (scalar(@sorted_events) > 0)
	{
		my $old_category = '';
		for (@sorted_events)
		{
			my $event = $_;
			my $start = $event->start->mdy('/') . " " . $event->start->hms;
			my $end   = $event->end->mdy('/') . " " . $event->end->hms;
			my $summ  = $event->summary || '';
			my $desc  = $event->description || '';
			my $categ = event_category ($event->start, $event->end, $now);
			
			if ($categ ne $old_category)
			{
				$old_category = $categ;
				$desc_of_events .=  $categ . " Events\n\n";
			}
			$desc_of_events .=  "  $summ\n";
			$desc_of_events .=  "    " . $start . " - " . $end . "\n";
			$desc_of_events .=  "    Desc : $desc\n" if $desc;
			$desc_of_events .=  "\n";
		}
	}
	else
	{
		$desc_of_events .= "No upcoming events within the " . kDurationInHours . " hour window.";
	}
	
	return $desc_of_events;
}


# send e-mail message
sub send_mail($$)
{
	my ($subject, $message) = @_;
	my $sender = new Mail::Sender {smtp => kMailServer, from => kMailFrom, on_errors => undef}
		or die "Can't create the Mail::Sender object: $Mail::Sender::Error\n";
	$sender->MailMsg({to => kMailTo, subject => $subject, msg => $message})
		or die "Failed to send the message: $sender->{'error_msg'}\n";
}


# main subroutine
sub main()
{
	my $now = DateTime->now(time_zone => 'local');
	my $message = describe_events($now);
	send_mail('Upcoming Events', $message);
}

main();