#!/usr/bin/perl
#
#
use strict;
use Getopt::Std;

my %opts;
getopts('hLrSvb:j:l:n:r:s:',\%opts);

$opts{h}        and help_exit();

my $printentries = 1;

my $journalarg  = $opts{j};
my $logfile     = $opts{l};
my $numstop     = $opts{n};
my $startentry  = $opts{s};
my $verbose     = $opts{v};
my $listfiles   = $opts{L};
my $resume      = $opts{r};
my $simulate    = $opts{S};

$main::VERSION = '2.10.2';

$journalarg or help_exit();
my $Log = new Logfile($logfile,$simulate);

my (@journalfiles, $boxdir);
if (-f $journalarg) {
    ($boxdir) = $journalarg =~ m!^(.+?)journal/[^/]+\.journal(\.gz)?!;
    push @journalfiles, $journalarg;
}
elsif (-d $journalarg) {
    $boxdir = $journalarg;
    @journalfiles = journalfiles($journalarg);
}

if ($listfiles) {
    foreach my $journalfile (@journalfiles) {
        $Log->write("Journalfile: $journalfile",2);
    }
    exit 0;
}

if (!@journalfiles) {
    print STDERR "ERROR boxdir or journalfile not valid: $journalarg\n";
    exit 3;
}


$startentry = Logfile->getLastId($logfile)  if $resume;
if ($startentry) {
    $Log->write("Start at entry $startentry",2);
    $printentries = 0;
}

$Log->write("Append to $logfile",2);

my $current_time = current_time();
$Log->write("$current_time: Export files from $journalarg",1);

my $n = 0;
foreach my $journalfile (@journalfiles) {
    $Log->write("Process journal file $journalfile",2) if $verbose;
    $Log->write(current_time().": Process journal file $journalfile",1);

    my $jh;
    if ($journalfile =~ /\.gz$/) {
        open $jh, "<:gzip", $journalfile   or die "Cannot open journal file \"$journalfile\": $!\n";
    }
    else {
        open $jh, $journalfile             or die "Cannot open journal file \"$journalfile\": $!\n";
    }


    foreach my $line (<$jh>) {
        chomp $line;
        # 2023-06-29 14:37:36 UTC: (SUCCESS) ARCHIVED   "2023:016ADE9F4C6640DC69B0A0B95D751E4B56AD5E6AF38851EFB4264DE0B11BE99500": archived

        my ($yeardir,$first,$second,$third,$filename) = $line =~ /"(\d{4}):(\w\w)(\w\w)(\w\w)(\w+?)": archived$/;
        next unless $filename;
        my $jrlentry = "$yeardir:$first$second$third$filename";

        if (! $printentries) {
            if ($startentry eq $jrlentry) {
                $printentries = 1;
                $Log->write("Start export at entry $startentry",3);
                next;   # start at next entry
            };
        }
        next unless $printentries;

        my $filepath = "$boxdir/$first/$second/$third/$filename.gz";
        $filepath =~ s!^/!!gm;
        $filepath =~ s!//!/!gm;

        print "$filepath\n";
        $Log->write("  $jrlentry",1);
        $n++;

        if ($numstop && ($n >= $numstop)) {
            $Log->write("STOPPED AFTER \" -s $numstop\" entries",2);
            exit 2;
        }
    }
    close $jh;
}

$Log->write("Export of $n entries from $boxdir successful",2) if $verbose;
$Log->write(current_time().": Export of $n entries from $boxdir successful",1);


### SUBS ###

### help_exit()
sub journalfiles
{
    my ($boxdirpath) = @_;
    my @journalfiles;

    my $journaldir = "$boxdirpath/journal";
    if (-d $journaldir) {
        opendir(my $dh, $journaldir) || die "Can't opendir $journaldir: $!";
        while (my $journalfile = readdir $dh) {
            next if $journalfile =~ /^\./;

            my $filepath = $boxdir.'/journal/'.$journalfile;
            push @journalfiles,$filepath;
        }
    }

    return sort @journalfiles;     # !!sort sorts array in place
}

sub current_time
{
    my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)=localtime();
    $year += 1900;
    $mon  += 1; $mon = sprintf("%02d",$mon);
    $mday = sprintf("%02d",$mday);
    $hour = sprintf("%02d",$hour);
    $min  = sprintf("%02d",$min);
    $sec  = sprintf("%02d",$sec);

    return "$mday.$mon.$year $hour:$min:$sec";
}


sub help_exit
{   
    print "Usage: $0 [-h] <-j <journalfile|boxdir>\n";
    print "Version $main::VERSION\n";
    print "\n";
    print "    Print journal file entries as filname with path.\n";
    print "    used for tar input as: \"| tar -T- -cf- | ssh benno\@targethost 'tar -xf-'\"\n";
    print "\n";
    print "   Arguments for -j:\n";
    print "    -j <journalfile> journal file to process (eg. /srv/benno/archive/repo/2023/journal/current.journal)\n";
    print "    -j <boxdir>      box directory with journal entries (e.g. /srv/benno/archive/repo/2023)\n";
    print "\n";
    print "    -l <logfile>     logfile\n";
    print "    -n <num>         stop after num entries (for debug purposes)\n"; 
    print "    -s <BennoID>     start at journal entry (eg. 2023:4BA3B...00)\n"; 
    print "    -r               resume from last entry of logfile\n"; 
    print "    -L               list journalfiles to process and exit\n";
    print "    -S               simulate - no writes to logfile\n";
    print "\n";
    
    exit 1;
}   


### EOP ###
1;  

package Logfile;

sub new
{
    my ($class,$logfile,$simulate) = @_;
    my $self = { 'loghandle' => undef };
    if ($logfile and not $simulate) {
        open my $loghandle, ">>$logfile" or die "Cannot write logfile  \"$logfile\": $!\n";
        $self->{loghandle} = $loghandle;
    }
    bless $self, $class;

    return $self;
}


# ($msg,$target)
#  targets
#    0: logfile
#    1: logfile
#    2: STDERR
#    3: logfile + STDERR

sub write
{
    my ($self,$msg,$target) = @_;

    $target = 1 unless $target;

    $msg .= "\n";
    print STDERR $msg if $target & 0b10;

    return unless $self->{loghandle};

    my $loghandle = $self->{loghandle};
    print $loghandle $msg if $target & 0b01;
}


sub getLastId
{
    my ($class,$logfile) = @_;
    
    my $lastline;
    open my $loghandle, "$logfile" or die "Cannot read logfile  \"$logfile\": $!\n";
    foreach my $logline (<$loghandle>) {
        next unless $logline =~ /^\s\s(\S.*)/;
        $lastline = $1;
    }
    chomp $lastline;

    return $lastline;   # return last line whith id
}

1; ### EOP ###
