# Album Plugin:	utils/mv
# For info:	'album -plugin_info utils/mv'
# For usage:	'album -plugin_usage utils/mv'
use strict;

my $DESC = <<DESC;
This will move images from one album to another.
It also moves associated files (thumbnails, medium) and updates captions.txt

It will rebuild the albums if you specify '-gen' in the options.

You can use a special shorthand to call this plugin:
% album -mv <images..> <destination>
DESC


sub usage {
  my $opt = shift @_;
  foreach my $msg (@_) { print STDERR "ERROR:  $msg\n"; }
  print STDERR <<USAGE;

Usage:\t$opt->{PROGNAME} -mv [-gen] <images..> <destination>

$DESC
USAGE
  exit -1;
}

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

  # We actually do this code during -list_plugins and shouldn't, but
  # right now it doesn't seem to matter.
  $opt->{mv}{dest} = pop @ARGV;
  while (my $arg = shift @ARGV) {
    if ($arg eq "-h") { usage(); }
    if ($arg eq "-gen") { $opt->{mv}{gen} = 1; next; }
    push(@{$opt->{mv}{src}}, $arg);
  }

  album::add_album_dir($opt, $opt->{mv}{dest}) if $opt->{mv}{gen};

  # Don't save the confs if we generate.
  $opt->{save_conf} = 0;

  album::hook($opt,'pre_do_albums', \&album_mv);

  return {
    author => 'David Ljung Madison',
    href => 'http://MarginalHacks.com/',
    version => '1.0',
    description => $DESC."
You can view usage with:
% $opt->{PROGNAME} -mv -h",
  };
}

# This should probably be in album (as well as the cache!)
my %ALBUM_INFO;	# Cache
sub album_info {
  my ($opt,$dir) = @_;

  unless ($ALBUM_INFO{$dir}) {
    my $data = album::new_album_data($opt,$dir);
    album::gather_contents($opt, $data);
    album::get_captions($opt,$data);
    album::sort_info($opt,$data);
    $ALBUM_INFO{$dir} = $data;
  }

  return $ALBUM_INFO{$dir};
}

sub img_mv {
  my ($opt, $dir, $img, $dest) = @_;

  # Move the image
  rename("$dir/$img","$dest/$img");

  # Move the .postfix files
  foreach my $post (".txt", $opt->{no_album}, $opt->{hide_album}, $opt->{not_img}) {
    rename("$dir/$img$post","$dest/$img$post");
  }

  # Move the medium/thumbnails
  my $pre = ($img =~ /^(.+)\.[^\.]+$/) ? $1 : $img;
  # A bit of a kludge, but we have no easy way to determine
  # the thumbnail and medium files without either generating
  # them or else duplicating album code.  Will only cause problems
  # if the album has images like:  image.gif and image.hi.gif
  opendir(TN,"$dir/$opt->{dir}") || return;
  my @tn = grep(!/^\.{1,2}$/, readdir TN);
  closedir TN;
  foreach my $tn ( @tn ) {
    rename("$dir/$opt->{dir}/$tn", "$dest/$opt->{dir}/$tn")
      if $tn =~ /^\Q$pre.\E/;
  }
}

sub album_mv {
  my ($opt) = @_;

  # Check destination
  my $dest = $opt->{mv}{dest};
  usage($opt,"Last argument to -mv must be a destination directory")
    unless -d $dest;
  $dest =~ s|/+$||;
  mkdir("$dest/$opt->{dir}");	# In case it's a new directory.

	usage($opt,"No files specified for -mv") unless $opt->{mv}{src};
	
  # For each source:
  my @src = @{$opt->{mv}{src}};
  my @gen;
  while (my $src = shift @src) {
    usage($opt,"Unknown file to -mv: $src") unless -f $src;
    my ($dir,@imgs) = album::split_path($opt, $src);
    push(@gen,$dir);

    # Find all the files with the same directory so we can move
    # them in bulk - that way we not only edit the captions.txt once,
    # but we keep them in order.
    my @nomatch;
    foreach my $src2 ( @src ) {
      my ($dir2,$img2) = album::split_path($opt, $src2);
      ($dir eq $dir2) ? push(@imgs, $img2) : push(@nomatch, $src2);
    }
    @src = @nomatch;

    # Get the album info.
    print "Moving from $dir:\n";
    my $data = album_info($opt, $dir);
    foreach my $img ( @imgs ) {
      print "  $img\n";
      img_mv($opt,$dir,$img,$dest);
    }

    # Update captions.txt
    if (open(CAP, "<$dir/$opt->{captions}")) {
      my (@new, @old);
      while (<CAP>) {
        # Any plugins that alter the way the first column of captions.txt
        # might not properly move captions over.  Worst case scenario is
        # that they get left behind.  This code is basically stolen from album:
        my $split_tabs = /\t/ ? 1 : 0;
        my ($file) = $split_tabs ? split(/\t+/, $_) : split(/\s*::\s*/, $_);
        $file =~ s/\s$//;	# In case it needed to be chomped
        $file =~ s/^#//;	# We move commented out files as well
        (grep($file eq $_, @imgs)) ? push(@new, $_) : push(@old, $_);
      }
      close CAP;

        # If we fail, perhaps we should move images back?  Bah.
      usage("Can't write destination captions: $dest/$opt->{captions}")
        unless open(CAP, ">>$dest/$opt->{captions}");
      print CAP @new;
      close CAP;

      usage("Can't write old captions: $dir/$opt->{captions}")
        unless open(CAP, ">$dir/$opt->{captions}");
      print CAP @old;
      close CAP;
    }
  }

  # Are we done?
  album::done() unless $opt->{mv}{gen};

  # Done moving!  Now regenerate all the albums!
  $opt->{depth} = 1;
  map { album::add_album_dir($opt, $_) } @gen;
}

# Plugins always end with:
1;
