#!/usr/bin/perl -w

use strict;
use Date::Parse;
use Email::Date::Format qw(email_date);
use File::Slurp qw(slurp);
use Getopt::Long;
use Mail::Sendmail;
use POSIX qw(strftime);

# outgoing SMTP server
my $SMTP = 'localhost';

# who this goes to
my $ME = 'dmarti@zgp.org';

my $TODO_FOLDER = '/home/dmarti/Maildir/INBOX';

my @TODOS_IN = ($TODO_FOLDER,
                '/home/dmarti/Maildir/pim',
);

my $When = '';
my $Verbose = 0;
my $Priority = '';
my $AlarmInterval;

GetOptions ("date|dtstart|d=s" => \$When,
            "priority|p=s" => \$Priority,
            "alarm|a:s" => \$AlarmInterval,
            "verbose|v" => \$Verbose);

if (defined($AlarmInterval) and not $AlarmInterval) {
    $AlarmInterval = 600;
}

my $what = join (' ', @ARGV);
my $athost = $1 if $ME =~ /@(.+)$/;
my $message_id = join ('.', time(), $$, $athost);
my $show_date = strftime("%e %b", localtime);

if ($AlarmInterval) {
    print "doing alarm";
    show_alarms($AlarmInterval);
    exit(0);
} elsif ($what !~ /\S/) {
    show_todos();
    exit(0);
}

my %message = ( 'From'    =>    "$show_date <$ME>",
                'To'      =>    $ME,
                'Date'    =>    email_date(),
                'Subject' =>    $what,
                'Message-ID' => "<$message_id>",
                'X-Todo'  =>    'new item',
         );

if ($When) {
    $message{'X-Dtstart'} = email_date(str2time($When));
}

if ($Priority) {
    $message{'X-Priority'} = $Priority;
}

if (!write_direct()) {
    print STDERR "\n";
    $message{'smtp'} = $SMTP;
    sendmail ( %message ) or die $Mail::Sendmail::error;
}

sub show_alarms {
    my $interval = shift;
    my $now = time();
    my @items = get_items(@TODOS_IN);
    foreach my $item (sort 
                      {$a->{'sort-date'} <=> $b->{'sort-date'}} @items) {
        next if !exists($item->{'X-Dtstart'});
        next if $item->{'sort-date'} > $now + $interval;
            print $item->{'sort-date'};
            print_item($item);
    }
}

sub show_todos {
    my @items = get_items(@TODOS_IN);
    my %priorities = ();
    foreach my $item (@items) {
        if ($item->{'X-Priority'}) {
            $priorities{$item->{'X-Priority'}} = 1;
        }
    }

    # calendar items
    print "Calendar items\n--------------\n";
    my $cal_count = 0;
    foreach my $item (sort 
                      {$a->{'sort-date'} <=> $b->{'sort-date'}} @items) {
        next if !exists($item->{'X-Dtstart'});
            print_item($item);
            $cal_count++;
    }
    print "No calendar items.\n" if !$cal_count;
    print "\n";

    # non-calendar items
    foreach my $p (sort keys(%priorities)) {
        print $p, "\n", '-' x length($p), "\n";
        foreach my $item (sort 
                          {$a->{'sort-date'} <=> $b->{'sort-date'}} @items) {
            next if exists($item->{'X-Dtstart'});              
            next if $item->{'X-Priority'} ne $p;
            print_item($item);
        }
        print "\n";
    }
    print "\n";
}

sub print_item {
    my $item = shift;
    if (exists($item->{'X-Dtstart'})) {
        print $item->{'X-Dtstart'}, " ";
    }
    print $item->{'Subject'}, "\n";
    if (exists($item->{'content'})) {
        foreach my $line (split(/\n/, $item->{'content'})) {
            print "  ", $line, "\n";
        }
    }
}



sub write_direct {
    my $dest;
    if (-d "$TODO_FOLDER/new") {
        $dest = "$TODO_FOLDER/new";
    } elsif (-d $TODO_FOLDER) {
        $dest = $TODO_FOLDER;
    } else {
        return undef;
    }
        
    open (FCC, "> $dest/$message_id") or return undef;
    foreach my $key (keys(%message)) {
        print FCC "$key: $message{$key}\n" or return undef;
    }
    close(FCC) or return undef;
    return(1);
}

sub get_items {
    my @todos_in = @_;
    my @result = ();
    foreach my $dir (@todos_in) {
        opendir (my $dh, $dir) or die "Can't open $dir";
        foreach my $file (readdir($dh)) {
            if (-d "$dir/$file" and ($file eq 'cur' or $file eq 'new')) {
                push(@result, get_items("$dir/$file"));
            }
            next if !-r "$dir/$file" or !-f "$dir/$file";
            my $content = slurp("$dir/$file");
            my $text; my $headers;
            ($headers, $text) = (split (/\n\n/, $content, 2));
            if ($headers =~ /^X-Todo/mi or
                $headers =~ /^X-Dtstart/mi) {
                my %item = ();
                foreach my $line (split(/\n/, $headers)) {
                    my $k; my $v;
                    ($k, $v) = split(/:\s+/, $line, 2);
                    $item{$k} = $v;
                    if ($k eq 'X-Dtstart') {
                        $item{'sort-date'} = str2time($v); 
                    } elsif ($k eq 'Date' and !exists($item{'sort-date'})) {
                        $item{'sort-date'} = str2time($v);
                    }
                }
                $item{'X-Priority'} = 'z' if !exists($item{'X-Priority'});
                $item{'X-Priority'} = uc($item{'X-Priority'});
                if (defined($text) and $text =~ /\S/) {
                    $item{'content'} = $text;
                }
                push (@result, \%item);
            }
        }
    }
    return @result;
}
