#!/usr/bin/perl
#
#
use strict;
use Getopt::Std;
use Sys::Syslog;
use Fcntl ':flock'; 
use YAML::Tiny;
use File::Copy;
use lib qw(/usr/lib/benno-import-tools);
use Benno;
use Benno::Import::RESTClient;

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

my %opts;
getopts('dhlsvR:U:y:',\%opts);

my $delete          = $opts{d};
my $yamlconfig      = $opts{y}  || '/etc/benno-import/rest.yml';
my $runuser         = $opts{R}  || 'benno';
my $multiplerun     = $opts{M};
my $listurls        = $opts{l};
my $simulate        = $opts{s};
my $urlonly         = $opts{U};
my $verbose         = $opts{v};


if ($opts{V}) {
    print "benno-send2archive $VERSION\n";
    exit 0;
}

help_exit() if $opts{h};

openlog('benno-import-tempfiles','nowait,pid','mail');

main::lock() unless $opts{M};
Benno->run_as($runuser);

my $config = YAML::Tiny->read($yamlconfig)->[0];

my $temppath   = $config->{benno}->{tempFiles}->{path};
my $jwt_secret = $config->{benno}->{jwt}->{sharedSecret};

my @storagebackends = ();
opendir(my $tph, $temppath) || die "Can't open $temppath: $!";
while (my $tempdir = readdir $tph) {
    next if $tempdir =~ /^\./;

    my $storagepath = "$temppath/$tempdir";
    my $storagefile = "$storagepath/.storageurl";
    my $storageurl  = "";

    if (-f $storagefile) {
        open my $sh, '<', $storagefile or warn "Cannot open $storagefile: $!\n" and next;
        $storageurl = <$sh>;
        close $sh;
    }
    elsif ($tempdir =~ /^archive$/) {
        $storageurl = 'file://'.$config->{benno}->{archiveEndpoint}->{inboxPath};
    } 
    else {
        next;
    }

    chomp $storageurl;
    $urlonly && next unless $urlonly eq $storageurl;
    print "Fetch url from $storagepath: $storageurl\n" if $verbose;
    print "Directory $storagepath for $storageurl\n" if $listurls;
    push @storagebackends, [$storagepath,$storageurl];
}
closedir $tph;

exit 0 if $listurls;

foreach my $backend (@storagebackends) {
    my $backendtmp = $backend->[0];
    my $backendurl = $backend->[1];
    print "Process storagebackend: $backendurl\n" if $verbose;
    if ($backendurl =~ /^http/) {
        my $RC = Benno::Import::RESTClient->new($backendurl);
        foreach my $dirfile (get_dirfiles($backendtmp)) {
            print "Send $dirfile to $backendurl\n" if $verbose;
            next if $simulate;
            my $ret = "Sent to $backendurl: ";
            eval {
                $RC->auth_bearer($jwt_secret,$dirfile);
                (-e $dirfile) or next;
                $ret .= $RC->upload_mail(get_filecontent($dirfile));
                $delete and unlink $dirfile and $ret .= ' (deleted)';
                syslog('LOG_INFO',$ret);
                print $ret."\n" if (-t STDIN);
            };
            if ($@) {
                my $err = $@;
                syslog('LOG_ERR',$err);
                print STDERR $err;
                next;
            }
        }
    }
    elsif ($backendurl =~ /^file/) {
        (my $inboxdir) = $backendurl =~ m!^file://(/.+)$!;
        foreach my $dirfile (get_dirfiles($backendtmp)) {
            print "Copy $dirfile to $backendurl\n" if $verbose;
            next if $simulate;
            eval {
                my ($basename) = $dirfile   =~ m!.*?([^/]+?)\.eml$!;
                my $targettmp = $inboxdir.'/'.$basename.'.imp';
                my $targeteml = $inboxdir.'/'.$basename.'.eml';
                (-e $targeteml) and next;
                copy($dirfile,$targettmp);
                link($targettmp,$targeteml) or die "Cannot link $targettmp to $targeteml: $!\n";
                unlink $targettmp or die "Cannot remove $targettmp: $!\n";

                syslog('LOG_INFO',"$dirfile moved to $inboxdir");
                print "$dirfile moved to $inboxdir\n" if (-t STDIN);
                $delete and unlink $dirfile;
            };
            if ($@) {
                my $err = $@;
                syslog('LOG_ERR',$err);
                print STDERR $err;
                next;
            }
        }
    }
    else {
        print STDERR "Cannot process storagebackend: $backendurl\n";
    }

}

closelog;

### SUBS ###


sub get_dirfiles
{
    my ($tmpdir) = @_;

    my @dirfiles;
    opendir(my $dh, $tmpdir) || die "Cannot open $tmpdir: $!";
    while (my $dirfile = readdir $dh) {
        next if $dirfile =~ /^\./;
        next unless $dirfile =~ /\.eml$/;

        push @dirfiles, "$tmpdir/$dirfile";
    }
    closedir $dh;

    return @dirfiles;
}


sub get_filecontent
{
    my ($file) = @_;

    my $content;
    open my $fh, '<', $file or die "Cannot open $file: $!\n";
    local $/ = undef;
    $content = <$fh>;
    close $fh; 

    return $content;
}


### help_exit()
sub help_exit
{
    my $msg = shift;

    if ($msg) {
        print $msg,"\n\n";
    }

    print "Usage: $0 [-c <yaml config>] [params]\n";
    print "\n";
    print "    -d             Delete file after successful upload\n";
    print "    -y <yaml conf> yaml config file (default: /etc/benno-import/rest.yml)\n";
    print "\n";
    print "    -M             run multiple instances of this program\n";
    print "    -R <user>      run as user (default: benno)\n";
    print "    -U <url>       process only storageurl\n";
    print "    -l             list storageurls and paths\n";
    print "    -s             simulate\n";
    print "    -v             verbose\n";
    print "    -V             print version\n";
    print "\n";

    exit 1;
}


### lock
#   allow one instance of this program running
sub lock {
    if (tell(*main::DATA) == -1) {
        # __DATA__ handle not available
        print STDERR "$0 needs an __END__ literal at the end of the file.\n";
        exit 2;
    }
    elsif (!flock main::DATA, LOCK_EX | LOCK_NB) {
        use Sys::Syslog;
        openlog('benno-imapimport','nowait,pid','mail');
        # cannot lock __DATA__ "file"
        print STDERR "An instance of $0 is already running.\n" if -t;
        syslog('ERR',"An instance of $0 is already running.\n");
        exit 1;
    }
}

1; ### EOP ###

__END__
