#!/usr/local/bin/perl -w
###########################################
# usbback - Backup files on USB sticks
# 2013, Mike Schilli <m@perlmeister.com>
###########################################
use strict;
use local::lib;
use YAML qw( LoadFile );
use Algorithm::Bucketizer 0.13;
use File::Basename;
use Sysadm::Install qw( :all );
use Log::Log4perl qw(:easy);

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

my( $home )  = glob "~";
my $src_dir  = "$home/books";
my $dst_dir  = "$home/sticks";
my $cfg_file = "usbback.yml";
my $gig      = 1_000_000_000;
my $buckets = Algorithm::Bucketizer->new();

my $conf = LoadFile $cfg_file;

my %files = ();

for my $path ( <$src_dir/*> ) {
  my $file = basename $path;
  $files{ $file } = 
    blocksize_round( -s $path );
}

  # buckets configured in YAML
for my $entry ( @$conf ) {
  my $bucket_dir  = $entry->{ name };
  my $bucket_path = "$dst_dir/$bucket_dir";

  if( !-d $bucket_path ) {
    mkd $bucket_path;
  }
  if( $entry->{ size } =~ /(\d+)g/ ) {
      $entry->{ size } = $1 * $gig;
  }

  my $bucket = $buckets->add_bucket( 
      maxsize => $entry->{ size },
      dir     => $bucket_path,
  );

    # prefill buckets with links found
  for my $path ( <$bucket_path/*> ) {
    my $file = basename $path;
    my $ref  = readlink $path;
    my $size = blocksize_round( -s $ref );

    $buckets->prefill_bucket( 
        $bucket->idx(), $file, $size );

    delete $files{ $file };
  }
}

  # remaining files
for my $file ( sort keys %files ) {
  my $size = $files{ $file };

  my $bucket = $buckets->add_item( 
      $file, $size ) or
        die "Item $file won't fit, " .
        "buckets are full";

  INFO "Adding $file ($size bytes) to ",
    "bucket $bucket->{ dir }";

  symlink "$src_dir/$file", 
          "$bucket->{ dir }/$file";
}

###########################################
sub blocksize_round {
###########################################
  my( $size ) = @_;
  
  my $bs = 4096;

  if( ($size % $bs) ) {
      return (int( $size/$bs ) + 1 ) * $bs;
  }

  return $size;
}
