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

my %opts;
getopts('hjvDIQc:e:f:F:i:L:q:s:H:P:',\%opts);

help_exit() if $opts{h};

my $container = $opts{c} || 'BennoContainer';
my $secret    = $opts{s} || fetchSecret('/etc/benno/rest.secret','/etc/benno/benno.xml');
my $query     = $opts{q};
my $mailid    = $opts{i};
my $json      = $opts{j};
my $filter    = $opts{f} || '*'; 
my $host      = $opts{H} || 'localhost';
my $port      = $opts{P} || 21080;
my $first     = $opts{F} || 0;
my $limit     = $opts{L} || 20;
my $verbose   = $opts{v};
my $quiet     = $opts{Q};

$verbose += 2 if $opts{D} ;

help_exit() unless $secret;
help_exit() if ($query && $mailid);

my $proto = 'http';

my $params;
my $path;
if ($mailid) {
    $params = { 'archive' => $container,
                'id'      => $mailid,
              };
    $params->{'format'} = 'raw' if not $json;

    $path  = '/mail/';
}
else {
    $query =~ s/SortableDate:\[/Date:[/g;
    if (-f $query)  { $query  = read_first_line($query); }
    if (-f $filter) { $filter = read_first_line($filter); }
    $params = { 'archive' => $container,
                'query'   => '('.$query.')',
                'query'   => $query,
                'start'   => $first,
                'limit'   => $limit,
                'filterQuery' => '('.$filter.')',
              };
    $path  = '/search/';
}

my $uri = $proto.'://'.'benno2:'.$secret.'@'.$host.':'.$port.$path;
my $UA = LWP::UserAgent->new;

my $Response = $UA->post($uri,$params);

my $return;
if ($Response->is_success) {
    $return = $Response->decoded_content;
}
else {
    print STDERR "Response status: ",$Response->status_line,"\n";
    print STDERR $Response->content,"\n";
    exit 1;
}
if ($mailid || $json) {
    # Response returned raw email
    print $return,"\n";
    exit 0;
}

# Response returned JSON data
my $JSON = JSON->new->allow_nonref;
my $data = $JSON->decode($return);

my $first    = $data->{first};
my $last     = $data->{last};
my $limit = $data->{limit};
my $found    = $data->{found};
my $results  = $data->{results};

verbose(2,"\n****** REQUEST ******");
verbose(2,"URI: $uri");
verbose(2,"Parameter:");
foreach my $param (keys %{$params}) {
    verbose(2,"    $param => $params->{$param}");
}
verbose(2,"\n****** RESPONSE *******");

my $num = 0;
foreach my $item (@{$results}) {
    print $item->{id},"\n" if ($verbose < 1 || $quiet);
    verbose(1, $item->{id}) if $verbose < 1;
    verbose(1, 'Id('.$num++.'): '.$item->{id});
    verbose(2, '  From: '.$item->{From});
    foreach my $to (@{$item->{To}}) {
        verbose(2,'  To: '.$to);
    }
    foreach my $cc (@{$item->{Cc}}) {
        verbose(2,'  Cc: '.$cc);
    }
    foreach my $bcc (@{$item->{Bcc}}) {
        verbose(2,'  Bcc: '.$bcc);
    }
    verbose(2,'  Subject: '.$item->{Subject});
    verbose(2, '  Date: '.$item->{Date});
    verbose(2, '  Attachment: '.$item->{hasAttachment});

}

if (!$num) {
    verbose(0, "No results found.");
    exit 0;
}

verbose(0, "$found mails found (first: $first, last: $last, limit: $limit)");
verbose(1, "\n### Result ##############################################################");
verbose(1, "Found: $found");
verbose(1, "Last:  $last");
verbose(1, "Limit: $limit");


### SUBS ###
### print help and exit
sub help_exit
{
    print "Usage: $0 [-h] [-V] -s <secret> [-H <hostname>] [-c <container>] [-P <port>] <-q|-i>\n";
    print "    -s <secret>         shared secret\n";
    print "    -q '<lucene query>' lucene query string or file with filter\n";
    print "                        (search header as \"HEADER-<HEADER-NAME>\")\n";
    print "    -i '<mailid>'       fetch mail with id\n";
    print "    -f '<lucene query>' lucene filter string or file with filter\n";
    print "    -c '<container>'    archive container\n";
    print "    -H <hostname>       (localhost)\n";
    print "    -P <port>           (21080)\n";
    print "    -F '<num>'          first email in response list\n";
    print "    -L '<num>'          limit response list to <num> mails\n";
    print "    -j                  dump raw JSON response\n";
    print "    -v                  verbose\n";
    print "    -D                  debug mode\n";
    print "    -Q                  quiet mode (suppress info messages)\n";
    print "\n";
    
    exit 1;
}

### print and format debug messages
sub verbose
{
    my ($level,$string) = @_;
    return if $quiet;
    if ($verbose >= $level) {
        print STDERR $string,"\n";
    }   
}


### fetch password from config file
sub fetchSecret
{
    my $sfile    = shift;
    my $bennoxml = shift;
    my $secret;

    if (open SF, $sfile) {
        $secret = <SF>;
        chomp $secret;
        close SF;
        return $secret; 
    }

    open XMLFILE, $bennoxml;
    foreach my $line (<XMLFILE>) {
        chomp $line;
        ($secret) = $line =~ m!<sharedSecret>(.+)</sharedSecret>!;
        last if $secret;
    }
    return $secret;
}


### read first line from file
sub read_first_line
{
    my $filename = shift;

    if (!open FILE, $filename) {
        print STDERR "Cannot open file $filename. $!\n";
        exit 2;
    }
    my $line = <FILE>;
    chomp $line;

    return $line;
}
