#!/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

  # List all of your notes.
  $ racknotes list

  # Delete note number 3.
  $ racknotes delete --num=3

  # Same thing.
  $ racknotes delete -n 3

  # Some commands expect to read text from stdin. You can type some text
  # and then hit <ctrl-d> when you are done.
  $ racknotes add --subject=foo
  some text
  <ctrl-d>

  # Or you could use piping or redirection.
  $ echo allo | racknotes add -s 'adding note contents via piping'
  $ racknotes add -s 'adding note contents via redirection' < some_file.txt

=head1 COMMANDS

=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 all the notes.
Each note is numbered so that other commands can refer to them.

=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
