#!/usr/bin/perl -w
###################################################

use AmazonMusicImage;
use ReadTag;
use File::Find;
use LWP::UserAgent;
use Image::Info qw(image_info dim);
use Getopt::Std;
use File::Spec;

use strict;

my %options;
my %seen;

if (!getopts('m:di:e:g:p:', \%options)|| !%options ) {
  help();
}
my $top = $options{m} || help();
my $debug = $options{d};
my $file_name = $options{i} || "cover.jpg";
my $genre_regex = $options{g};
if ($file_name !~ /\.jpg$/) {
  print "\nFile name must end with .jpg\n";
  exit;
}
my $exclude = $options{e} || "tmp|lost+found|Misc. Live";
$|++;

my $slimpath = $options{p} || help();
if (! (-e $slimpath && -r $slimpath && -e File::Spec->catfile("$slimpath","CPAN")) ) {
	die "You must provide the full path to your Slimserver installation\n";
}

my @path = ("$slimpath",File::Spec->catdir("$slimpath","CPAN"),
       File::Spec->catdir($slimpath,'CPAN','arch',(join ".", map {ord} split //, $^V), $Config::Config{'archname'}),
       File::Spec->catdir($slimpath,'CPAN','arch',(join ".", map {ord} split //, $^V), $Config::Config{'archname'}, 'auto'),
       File::Spec->catdir($slimpath,'CPAN','arch',(join ".", map {ord} (split //, $^V)[0,1]), $Config::Config{'archname'}),
       File::Spec->catdir($slimpath,'CPAN','arch',(join ".", map {ord} (split //, $^V)[0,1]), $Config::Config{'archname'}, 'auto'),
       File::Spec->catdir($slimpath,'CPAN','arch',$Config::Config{archname})
);


push(@INC,@path);
require Slim::Formats::Movie;
require Slim::Formats::AIFF;
require Slim::Formats::FLAC;
require Slim::Formats::MP3;
require Slim::Formats::Ogg;
require Slim::Formats::Wav;
require Slim::Formats::WMA;
require Slim::Formats::Musepack;
require Slim::Formats::Shorten;

# Calls the main workflow --
find(\&wanted, $top);



##### Sub here #####

sub help {
  print qq(
Usage: $0 -p "/path/to/Slimserver" -m "/path/to/music/dir" [options]
Options are:
\t-p path\t\tFull path to the top level of your Slimserver install
\t\t\tTHIS OPTION IS REQUIRIED
\t-m path\t\tFull path to the top of your music hierarchy. 
\t\t\tTHIS OPTION IS REQUIRIED
\t-i image_name\tFile name to save album cover as. Default: cover.jpg
\t-d\t\tTurn on verbose debugging
\t-e\t\tDirectories to exclude seperated by a "|".
\t\t\tUse just the dir name, not the full path
\t\t\t(i.e. "temporary directory|dir to skip" etc.)
\t-g\t\tGenre to exclude from process. Ex: "-g classical" would 
\t\t\tskip all tracks with "Classical" (case insensitive) 
\t\t\tin the GENRE field.
	  );
  print "\n";
  exit;
}

sub wanted {
  my $image;
  my $dir = $File::Find::dir;
  if ($seen{$dir}) {
    return;
  }
  # Mark that we've been here. No point doing a dir twice
  $seen{$dir} = 1;
  if ($dir =~ /$exclude/i) {
    print "\nExcluding $dir\n" if ($debug);
    return;
  }
  print "#" if (!$debug);
  opendir(DIR, $dir) || die "can't opendir $dir: $!";
	# Grab any file that doesn't start with a .
  my @files = grep {/^[^\.]/ && -f File::Spec->catfile("$dir",$_)} readdir(DIR);
	return if $#files < 0;
  closedir(DIR);
  # If there's not a cover here already
  if (!(grep {/$file_name/i} @files)) {
    # We only want music file with extensions we recognize
    @files = ReadTag::getMatchingExts(@files);
    return if ($#files < 0);
    warn "\nNow looking in: $dir\n" if ($debug);
    # Are we doing a various artist type disc?
    # Check by comparing the artist tags on 1st and 2nd track
    my $tag;
    my $various = ReadTag::isVarious(@files);
    warn "This album is", $various ? "" : " not", " a Various artists album\n" if ($debug);
    # Let's just grab the first file with a tracknumber of 1 
    # or -if that doesn't exist- just the first  file we find. 
    # Use the info from him
    $tag = ReadTag::getTag(ReadTag::getTrackNum(1,@files) || shift @files) || warn "\nNo tag info in: $dir\n";
    warn "Using this track to test: ", $tag->{"ALBUM"}, "\n" if ($debug);
    if (!$tag->{"ARTIST"} || ! $tag->{"ALBUM"}) {
       warn "\nNo artist or album in $dir\n" if ($debug);
       return;
    }
    if($tag->{"GENRE"} && ($genre_regex)) {
       if($tag->{"GENRE"} =~ /$genre_regex/i) {
          warn "\nSkipping genre " . $tag->{"GENRE"} . " in $dir\n" if ($debug);
	  return;
       }
    }

    my $a = new AmazonMusicImage(debug=>$debug);
    # Start by trying to get the large size image
    # If it's not there, ask for smaller sized images
    # We have to fetch the image each time because we have no
    # way of knowing about a place-holder image until we look at it
    my $url = $a->get_url($tag, size=>"Large", var=>"$various");
    if ($url) {
      $image = get_image($url);
    }
    if (!$image) {
      $url = $a->get_url($tag, size=>"Medium", var=>"$various");
      $image = get_image($url) if $url;
    }
    if (!$image) {
      $url = $a->get_url($tag, size=>"Small", var=>"$various");
      $image = get_image($url) if $url;
    }
    if ($image) {
      open(FOO,">$file_name") || die "Could not open cover.jpg in $dir for writing! $!\n";
      # In case we're on Windows or
      # on a perl build that thinks everything should be
      # UTF-8 text
      binmode(FOO); 
      print FOO $image;
      close FOO || warn "\nCould not write to $file_name!: $!\n";
    }
  }
	else {
		warn "Image file already exists in $dir\n" if ($debug);
	}
}

sub get_image {
  my $url = shift;
  my $image;
  my $ua = LWP::UserAgent->new;
  my $req = HTTP::Request->new(GET=>$url);
  my $res = $ua->request($req);
  if ($res->is_success) {
     $image =  $res->content;
  } else {
    warn  "\nCould not download image file for $url\n" if ($debug);
		return;
  }

  my $info = image_info(\$image);
  my ($h, $w) = dim($info);
  if (($h == 1) && ($w == 1)) {
    # Sometimes Amazon gives us a 1x1 gif if it could not find the picture
    warn  "\n1x1 image found. Moving on\n" if ($debug);
    return;
  }
  return $image;
}
