#!/usr/local/bin/perl -w
###########################################
# en-ebooks - Tags for Ebooks in Evernote
# Mike Schilli, 2012 (m@perlmeister.com)
###########################################
use strict;
use Net::Evernote::Simple;
use Log::Log4perl qw(:easy);
use File::Basename;
use File::Temp qw( tempfile );
use Digest::MD5 qw( md5_hex );
use Sysadm::Install qw( :all );

Log::Log4perl->easy_init( $INFO );

my( $HOME ) = glob "~";

my $EN_FOLDER = "50-Ebooks";
my $BOOKS_DIR = "$HOME/books";

my $enote   = Net::Evernote::Simple->new();
my $enstore = $enote->note_store();

my $en_folder_id = en_folder_id( 
  $enote, $enstore );

my %en_books = map { $_ => 1 }
   en_folder_notes( $enote, $enstore, 
                    $en_folder_id );

for my $pdf ( <$BOOKS_DIR/*.pdf> ) {
  my $file = basename $pdf;
  (my $title = $file ) =~ s/\.pdf$//;

  if( exists $en_books{ $title } ) {
    DEBUG "$title already in Evernote";
    next;
  }

  en_add( $enote, $enstore, $title, 
        title_pic( $pdf ), $en_folder_id );
}

###########################################
sub en_add {
###########################################
  my( $enote, $enstore, $title, 
      $title_pic, $en_folder_id ) = @_;

  my $PRFX = "Net::Evernote::Simple::" .
    "EDAMTypes::";
  my $data_class     = $PRFX . "Data";
  my $resource_class = $PRFX . "Resource";
  my $note_class     = $PRFX . "Note";

  eval "require $data_class";
  eval "require $resource_class";
  eval "require $note_class";

  INFO "Adding $title to Evernote";

  my $data = $data_class->new();

  my $content = slurp $title_pic;
  $data->body( $content );
  my $hash = md5_hex( $content );
  $data->bodyHash( $hash );
  $data->size( length $content );

  my $r = $resource_class->new();
  $r->data( $data );
  $r->mime( "image/jpeg" );
  $r->noteGuid( "" );

  my $note = $note_class->new();
  $note->title( $title );
  $note->resources( [$r] );
  $note->notebookGuid( $en_folder_id );

  my $enml = <<EOT;
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE en-note SYSTEM 
"http://xml.evernote.com/pub/enml2.dtd">
<en-note>
   <en-media type="image/jpeg" 
             hash="$hash"/>
</en-note>
EOT

  $note->content( $enml );

  $enstore->createNote(
      $enote->dev_token(), $note );
}

###########################################
sub title_pic {
###########################################
  my( $in_pdf ) = @_;

  my ($fh1, $pdf_file) = tempfile( 
      SUFFIX => '.pdf', UNLINK => 1 );

  my ($fh2, $jpg_file) = tempfile( 
      SUFFIX => '.jpg', UNLINK => 1 );

  tap { raise_error => 1 }, 
    "pdftk", "A=$in_pdf", "cat", "A1",
    "output", $pdf_file;

  tap { raise_error => 1 }, 
    "convert", "-resize", "100x", 
    $pdf_file, $jpg_file;

  return $jpg_file;
}

###########################################
sub en_folder_id {
###########################################
  my( $enote, $store ) = @_;

  my $notebooks = $enstore->listNotebooks( 
    $enote->dev_token() );

  for my $notebook (@$notebooks) {
    if ( $notebook->name() eq $EN_FOLDER ){
      return $notebook->guid();
    }
  }

  die "$EN_FOLDER not found";
}

###########################################
sub en_folder_notes {
###########################################
  my( $enote, $store, $en_folder_id ) = @_;

  my $filter_class = "Net::Evernote::" .
   "Simple::EDAMNoteStore::NoteFilter";
  eval "require $filter_class";
  
  my $filter = $filter_class->new();
  $filter->notebookGuid( $en_folder_id );

  my @titles = ();

  my $max_per_call = 50;

  for( my $offset = 0; ;
       $offset += $max_per_call ) {

    my $note_list = $store->findNotes( 
        $enote->dev_token(),
        $filter, $offset, $max_per_call );

    my $notes_found = 0;

    for my $note ( 
        @{ $note_list->{ notes } } ) {
      $notes_found++;
    
      push @titles, $note->title();
    }
    
    last if $notes_found != $max_per_call;
  }

  return @titles;
}
