#!/usr/bin/perl
#
#
use strict;
use Getopt::Std;
use XML::LibXML;
use LWP::Protocol::https;   # ensure using https!
use Net::Amazon::S3;
use Benno::Box;
use Benno::Boxstate::S3;

my $VERSION = '2.8.16';
my $DEBUG = $ENV{DEBUG};

my %opts;
getopts('hVqvb:k:t:',\%opts);

$opts{h} and help_exit();
$opts{V} and print "benno-s3-checks $VERSION\n" and exit;

my $conf;
$conf->{boxstate}     = $opts{b} if $opts{b};
$conf->{keylist}      = $opts{k} if $opts{k};
$conf->{throttle}     = $opts{t} || 2;
$conf->{quiet}        = $opts{q} if $opts{q};
$conf->{verbose}      = $opts{v} if $opts{v};

$conf->{boxstate}   or help_exit();
$conf->{keylist}    or help_exit();

my $idlist = get_idlist($conf->{keylist});

my $Boxstate;
eval {
    $Boxstate = new Benno::Boxstate::S3($conf->{boxstate});
};
if ($@) {
   die "Cannot parse boxstate file: $@\n";
}

# load boxes
my $boxes;
my $suffix = '';
foreach my $Box ($Boxstate->get_boxes) {
    $conf->{authkeyid}  = $Box->get_config('authKeyId');
    $conf->{authsecret} = $Box->get_config('authKey');
    $conf->{endpoint}   = $Box->get_config('endpoint');
    my $bucketname = $Box->get_config('bucket');
    my $boxpath    = $Box->get_config('bennoPath');
    if ($Box->get_config('compression') eq 'gzip') {
        $suffix = '.gz';
        $conf->{verbose} && print "Compression enabled, append $suffix to keyid\n";
    }

    my $S3Bucket = new S3($conf)->bucket(name => $bucketname);
    $conf->{verbose} && print "Connect $conf->{endpoint}:$bucketname\n";

    foreach my $subid (@{$idlist->{$Box->id}}) {
        my $keyid = $boxpath.'/'.$Box->id.':'.$subid.$suffix;
        my $Object = $S3Bucket->object(key => $keyid);
        $conf->{verbose} && print "Fetch object: ",$Object->uri,"\n";
        eval { # Version 0.86 returns 0, other versions die
            if ($Object->exists) {
                print "OK: $keyid\n" unless $conf->{quiet};
            }
            else {
                die "Object does not exist\n";
            }
        };
        if ($@) {
            if ($@ =~ /^404:/) {
                print "NA: $keyid\n";
            }
            else {
                print "ERROR: $@\n";
            }
        }
        my $req_sec = 1 / $conf->{throttle};
        select(undef,undef,undef,$req_sec);
    }
}



### SUBS #######################################################################

### get_idlist
sub get_idlist
{
    my ($listfile) = @_;
    my $boxlist = {};
    my $idlist;

    open my $listfh, $listfile or die "Cannot open $listfile: $!\n";
    foreach my $line (<$listfh>) {
        next if $line =~ /^#/;
        $line =~ s/\R//g;
        # 2022:980A9994505E8B241C6A7A3B7DDE08D2FD26246B3527F62B8FF4D31036744C4500
        my ($box,$bennoid) = split /:/, $line;
#        $boxlist->{$box} = [] unless (exists ($boxlist->{$box});
        push @{$boxlist->{$box}}, $bennoid;
    }
    close $listfh;

    return $boxlist;
}


### help_exit
sub help_exit
{
    print "Usage: benno-s3-admin -b <bucket> -k <keylistfile> [-t <requests>]\n";
    print "  -b <boxstate>      boxstate file\n";
    print "  -k <keylist>       file with list of keys or \"-\" for STDIN\n";
    print "  -t <requests>      throttle to <requests>/s (default: 2)\n";
    print "  -q                 quiet mode, print only not available objects\n";
    print "  -v                 verbose mode\n";
    print "  -V                 print version\n";
    print "\n";
    exit 1;
}

### EOP ###
1;


package S3;
use parent 'Net::Amazon::S3::Client';

sub new
{
    my $class = shift;
    my ($conf) = @_;
    my $self = Net::Amazon::S3::Client->new(s3 => 
            Net::Amazon::S3->new({
                  aws_access_key_id     => $conf->{authkeyid},
                  aws_secret_access_key => $conf->{authsecret},
                  host                  => $conf->{endpoint},
           })
        );

    bless $self, $class;
    return $self;
}


### EOP ###
1;

