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

my %opts;
getopts('hjvDIMb:c:e: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/benno.xml');
my $query     = $opts{q};
my $mailid    = $opts{i};
my $json      = $opts{j};
my $begin     = $opts{b} || 0;
my $limit     = $opts{l} || 20;
my $filter    = $opts{f} || '*'; 
my $host      = $opts{H} || 'localhost';
my $port      = $opts{P} || 21080;
my $DEBUG     = $opts{v};
my $p_mailid  = $opts{M};

$DEBUG        = 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'   => $begin,
                '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};

print "Found $found emails.\n" unless ($DEBUG || $p_mailid || $mailid);


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

print_debug(1, "Found: $found");
print_debug(1, "First: $first");
print_debug(1, "Last: $last");
print_debug(1, "Limit: $limit");

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


### 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 "    -b '<num>'          begin with email number in response list\n";
    print "    -l '<num>'          limit respones to num\n";
    print "    -c '<container>'    archive container\n";
    print "    -H <hostname>       (localhost)\n";
    print "    -P <port>           (8080)\n";
    print "    -j                  dump raw JSON response\n";
    print "    -M                  print results as list of mail ids\n";
    print "    -v                  verbose\n";
    print "    -D                  debug mode\n";
    print "\n";
    
    exit 1;
}

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


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

    open XMLFILE, $bennoxml;
    my $secret;
    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;
}
