#!/usr/bin/perl
# vim: set ts=4 sw=4 tw=78 et si ft=perl:
#
# leanpub
#
use 5.010;
use strict;
use warnings;

use Cwd;
use Getopt::Long;
use Pod::Usage;
use WebService::Leanpub;

my $defconffile = ".leanpub.conf";

my %opt = (
    really => 0,
);

Getopt::Long::Configure('require_order');
GetOptions( \%opt,
    'api_key=s', 'slug=s',
    'really', 'version',
    'help|?', 'manual')
    or pod2usage(2);

pod2usage(-exitval => 0, -verbose => 1, -input => \*DATA) if ($opt{help});
pod2usage(-exitval => 0, -verbose => 2, -input => \*DATA) if ($opt{manual});

if ($opt{version}) {
    print "WebService::Leanpub, version $WebService::Leanpub::VERSION\n";
    exit 0;
}

read_config(\%opt);

my $cmd = shift;

pod2usage(0) unless ($cmd);

my $wl   = WebService::Leanpub->new($opt{api_key},$opt{slug});

if ($cmd =~ /^summary/i) {
    my $js = $wl->summary();
    print $wl->pretty_json($js) if ($js);
}
elsif ($cmd =~ /^individual/i) {
    my %lopt = ( page => 1, );
    GetOptions( \%lopt, 'page=i' );
    my $ip = $wl->get_individual_purchases( { page => $lopt{page} } );
    print $wl->pretty_json($ip) if ($ip);
}
elsif ($cmd =~ /^job_status/i) {
    my $js = $wl->get_job_status();
    print $wl->pretty_json($js) if ($js);
}
elsif ($cmd =~ /^(partial|subset)/i) {
    my $pv = $wl->subset();
    print $pv if ($pv);
}
elsif ($cmd =~ /^preview/i) {
    my $pv = $wl->preview();
    print $pv if ($pv);
}
elsif ($cmd =~ /^single/i) {
    my $fname = shift;

    pod2usage('need a filename with command single')    unless ($fname);
    open(my $input, '<', $fname) or die "Can't open $fname: $!";

    local $/;
    undef $/;
    my $content = <$input>;
    close $input;

    my $pv = $wl->single({ content => $content });
    print $pv if ($pv);
}
elsif ($cmd =~ /^publish/i) {
    if ($opt{really}) {
        my %lopt = ();
        GetOptions( \%lopt, 'email_readers|email', 'release_notes=s' );
        my $pv = $wl->publish(\%lopt);
        print $pv if ($pv);
    }
    else {
        pod2usage(0);
    }
}
elsif ($cmd =~ /^sales/i) {
    my $sd = $wl->get_sales_data();
    print $wl->pretty_json($sd) if ($sd);
}
elsif ($cmd =~ /^coupons/i) {
    my $cl = $wl->get_coupon_list();
    print $wl->pretty_json($cl) if ($cl);
}
elsif ($cmd =~ /^create_coupon/i) {
    my %lopt = ();
    GetOptions( \%lopt,
                'coupon_code=s', 'discounted_price=s', 'start_date=s',
                'end_date=s', 'has_uses_limit', 'max_uses=i',
                'note=s', 'suspended',
              );
    my $cc = $wl->create_coupon(\%lopt);
    if ($cc) {
        print $cc;
    }
    else {
        die "problem creating coupon";
    }
}
elsif ($cmd =~ /^update_coupon/i) {
    my %lopt = ();
    GetOptions( \%lopt,
                'coupon_code=s', 'discounted_price=s', 'start_date=s',
                'end_date=s', 'has_uses_limit!', 'max_uses=i',
                'note=s', 'suspended!',
              );
    my $uc = $wl->update_coupon(\%lopt);
    if ($uc) {
        print $uc;
    }
    else {
        die "problem creating coupon";
    }
}

exit 0;

#--- only functions following ---

sub read_config {
    my ($opt) = @_;
    my $config;
    my $here = cwd();

    my $read = sub {
        my ($in) = @_;
        my $config = {};
        while (<$in>) {
            next if (/^\s*#/);
            if (/^\s*(\S+)\s*=\s*(\S.*)$/) {
                $config->{$1} = $2;
            }
        }
        return $config;
    };
    while ($here) {
        if ( -r $here . '/' . $defconffile
            && open my $in, '<', $here . '/' . $defconffile) {
            $config = $read->($in);
            close $in;
            foreach my $k (keys %$config) {
                unless ($opt->{$k}) {
                    $opt->{$k} = $config->{$k};
                }
            }
        }
        $here =~ s|/[^/]+$||;
    }

} # read_config()

__END__

=head1 NAME

leanpub - access the Leanpub web API

=head1 VERSION

This document refers to leanpub version v0.3.1

=head1 USAGE

 leanpub [options] command [command options]

=head1 OPTIONS

=over 8

=item B<< -api_key=key >>

Provide the Leanpub API key to be used for all actions.

=item B<< -help >>

Print a brief help message and exit.

=item B<< -manual >>

Print the manual page and exit.

=item B<< -really >>

State that you really intend to do the command (e.g. publish).

=item B<< -slug=your_book >>

Provide the book's slug.

=item B<< -version >>

Print $WebService::Leanpub::VERSION and exit.

=back

=head1 COMMANDS

=over

=item summary

Get information about the book.

=item job_status

Retrieve the status of the last job.

=item partial_preview

Start a partial preview of your book using Subset.txt.

=item subset

Start a partial preview of your book using Subset.txt.

=item preview

Start a preview of your book.

=item single filename

Create a preview from a single file.

=item publish [ options ]

Publish your book.

You have to use option B<< -really >> with this command.

This command takes the following command options:

=over

=item -email_readers

Email readers, notifying them that the book has been updated.

=item -release_notes=notes

The release notes to be included in the email to the readers.

=back

=item sales_data

Retrieve a summary of sales data.

=item individual_purchases [ -page=p ]

Retrieve data about individual purchases.

This command takes the option C<< -page >> to set the page of the individual
purchases report to be retrieved.

=item coupons options

Get a list of coupons available for the book.

=item create_coupon

Create a new coupon for your book.

This function takes the following command options:

=over

=item -coupon_code=code

Required.
The coupon code for this coupon. This must be unique for the book.

=item -discounted_price=price

Required.
The amount the reader will pay when using the coupon.

=item -start_date=YYYY-MM-DD

Required.
The date the coupon is valid from.

=item -end_date=YYYY-MM-DD

The date the coupon is valid until.

=item -has_uses_limit

Whether or not the coupon has a uses limit.

=item -max_uses=uses

The max number of uses available for a coupon. An integer.

=item -note=note_for_me

A description of the coupon. This is just used to remind you of what it was
for.

=item -suspended

Whether or not the coupon is suspended.

=back

=item update_coupon options

Update a coupon.

This command takes the same argumentes as create_coupon but only the option
--coupon_code is required, all others are optional.

=back

=head1 DESCRIPTION

This program interacts with the Leanpub API.
You can find details about this API at L<< https://leanpub.com/help/api >>.

The slug is the part of the URL for your book coming
after C<< https://leanpub.com/ >>. For instance if your book is found at
C<< https://leanpub.com/your_book >>, then the slug for your book is
I<your_book>.

=head1 FILES

=head2 CONFIGURATION

This program searches in the current working directory and all directories
above for a text file named I<.leanpub.conf>. It reads these files
and adds configuration directives which are not set so far to its
configuration.

The format of the file is rather simple. It is just a key and a value separated
by an equal sign and optional whitespace. Valid keys are the names of the
global options without any minus or plus sign. For instance I have a file
containing something like:

 # configuration for leanpub
 #
 api_key = my_api_key_from_leanpub
 slug    = using-the-leanpub-api-with-perl

in the directory I am developing this module in. So I don't have to provide
the options C<< -api_key >> and C<< -slug >> to test this script. When I use
the script for more than one book, I place a file called I<.leanpub.conf>
containing the API key further up and have only the SLUG in the files located
in the book directories. To use a different API key I would write it in the
file in the book directory so that the one further up would not be used.

=head1 AUTHOR

Mathias Weidner

