#!/usr/bin/env perl
use strict;
use warnings;

our $VERSION = '20130522.0';

use Getopt::Long;
use LWP::UserAgent;
use URI::Escape qw/uri_escape/;
use JSON        qw/decode_json/;
use File::Temp  qw//;

my %opt;
GetOptions(
    \%opt,
    'distribution|d',
    'help|h',
    'version',
);

if ($opt{help}) {
    print usage();
} elsif ($opt{version}) {
    print "cpanchanges/$VERSION\n";
} else {
    my $name = shift or die usage();
    my $changes = changes($name);

    if ($ENV{PAGER} and -t *STDOUT) {
        my $tmp = File::Temp->new;
        print { $tmp } $changes;
        system($ENV{PAGER}, $tmp->filename) == 0
            or die "Couldn't run \$PAGER ($ENV{PAGER}): $!\n";
    } else {
        print $changes;
    }
}
exit;

sub usage {
    <<"."
usage: cpanchanges Moose
       cpanchanges LWP::UserAgent
       cpanchanges --distribution libwww-perl

  --distribution, -d    Lookup by distribution, not module, name
  --help                Show this help
  --version             Show version

.
}

sub changes {
    my $name = shift;
    my @release;

    if ($opt{distribution}) {
        # The API will lookup the latest release from the distribution name for us.
        @release = $name;
    } else {
        my $module = request( module => $name )
            or die "Unable to find module '$name'\n";

        @release = @$module{"author", "release"};
    }

    my $changes = request( changes => @release )
        or die "Unable to find changes for ", join("/", @release), "\n";

    return "# Changes for $changes->{author}/$changes->{release}\n\n"
          . $changes->{content} . "\n";
}

sub request {
    my $url = "http://api.metacpan.org/v0/"
            . join "/", map uri_escape($_), @_;

    my $ua = LWP::UserAgent->new(
        agent => "cpanchanges/$VERSION",
    );
    my $response = $ua->get($url);

    if (!$response->is_success) {
        warn "Request '$url' failed: ", $response->status_line, "\n"
            unless $response->code == 404;
        return;
    }

    my $result = eval { decode_json($response->decoded_content) };
    if ($@ or not $result) {
        warn "Error decoding response: $@\n";
        return;
    }
    return $result;
}
