package CPAN::Testers::Reports::Query::JSON;
use Moose;

use version;
use LWP::Simple;
use CPAN::Testers::WWW::Reports::Parser;
use CPAN::Testers::Reports::Query::JSON::Set;

our $VERSION = '0.01';

has distribution    => ( isa => 'Str', is => 'ro', );
has version         => ( isa => 'Str', is => 'rw' );
has current_version => ( isa => 'Str', is => 'ro', lazy_build => 1 );
has versions => ( isa => 'ArrayRef[Str]', is => 'ro', lazy_build => 1 );
has report => (
    is         => 'rw',
    lazy_build => 1,
    isa        => 'ArrayRef[CPAN::Testers::WWW::Reports::Report]',
);

sub _build_current_version {
    my $self   = shift;
    my $report = $self->report();

    my $max_version = version->new('0');
    my $version     = $self->versions()->[0];
    return $self->version($version);
}

sub _build_report {
    my $self = shift;

    my $data = $self->_raw_json();

    my $obj = CPAN::Testers::WWW::Reports::Parser->new(
        format  => 'JSON',
        data    => $data,
        objects => 1,
    );

    my @results;
    while ( my $data = $obj->report() ) {
        next unless $data->csspatch() eq 'unp';
        push( @results, $data );
    }

    return \@results;
}

sub _build_versions {
    my $self   = shift;
    my $report = $self->report();

    my %versions;
    foreach my $data ( @{$report} ) {
        my $this_version = version->new( $data->version() );
        $versions{ $this_version->stringify } = 1;
    }
    my @vers = reverse sort keys %versions;
    return \@vers;
}

=head1 NAME
 
  CPAN::Testers::Reports::Query::JSON - Find out about a distributions cpantesters results
  
=head1 SYNOPSIS

    my $dist_query = CPAN::Testers::Reports::Query::JSON->new(
        {   distribution => 'Data::Pageset',
            version => '1.01',    # optional, will default to latest version
        }
    );

    print "Processing version: " . $dist_query->version() . "\n";
    print "Other versions are: " . join(" ", @{$dist_query->versions()}) . "\n";

    my $all = $dist_query->all();
    printf "There were %s tests, %s passed, %s failed - e.g. %s percent",
        $all->total_tests(),
        $all->number_passed(),
        $all->number_failed(),
        $all->percent_passed();

    my $win32_only = $dist_query->win32_only();
    printf "There were %s windows tests, %s passed, %s failed - e.g. %s percent",
        $win32_only->total_tests(),
        $win32_only->number_passed(),
        $win32_only->number_failed(),
        $win32_only->percent_passed();

    my $non_win32 = $dist_query->non_win32();
    printf "There were %s windows tests, %s passed, %s failed - e.g. %s percent",
        $non_win32->total_tests(),
        $non_win32->number_passed(),
        $non_win32->number_failed(),
        $non_win32->percent_passed();
        
    # Get results for a specific OS
    my $specific_os = $dist_query->for_os('linux');
  
=head1 DESCRIPTION

This module queries the cpantesters website (via the JSON interface) and 
gets the test results back, it then parses these to answer a few simple questions.

This module only reports on versions of Perl which are unpatched.

=head2 all

Get stats on all tests

=head2 win32_only

Only windows 32 tests

=head2 non_win32

Non windows.

=head2 for_os

  my $report = $dist_query->for_os('linux');

=head2 current_version

  my $current_version = $query->current_version();

Sets $query->version() and returns the largest version

=head1 AUTHOR
 
Leo Lapworth, LLAP@cuckoo.org
 
=head1 BUGS
 
None that I'm aware of - export may not encode correctly.
 
=head1 Repository (git)

http://github.com/ranguard/cpan-testers-reports-query-json,
git://github.com/ranguard/cpan-testers-reports-query-json.git
 
=head1 COPYRIGHT
 
Copyright (c) Leo Lapworth. All rights reserved.
This program is free software; you can redistribute
it and/or modify it under the same terms as Perl itself.

=cut


sub all {
    my $self = shift;

    return $self->_create_set( { name => 'all', } );
}

sub win32_only {
    my $self = shift;

    return $self->_create_set(
        {   os_include_only => {
                'MSWin32' => 1,
                'cygwin'  => 1,
            },
            name => 'win32_only',
        }
    );

}

sub non_win32 {
    my $self = shift;

    return $self->_create_set(
        {   os_exclude => {
                'MSWin32' => 1,
                'cygwin'  => 1,
            },
            name => 'non_win32',
        }
    );

}

sub for_os {
    my ( $self, $os ) = @_;
    return $self->_create_set(
        {   os_include_only => { $os => 1, },
            name            => $os,
        }
    );
}

sub _create_set {
    my ( $self, $conf ) = @_;

    $conf ||= {};

    my @os_data;

    foreach my $data ( @{ $self->_get_data_for_version() } ) {

        # Only want non-patched Perl at the moment
        if ( $conf->{os_exclude} ) {
            next if $conf->{os_exclude}->{ $data->osname() };
        }
        if ( $conf->{os_include_only} ) {
            next unless $conf->{os_include_only}->{ $data->osname() };
        }
        push( @os_data, $data );
    }

    return CPAN::Testers::Reports::Query::JSON::Set->new(
        { data => \@os_data, name => $conf->{name} } );
}


sub _get_data_for_version {
    my $self    = shift;
    my $version = $self->version || $self->current_version;
    my $report  = $self->report();

    my @data = grep { $_->version() eq $version } @{$report};
    return \@data;
}

sub _json_url {
    my $self = shift;
    my $dist = $self->distribution();
    $dist =~ s/::/-/;
    my ($letter) = ( $dist =~ /(.{1})/ );

    return "http://www.cpantesters.org/distro/$letter/$dist.json";
}

sub _raw_json {
    my $self = shift;

    # Fetch from website - could have caching here
    return get( $self->_json_url() );
}

1;
