The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
#!/usr/bin/perl -w
use 5.010;
use strict;
use warnings;
use autodie;
use utf8::all;

# ABSTRACT: Command line interface to idonethis.com

our $VERSION = '0.23'; # VERSION: Generated by DZP::OurPkg::Version

# PODNAME: idone


use Getopt::Std;
use Pod::Usage;
use WebService::Idonethis;
use Config::Tiny;
use POSIX qw(tzset strftime);
use Date::Manip::Date;
use constant ONE_DAY => 86400;      # Seconds in a day

# Make Getopt less wrong.
$Getopt::Std::STANDARD_HELP_VERSION = 1;
sub VERSION_MESSAGE { pod2usage(1); }

my %opts = (
    'c' => undef,                            # STDIN
    'd' => undef,                            # Date
    'f' => "$ENV{HOME}/.idonethisrc",        # Config
    'h' => undef,                            # Help
    'l' => undef,                            # List
    'r' => undef,                            # Range
    'V' => undef,                            # Version
    'y' => undef,                            # Yesterday
);

getopts('cd:f:hlr:Vy', \%opts);

if ($opts{h}) {
    pod2usage(1);
}

if ($opts{V}) {
    say "idone version " , WebService::Idonethis->VERSION;
    exit 1;
}

my $config = Config::Tiny->read( $opts{f} );

unless ($config->{auth}{user}) {
    die "Cannot find credentials in $opts{f}\n";
}

my $idt = WebService::Idonethis->new(
    user     => $config->{auth}{user},
    pass     => $config->{auth}{pass},
    calendar => $config->{auth}{calendar}
);

# Range processing

# BUG: If '-r' is provided with no argument, this doesn't seem
# to trigger. So don't do that.

if ($opts{r}) {

    if ( $opts{d} or $opts{y} or $opts{c} ) {
        die "-r cannot be used with either -d, -y or -c\n";
    }

    if (@ARGV) {
        die "Items cannot be added to idone with C<-r>\n";
    }

    my ($from, $to) = split(/\s*,\s*/, $opts{r});

    $to ||= 'now';

    unless ($from) {
        die "At least a start date is required for -r\n";
    }

    $from = parse_date($from);
    $to   = parse_date($to);

    my $dones = $idt->get_range($from, $to);

    # Results seem to come back in reverse chronological order,
    # so we reverse them here.

    foreach my $item (reverse @$dones) {
        say "[$item->{done_date}] $item->{text}";
    }
    
    exit 0;
}

my $date = parse_date( $opts{d} || strftime("%Y-%m-%d",localtime()) );

# Handle yesterday if '-y' switch is turned on.
if ($opts{y}) {
    $date = strftime("%Y-%m-%d", localtime(time() - ONE_DAY));
}

# If we've been given an argument, insert that as a done.

if (@ARGV) {
    $idt->set_done( text => "@ARGV", date => $date );
}

elsif (not $opts{l}) {
    # No arguments, and no -l implies -c
    $opts{c} = 1;
}

# List items, if required.

if ($opts{l}) {
    my $dones = $idt->get_day($date);

    say "\nDone tasks for $date:\n";

    foreach my $item (@$dones) {
        say "* $item->{text}";
    }
}

# Read items, if requested.

if ($opts{c}) {
    say "\nReading done items for $date (one per line).\n";
    while (<STDIN>) {
        chomp;
        $idt->set_done( text => $_, date => $date );
    }
}

sub parse_date {
    my ($date) = @_;

    if ($date !~ /^\d{4}-\d{2}-\d{2}$/) {
        my $dmd = Date::Manip::Date->new;
        if ($dmd->parse($date)) {
            die "Can't parse date '$date' - " . $dmd->err . "\n";
        }
        $date = $dmd->printf("%Y-%m-%d");
    }

    return $date;
}

__END__

=pod

=head1 NAME

idone - Command line interface to idonethis.com

=head1 VERSION

version 0.23

=head1 SYNOPSIS

    # Submit an item to idonethis.com
    $ idone "Installed some cool software today."

    # See what I've done today.
    $ idone -l

    # Add an item to idonethis, and then show everything I've done
    $ idone -l "Calibrated the flux capacitor"

    # See what I've done yesterday.
    $ idone -ly

    # See what I did some time ago.
    $ idone -ld 2012-01-01
    
    # See what I've done today, and read new items from STDIN.
    $ idone -lc

    # See what I've done yesterday, and add more items from STDIN.
    $ idone -lcy

    # See what I've done in the last week
    $ idone -lr 'last week,today'

    # In ~/.idonethisrc
    [auth]
    user=someuser
    pass=somepass
    calendar=some calendar name

=head1 DESCRIPTION

By default, this submits items to your personal calendar on idonethis.  All
arguments are concatenated together to form a single string, which
is then submitted to your calendar for the current day (using the
local timezone on your machine).

The C<calendar> name is optional, and if present will be searched
for in first the URL, then as a text link. If not found, your username
will be used, and if all else fails, idone will default to your
personal calendar.

Patches are extremely welcome.  L<https://github.com/pjf/idonethis-perl>

=head1 OPTIONS

=over

=item B<-c>

Read items from STDIN and add them to your done list, with one item per
line. This is the default behaviour if C<-l> is not specified, nor any
done item on the command line.

=item B<-d date>

Specify the date upon which actions should be taken. Any date that can
be understood by L<Date::Manip::Date> can be used, including strings such
as 'last Tuesday' or 'three days ago'.

If in doubt, use YYYY-MM-DD format.

Defaults to today. This switch is silently ignored if used with C<-y>.

=item B<-f config>

Specify the location of the configuration file.  Defaults to ~/.idonethisrc

=item B<-h>

Displays this help.

=item B<-l>

List items that you've done.  Combine this with the C<-c> switch
to list done items, and let you add new ones to the end.

=item B<-r>

List items in a I<range> of dates, in the form C<-r '2013-01-01, 2013-01-31'>.
Natural dates may also be used, as in C<-r '1 week ago, today'>.  This switch
is exclusive of the C<-d>, C<-y> and C<-c> switches.

With only a single argument, a second argument of 'now' is implied. This
allows shortcuts like C<idone -r'last week'> to show everything done
since last week.

This switch implies C<-l>.

=item B<-V>

Shows the current version and exits.

=item B<-y>

Perform all operations (adding and listing) using yesterday's date.
This switch overrides the C<-d> switch, if given.

=back

=head1 AUTHOR

Paul Fenwick <pjf@cpan.org>

=head1 COPYRIGHT AND LICENSE

This software is copyright (c) 2014 by Paul Fenwick.

This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.

=cut