#!/usr/bin/env perl

use strict;
use warnings;

use 5.010;

use Book;
use Net::Amazon;
use DateTime;

# List of valid sub-commands with subroutines to implement them
my %command = (
  add => \&add,
  list => \&list,
  start => \&start,
  end => \&end,
);

# Default sub-command is 'list'
my $what = shift || 'list';

if (exists $command{$what}) {
  $command{$what}->(@ARGV);
} else {
  die "Invalid command: $what\n";
}

# Connect to the database and return a schema object
sub get_schema {
  return Book->connect('dbi:mysql:database=books', 'books', 'README')
  or die "Cannot connect to database\n";
}

# List all books in the database
sub list {
  my $schema = get_schema();
  my $books_rs = $schema->resultset('Book');
  
  say "Reading:\n";
  
  # Books we're reading have a start date but no end date
  foreach ($books_rs->search({
    started => { '!=', undef },
    ended => undef,
  })) {
    say ' * ', $_->title, ' (', $_->author->name, ')';
  }
  
  # Books we're going to read have no start date
  say "\nTo Read:\n";
  
  foreach ($books_rs->search({
    started => undef,
  })) {
    say ' * ', $_->title, ' (', $_->author->name, ')';
  }
  
  say "\nRead:\n";
  
  # Books we've read have an end date
  foreach ($books_rs->search({
    ended => { '!=', undef },
  })) {
    say ' * ', $_->title, ' (', $_->author->name, ')';
  }
}

# Add a book to the database
sub add {
  my $isbn = shift || die "No ISBN to add\n";

  my $schema = get_schema();
  my $books_rs = $schema->resultset('Book');

  # Don't add the same book twice
  if ($books_rs->search({ isbn => $isbn })->count) {
    warn "ISBN $isbn already exists in db\n";
    return;    
  }

  my $amz = Net::Amazon->new(
    token => $ENV{AMAZON_KEY},
    secret_key => $ENV{AMAZON_SECRET},
    locale => 'uk',
  ) or die "Cannot connect to Amazon\n";

  # Search for the book at Amazon
  my $resp = $amz->search(asin => $isbn);
  
  unless ($resp->is_success) {
    say 'Error: ', $resp->message;
    return;
  }
  
  my $book = $resp->properties;
  my $title = $book->ProductName;
  my $author_name = ($book->authors)[0];
  my $imgurl = $book->ImageUrlMedium;

  # Find or create the author
  my $author = $schema->resultset('Author')->find_or_create({
    name => $author_name,
  });

  # Add the book to the author
  $author->add_to_books({
    isbn => $isbn,
    title => $title,
    image_url => $imgurl,
  });
  
  say "Added $title ($author_name)";
  
  return;
}

# Start reading a book
sub start {
  my $schema = get_schema();
  my $books_rs = $schema->resultset('Book');

  my $isbn = shift || die "No ISBN to start\n";

  # Ensure the book is in the database
  my ($book) = $books_rs->search({ isbn => $isbn });
  
  unless ($book) {
    # N.B. Could call 'add' at this point
    die "ISBN $isbn not found in db\n";
  }
  
  # Update 'started' column to contain current date/time
  $book->started(DateTime->now);
  $book->update;
  
  say 'Started to read ', $book->title;
}

# Finish reading a book
sub end {
  my $schema = get_schema();
  my $books_rs = $schema->resultset('Book');

  my $isbn = shift || die "No ISBN to end\n";

  # Ensure the book is in the database
  my ($book) = $books_rs->search({ isbn => $isbn });
  
  unless ($book) {
    # N.B. Could call 'add' and 'start' at this point
    die "ISBN $isbn not found in db\n";
  }
  
  # Update 'ended' column to contain current date/time
  $book->ended(DateTime->now);
  $book->update;
  
  say 'Finished reading ', $book->title;
}
