package Allconsuming::Agent;

# Simple agent for allconsuming.net
# (c) DJ Adams 2003

use strict;
use LWP::UserAgent;
use HTTP::Cookies;
use Carp;
use vars qw/$VERSION $ACURL $ISBN %TTYPE/;

%TTYPE = (
  'CurrentlyReading' => 'being read',
  'FavoriteBooks'    => 'favorite books',
  'FavouriteBooks'   => 'favorite books',
);

# URL needs to have 'www.' as cookies are set for '.allconsuming.net'
$ACURL   = "http://www.allconsuming.net";
$VERSION = "0.1";
$ISBN    = "0596002025"; # what else? 

sub new {
  my ($class) = @_;
  my $ua = new LWP::UserAgent;
  $ua->agent("acagent/$VERSION");
  $ua->cookie_jar(new HTTP::Cookies);
  bless { 
    ua => $ua,
    loggedin => 0,
  } => $class;
}

sub logIn {
  my $self = shift;
  my ($user, $pass) = @_;

  my $request = new HTTP::Request(POST => "$ACURL/log-in.cgi");
  $request->content_type('application/x-www-form-urlencoded');
  $request->content("username=$user&password=$pass");
  
  my $response = $self->{ua}->request($request);

  # Assume login success if cookies have been set
  croak "logIn failed" unless $self->{ua}->cookie_jar->as_string;

  return $self->{loggedin} = 1;
}


sub logOut {
  my $self = shift;
  return $self->{loggedin} unless $self->{loggedin};
  my $request = new HTTP::Request(GET => "$ACURL/log-in.cgi?logout=1");
  my $response = $self->{ua}->request($request);
  $response->is_success and $self->{loggedin} = 0;
  return $self->{loggedin};
}


# Some forms require a hidden UID field which is unique per
# user (I think) and not directly available from looking at 
# the cookies. This routine grabs a book and looks for the
# value in the form. Need to be logged in for the form to exist
# on the page. 
# On further investigation, perhaps this UID isn't actually
# required. Hrm...
sub determineUid {
  my $self = shift;
  croak "Must logIn() before calling getUid()" unless $self->{loggedin};
  my $request = new HTTP::Request(GET => "$ACURL/item.cgi?isbn=$ISBN");
  my $response = $self->{ua}->request($request);
  my ($uid) = $response->content =~ m/name="uid"\s+value="(\d+)"/;
  croak "Can't find uid" unless $uid;
  return $self->{uid} = $uid;
}


sub uid {
  my $self = shift;
  $self->{uid};
}


sub _addToCollection {
  my $self = shift;
  my ($uid, $collection, $asin) = @_;

  # Automatically determine UID
  unless (defined $uid) { 
    $uid = $self->determineUid;
  }

  croak "No uid" unless defined $uid;
  croak "Don't know about $asin" unless $self->knowsBook($asin);

  $collection =~ s/\s/+/g;

  my $request = new HTTP::Request(POST => "$ACURL/control.cgi");
  $request->content_type('application/x-www-form-urlencoded');
  $request->content("action=save-thread-item&tid=&uid=$uid&asin=$asin&ttype=$collection");
  
  my $response = $self->{ua}->request($request);

  # Check for success by looking for "+ add comment" in returned page
  return $response->is_success && $response->content =~ m/\+ add comment/;
}


# Should perhaps do these with autoloader
sub addToCurrentlyReading {
  my $self = shift;
  my ($asin) = @_;
  return $self->_addToCollection($self->{uid}, $TTYPE{'CurrentlyReading'}, $asin);
}


sub addToFavouriteBooks {
  my $self = shift;
  my ($asin) = @_;
  return $self->_addToCollection($self->{uid}, $TTYPE{'FavouriteBooks'}, $asin);
}


# There's no accounting for the decline of the English language ;-)
sub addToFavoriteBooks {
  my $self = shift;
  return $self->addToFavouriteBooks(@_);
}
  


# Check that allconsuming knows about the book - it doesn't 
# know about all ISBNs (e.g. some books are available on amazon.co.uk
# but not on amazon.com). Just look for a book title in the <title>.
sub knowsBook {
  my $self = shift;
  my ($asin) = @_;
  my $request = new HTTP::Request(GET => "$ACURL/item.cgi?isbn=$asin");
  my $response = $self->{ua}->request($request);
  return $response->is_success
    && $response->content =~ m/<title>All Consuming: Book Info: .+?<\/title>/;
}


sub DESTROY {
  my $self = shift;
  $self->logOut;
}


1;
