###########################################
# Mike Schilli, 2006 (m@perlmeister.com)
###########################################
package Videodir;
###########################################
use strict; use warnings;
use YAML qw(LoadFile DumpFile);
use File::Basename;

###########################################
sub new {
###########################################
  my($class, %options) = @_;

  my $self = { 
    dir          => "$ENV{HOME}/tv",
    meta_file    => ".meta",
    keep_default => 5,
    meta         => {},
    max_gigs     => 20,
    %options };

  $self->{meta_path} = 
     "$self->{dir}/$self->{meta_file}";

  bless $self, $class;
  $self->rescan();
  return $self;
}

###########################################
sub rescan {
###########################################
  my($self) = @_;
  if(-f $self->{meta_path}) {
    $self->{meta} = 
        LoadFile($self->{meta_path});
  }

  $self->{total_size} = 0;
  my @items = ();

  my $dir = $self->{dir};
  for my $path (<$dir/*>) {

    next unless -f $path;
    my $file = basename $path;

    $self->{meta}->{$file}->{keep} = 
       $self->{keep_default} unless defined 
       $self->{meta}->{$file}->{keep};

    my $size = -s $path;
    $self->{total_size} += $size;

    my $age  = age_in_days($path);

    push @items, { 
      file => $file,
      path => $path,
      age  => $age,
      size => gb($size),
      ttl  => 
          $self->{meta}->{$file}->{keep} - 
          $age,
    };
  }
    
  $self->{total_size} =
      gb($self->{total_size});

    # Delete outdated entries
  for my $k (keys %{$self->{meta}}) {
     delete $self->{meta}->{$k} unless 
         -f "$self->{dir}/$k";
  }

  $self->meta_save();

    # Sort by descending by age
  $self->{items} = [
    sort { $a->{age} <=> $b->{age} } 
         @items ];
  return $self->{items};
}

###########################################
sub gb {           # Umrechnen in Gigabytes
###########################################
  my($val) = @_;
  return sprintf "%.1f", $val / (1024**3);
}

###########################################
sub remove {
###########################################
  my($self, $file) = @_;

  my $path = "$self->{dir}/$file";
  if(-f $path) {
    unlink $path or 
      die "Cannot unlink $path";
  }
  $self->rescan();
}

###########################################
sub age_in_days {
###########################################
    my($file) = @_;

    return(sprintf "%.1f", (time() - 
       (stat $file)[9]) / 24 / 3600);
}

###########################################
sub shrink {
###########################################
  my($self) = @_;

  my $deleted = 0;
  my @doomed = reverse
               grep { $_->{ttl} < 0 }
               @{$self->{items}};
  while($self->{total_size} > 
        $self->{max_gigs}) {
    last unless @doomed;
    my $item = shift @doomed;
    $deleted++;
    $self->remove($item->{file});
  }
  return $deleted;
}

###########################################
sub meta_save {
###########################################
  my($self) = @_;
  DumpFile($self->{meta_path}, 
           $self->{meta});
}

1;
