#!/usr/bin/perl

# etff: Eat the Frog First

use strict;
use Date::Parse;
use DB_File::Lock;
use Email::Simple;
use File::Find;
use File::Slurp qw( slurp ) ;

use constant DAY => 86400;

use constant TASK => 0;
use constant META => 1;
use constant FILENAME => 2;
use constant AGE => 3;
use constant DEADLINE => 4;

use constant SKIP => 0;
use constant CHECK => 1;
use constant UNKNOWN => 2;

my $DB = '/home/dmarti/.etff';
my $SPAM = '/home/dmarti/Maildir/spam';
my %Todo_messages;

my %Item;

my $Last_modified = 90;
if (-e $DB) {
    $Last_modified = -M $DB;
}
my $Now = time();

tie(%Todo_messages, 'DB_File::Lock', 
    [$DB, O_RDWR|O_CREAT, 0660, $DB_HASH], 'write')
    or die "Can't open $DB (another copy running?)\n";

find (\&wanted, '/home/dmarti/Maildir');
untie(%Todo_messages) or die $!;

foreach my $item (values(%Item)) {
    $item->[DEADLINE] = $Now + 365 * DAY;
    if ($item->[META] =~ /^done/i) {
        # recycle old done items?
        ;
    } elsif ($item->[META] =~ /^A\b/i) {
        $item->[DEADLINE] = $Now;
    } elsif ($item->[META] =~ /^(B)\b/i) {
        $item->[DEADLINE] = $Now + 7 * DAY;
    } elsif ($item->[META] =~ /^(C)\b/i) {
        $item->[DEADLINE] = $Now + 1000 * DAY;
    } elsif ($item->[META] =~ /^due\s+(.*)/) {
        $item->[DEADLINE] = str2time($1);
    } else {
        defined($ENV{'EDITOR'}) and -e $ENV{'EDITOR'} or die $!;
        exec ($ENV{'EDITOR'}, $item->[FILENAME]);
    }
}

print "Items due today\n----- --- -----\n";
foreach my $item (sort {$a->[DEADLINE] <=> $b->[DEADLINE]} values(%Item)) {
    next if !$item->[DEADLINE];
    next if $Now + 1 * DAY < $item->[DEADLINE];
    print "$item->[TASK]    $item->[META]\n";
}

print "\nOther\n-----\n";
foreach my $item (sort {$a->[DEADLINE] <=> $b->[DEADLINE]} values(%Item)) {
    next if $item->[DEADLINE] < $Now + 1 * DAY;
    next if $item->[META] =~ /^done$/i;
    print "$item->[TASK]    $item->[META]\n";
}

sub is_todo {
    my $file = shift;
    my $result = UNKNOWN;
    if (exists($Todo_messages{$file})) {
        $result = $Todo_messages{$file};
    }
    return $result;
}

sub wanted {
    my $file = $File::Find::name;
    next if $file =~ /^$SPAM/;
    if (-f $file) {
        if (-M $file < $Last_modified or is_todo($file) != SKIP) {
            # print "checking $file\n";
            my $text = slurp($file);
            my $email = Email::Simple->new(\$text);
            if (my $todo = $email->header('X-Todo')) {
                $Todo_messages{$file} = CHECK;
                if (my $mid = $email->header('Message-ID')) {
                    unless (exists $Item{$mid} 
                            and -M $file > $Item{$mid}->[AGE]) {
                        $Item{$mid} = [$email->header('Subject'), 
                                       $todo, $file, -M $file];
                        } else {
                            print "dup $Item{$mid}->[TASK]\n";
                        }
                }
            } else {
                $Todo_messages{$file} = SKIP;
            }
        }
    }
}
