#!/usr/bin/env perl
use strict;
use warnings;
use lib qw(lib);
use App::Rad;
use Getopt::Long qw(GetOptions);
use Net::Rackspace::Notes qw(notes);
use Pod::Usage qw(pod2usage);
use Term::ReadPassword qw(read_password);

sub setup {
    my $c = shift;
    $c->register_commands({
        add    => 'add a new note, content is read from stdin',
        append => 'append the content of stdin to the note',
        delete => 'delete the note',
        list   => 'lists id and subject of all notes',
        show   => 'show the contents of the note',
    });
}

sub pre_process {
    my $c = shift;
    return if ! grep { $_ eq $c->cmd } $c->commands or $c->cmd eq 'help';
    $c->getopt('num|n=i', 'subject|s=s') or exit 1;
    my ($email, $password) = get_login_info($c);
    $c->stash->{racknotes} = Net::Rackspace::Notes->new(
        email    => $email,
        password => $password,
    );
}

App::Rad->run();

#-------------------------------------------------------------------------------
# Function definitions ---------------------------------------------------------

sub add {
    my $c = shift;
    my $subject = $c->options->{subject};
    my $body = do { local $/; <STDIN> };
    my $racknotes = $c->stash->{racknotes};
    my $response = $racknotes->add_note($subject, $body);
    return "status: " . $response->status_line;
    #print $response->content . "\n" unless $response->is_success;
}

sub append {
    my $c = shift;
    my $num = get_required_opt($c, 'num');
    my $racknotes = $c->stash->{racknotes};
    my $body = do { local $/; <STDIN> };
    my $note = $racknotes->notes->[$num];
    my $content = $note->{content} . $body;
    my $response = $racknotes->add_note($note->{subject}, $content);
    $response = $racknotes->delete_note($num);
    return "status: " . $response->status_line;
}

sub delete {
    my $c = shift;
    my $num = get_required_opt($c, 'num');
    my $racknotes = $c->stash->{racknotes};
    my $response = $racknotes->delete_note($num);
    return "status: " . $response->status_line;
    #print $response->content . "\n" unless $response->is_success;
}

sub show {
    my $c = shift;
    my $num = get_required_opt($c, 'num');
    my $racknotes = $c->stash->{racknotes};
    my $note = $racknotes->notes->[$num];
    return "Subject: $note->{subject}\n\nBody:\n$note->{content}";
}

sub get_required_opt {
    my ($c, $opt) = @_;
    my $value = $c->options->{$opt};
    die "Option --$opt is required for command " . $c->cmd . "\n"
        if not defined $value;
    return $value;
}

sub list {
    my $c = shift;
    my $count = 0;
    my $racknotes = $c->stash->{racknotes};
    return join "\n",
        map { sprintf "%2d: %s", $count++, $_->{subject}  } $racknotes->notes;
}

sub get_login_info {
    my $c = shift;
    my ($email, $password);
    my $config_path = "$ENV{HOME}/.racknotes";
    if (-r $config_path) {
        $c->load_config($config_path);
        ($email, $password) = @{$c->config}{qw(email password)};
        $password = read_password('password: ')
            if not defined($password) or $password eq '';
    } else {
        print "If you don't want to enter your account info each time, you\n",
            "can create a config file at $config_path with 2 entries:\n",
            "  email = bob\@foo.com\n",
            "  password = foo\n\n",
            "Your config file may also just contain the email entry without\n",
            "the password entry. You will then just be prompted for your\n",
            "password when you run racknotes.\n\n";

        print "email: ";
        chomp($email = <STDIN>);
        die "$email is not a valid email address\n"
            unless $email =~ /.+@.+\..+/;

        $password = read_password('password: ');
    }
    return ($email, $password);
}


__END__

=head1 NAME

racknotes - A command line interface to Rackspace Email Notes.

=head1 SYNOPSIS
  Usage: racknotes command [arguments]
  
  Available Commands:
      add         add a new note, content is read from stdin
      append      append the content of stdin to the note
      delete      delete the note
      help        show syntax and available commands
      list        lists id and subject of all notes
      show        show the contents of the note

=head1 OPTIONS

=over 4

=item B<-h|--help>

Print a brief help message.

=item B<add -s|--subject=SUBJECT>

Add a new note with the given subject.
The contents of the note will be read from stdin.

=item B<append -n|--num=NUM>

Append the content of stdin to the note.

=item B<delete -n|--num=NUM>

Delete the note.

=item B<list>

List the id and subject of all the notes.

=item B<show -n|--num=NUM>

Show the contents of the note.

=back

=head1 DESCRIPTION

This program is a command line tool to interface with Rackspace Email Notes.

=cut
