The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
use strict;
use warnings;

package WebService::TVDB;
{
  $WebService::TVDB::VERSION = '1.123160';
}

# ABSTRACT: Interface to http://thetvdb.com/

use WebService::TVDB::Languages qw($languages);
use WebService::TVDB::Series;
use WebService::TVDB::Mirror;
use WebService::TVDB::Util qw(get_api_key_from_file);

use Carp qw(carp);
use LWP::Simple ();
use URI::Escape qw(uri_escape);
use XML::Simple qw(:strict);

use constant SEARCH_URL =>
  'http://www.thetvdb.com/api/GetSeries.php?seriesname=%s';

use constant API_KEY_FILE => '/.tvdb';

use Object::Tiny qw(
  api_key
  language
  max_retries
);

sub new {
    my $class = shift;
    my $self  = $class->SUPER::new(@_);

    unless ( $self->api_key ) {
        require File::HomeDir;
        $self->{api_key} =
          get_api_key_from_file( File::HomeDir->my_home . API_KEY_FILE );
        die 'Can\'t find API key' unless $self->api_key;
    }

    unless ( $self->language ) {
        $self->{language} = 'English';
    }

    unless ( $self->max_retries ) {
        $self->{max_retries} = 10;
    }

    return $self;
}

sub search {
    my ( $self, $term ) = @_;

    unless ($term) {
        die 'search term is required';
    }
    unless ( $self->{mirrors} ) {
        $self->_load_mirrors();
    }

    my $url = sprintf( SEARCH_URL, uri_escape($term) );
    my $agent = $LWP::Simple::ua->agent;
    $LWP::Simple::ua->agent("WebService::TVDB/$WebService::TVDB::VERSION");
    my $xml     = LWP::Simple::get($url);
    my $retries = 0;
    until ( defined $xml || $retries == $self->max_retries ) {
        carp "failed to get URL $url - retrying";

        # TODO configurable wait time
        sleep 1;
        $xml = LWP::Simple::get($url);

        $retries++;
    }
    $LWP::Simple::ua->agent($agent);
    unless ($xml) {
        die "failed to get URL $url after $retries retries. Aborting.";
    }
    $self->{series} = _parse_series(
        XML::Simple::XMLin(
            $xml,
            ForceArray    => ['Series'],
            KeyAttr       => 'Series',
            SuppressEmpty => 1
        ),
        $self->api_key,
        $languages->{ $self->language },
        $self->{mirrors},
        $self->max_retries
    );

    return $self->{series};
}

# parse the series xml and return an array of WebService::TVDB::Series
sub _parse_series {
    my ( $xml, $api_key, $api_language, $api_mirrors, $max_retries ) = @_;

    # loop over results and create new series objects
    my @series;
    for ( @{ $xml->{Series} } ) {
        push @series,
          WebService::TVDB::Series->new(
            %$_,
            _api_key      => $api_key,
            _api_language => $api_language,
            _api_mirrors  => $api_mirrors,
            _max_retries  => $max_retries
          );
    }

    return \@series;
}

# loads mirros when needed
sub _load_mirrors {
    my ($self) = @_;

    my $mirrors = WebService::TVDB::Mirror->new();
    $mirrors->fetch_mirror_list( $self->api_key );
    $self->{mirrors} = $mirrors;
}

1;



=pod

=head1 NAME

WebService::TVDB - Interface to http://thetvdb.com/

=head1 VERSION

version 1.123160

=head1 SYNOPSIS

  my $tvdb = WebService::TVDB->new(api_key => 'ABC123', language => 'English', max_retries => 10);

  my $series_list = $tvdb->search('men behaving badly');

  my $series = @{$series_list}[0];
  # $series is a WebService::TVDB::Series
  say $series->SeriesName;
  say $series->overview;

  # fetches full series data
  $series->fetch();

  say $series->Rating;
  say $series->Status;

  for my $episode (@{ $series->episodes }){
    # $episode is a WebService::TVDB::Episode
    say $episode->Overview;
    say $episode->FirstAired;
  }

  for my $actor (@{ $series->actors }){
    # $actor is a WebService::TVDB::Actor
    say $actor->Name;
    say $actor->Role;
  }

  for my $banner (@{ $series->banners }){
    # $banner is a WebService::TVDB::Banner
    say $banner->Rating;
    say $banner->url;
  }

=head1 DESCRIPTION

WebService::TVDB is an interface to L<http://thetvdb.com/>.

=head1 METHODS

=head2 new

Creates a new WebService::TVDB object. Takes the following parameters:

=over 4

=item api_key

This is your API key. If not passed in here, we will look in ~/.tvdb. Otherwise we will die.

=item language

The language you want tour results in. L<See WebService::TVDB::Languages> for a list of languages. Defaults to English.

=item max_retries

The amount of times we will try to get the series if our call to the URL failes. Defaults to 10.

=back

=head2 search( $term )

Searches the TVDB and returns a list of L<WebService::TVDB::Series> as the result.

=head1 API KEY

To use this module, you will need an API key from http://thetvdb.com/?tab=apiregister.

You can pass this key into the constructor, or save it to ~/.tvdb.

=head1 AUTHOR

Andrew Jones <andrew@arjones.co.uk>

=head1 COPYRIGHT AND LICENSE

This software is copyright (c) 2012 by Andrew Jones.

This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.

=cut


__END__