# NOTICE:  If you see "Can't locate Encode/ConfigLocal.pm in @INC"
# then you need to run (as root user on unix):  "enc2xs -C"

# TODO: feed autodiscovery
# TODO: enclosures (MediaRSS?)
use strict;
my $XML_RSS = album::attempt_require('XML::RSS');
my $XML_RSS = 1;

# This plugin generates one feed per album.  Thus,someone can subscribe to sub-albums in an album
# i.e. if you have a multi-person album or something.  my_end_album is where we do our work.
# This function gets called as the recursive do_album function is unwinding, so we're working
# from leaf nodes back up the tree.  What we do is collect up items left to us by our child nodes,
# add our items, write it out to the feed, and leave this collection for our (potential) parent
# node.

# Definitions:
# Item: A single entry in an RSS feed.  Could be a whole album or could be a single image,
#       depending on configuration.

my ($SINCE, $ITEMS);

sub start_plugin {
    my ($opt, $plugin, $path) = @_;

    my $ret = {
	author => 'Jason Dufair',
	href => 'http://www.dufair.org/',
	version => '0.1',
	description => "Generates an rss feed for recently added/updated albums and images",
    };


    unless ($XML_RSS) {
	my $err = "XML::RSS is required and not installed!\n";
	print STDERR "\n[Plugin: $plugin] $err\n";
	$ret->{description} .= "\n$err";
	return $ret;
    }


    ##################################################
    # OPTIONS
    ##################################################
    album::add_option(1,
		      'numberOfDays',
		      album::OPTION_NUM,
		      default=>30,
		      usage=>"Include images up to this many days old");
    album::add_option(1,
		      'title',
		      album::OPTION_STR,
		      usage=>"The album's RSS feed title");
    album::add_option(1,
		      'language',
		      album::OPTION_STR, default=>'en-us',
		      usage=>"The album's RSS feed language");
    album::add_option(1,
		      'description',
		      album::OPTION_STR,
		      usage=>"A short description of the album's RSS feed");
    album::add_option(1,
		      'creator',
		      album::OPTION_STR, usage=>"The creator of the album's RSS feed");
    album::add_option(1,
		      'publisher',
		      album::OPTION_STR,
		      usage=>"The publisher for the album's RSS feed");
    album::add_option(1,
		      'feedImage',
		      album::OPTION_STR,
		      usage=>"The URL to an image associated with the whole album");
    album::add_option(1,
		      'feedFilename',
		      album::OPTION_STR,
		      default=>'index.rdf',
		      usage=>"The name of the file containing the XML for the feed");
    album::add_option(1,
		      'feedBase',
		      album::OPTION_STR,
		      usage=>"The URL that points to your album's top folder (no trailing slash)");

    album::hook($opt,'end_album', \&my_end_album);

    $ret;
}

sub create_feed {
    my ($opt, $rss, $dir) = @_;

    my $feedBase = album::option($opt, 'feedBase');
    $rss->channel(title       => album::option($opt, 'title') | "No title",
		  link        => "$feedBase$dir/index.html",
		  description => album::option($opt, 'description') || "No description given",
		  dc => {creator   => album::option($opt, 'creator'),
			 publisher => album::option($opt, 'publisher'),
			 language  => album::option($opt, 'language')});
    $rss->image(title => album::option($opt, 'title'),
		url   => album::option($opt, 'feedImage'),
		link  => "$feedBase$dir/index.html")
	if album::option($opt, 'feedImage');
}

sub get_items_left_by_children {
    my ($data) = @_;

    return $ITEMS->{$data->{paths}{album_path}} || [];
}

sub add_local_images {
    my ($opt, $data, $dir, $albumItems, $itemCount) = @_;

    my $description = "<![CDATA[<div align=\"center\">";
    my $album_url =
	album::option($opt, 'feedBase') . "/" .
	$data->{paths}{album_path} . "/";
    my $imageCount = 0;
    for(my $i=0; $i<=$#{$data->{pics}}; $i++) {
	my $pic = $data->{pics}[$i];
	my $picModTime = (stat("$dir/$pic"))[9];
	next if $picModTime < $SINCE;

	my $obj = $data->{obj}{$pic};
	my $name = $obj->{name};
	$description .=
	    "<a href=" .
	    "'" . $album_url . eval($obj->{URL}{album_page}{image}) . "'" .
	    "><img src=" .
	    "'" . $album_url . eval($obj->{URL}{album_page}{thumb}) . "'" .
	    " /><br />$name<br /><br /><br /></a>\n";
	$imageCount++;
    }
    $description .= "</div>]]>";

    my $itemModTime = (stat($dir))[9];
    if ($imageCount) {
	push(@$albumItems,
	     ({title => $data->{paths}{album_path}, #TODO: make this more friendly
	       link => $album_url,
	       description => $description,
	       modTime => $itemModTime}));
    
    	$$itemCount++;
    }
}

sub write_items_to_feed {
    my ($rss, $albumItems) = @_;

    foreach my $item (sort { $a->{modTime} cmp $b->{modTime} } @$albumItems) {
	$rss->add_item(title       => $item->{title},
		       link        => $item->{link},
		       description => $item->{description});
    }
}

sub save_items_for_parent {
    my ($data, $albumItems) = @_;

    my $parent = join('/',
		      @{$data->{paths}{parent_albums}}[0..@{$data->{paths}{parent_albums}} - 2]);

    $ITEMS->{$parent} = [] if (!$ITEMS->{$parent});
    foreach my $item (@$albumItems) {
	push(@{$ITEMS->{$parent}}, ($item));
    }

    delete $ITEMS->{$data->{paths}{album_path}};
}

sub save_feed {
    my ($opt, $rss, $dir) = @_;

    my $feedFilename = album::option($opt, 'feedFilename');
    $rss->save("$dir/$feedFilename");
}

sub my_end_album {
    my ($opt, $data, $hookname, $dir, $album) = @_;

    my $numberOfDays = album::option($opt, 'numberOfDays');
    $SINCE = time() - ($numberOfDays * 24 * 60 * 60);

    my $rss = new XML::RSS (version => '1.0');
    create_feed($opt, $rss, $dir);

    my $albumItems = get_items_left_by_children($data);
    my $itemCount = @$albumItems;
    add_local_images($opt, $data, $dir, $albumItems, \$itemCount);
    write_items_to_feed($rss, $albumItems);
    save_items_for_parent($data, $albumItems);
    save_feed($opt, $rss, $dir);

    my $w = $opt->{hash_width} - $opt->{num_hashes} - 3 - 8;
    my $album = $data->{paths}{album_path};
    my $p = (length($album) >= $w) ?  '..'.substr($album,-$w+3) : $album;
    album::start_hashes($opt, "RSS    : $p");
    print "$itemCount new or updated album";
    print "s" if ($itemCount != 1);
    print "\n";
}
1;
