#!/usr/bin/perl -w

use strict;

# fix lib paths, some may be relative
BEGIN {
    require File::Spec;
    my @libs = (
        "lib",
        "local/lib",
        "../libcif/lib", # in case we're in -dev mode
        "../libcif-dbi/lib", # in case we're in -dev mode
        "../cif-router/lib", # in case we're in -dev mode
        "../../../lwpx-paranoidagent/lib",
        "../../../iodef-pb-simple-perl/lib",
    );
    my $bin_path;

    for my $lib (@libs) {
        unless ( File::Spec->file_name_is_absolute($lib) ) {
            unless ($bin_path) {
                if ( File::Spec->file_name_is_absolute(__FILE__) ) {
                    $bin_path = ( File::Spec->splitpath(__FILE__) )[1];
                }
                else {
                    require FindBin;
                    no warnings "once";
                    $bin_path = $FindBin::Bin;
                }
            }
            $lib = File::Spec->catfile( $bin_path, File::Spec->updir, $lib );
        }
        unshift @INC, $lib;
    }
}

use Getopt::Std;
use Cikl::Smrt;
use Config::Simple;
use Data::Dumper;
use MIME::Lite;
use Cikl qw/debug/;
use Cikl::Smrt::Handlers::ConfigBasedHandler;
use Cikl::Smrt::Handlers::Alexa;
use Cikl::Smrt::FeedParserConfig;
use Try::Tiny;

my %opts;
getopts('g:hNA:s:dC:f:r:v:p:',\%opts);
our $debug = $opts{'d'} || 0;
$debug = $opts{'v'} if($opts{'v'});

my $config_file      = $opts{'C'} || $ENV{'HOME'}.'/.cikl';
my $rules       = $opts{'r'};
my $feed        = $opts{'f'};

my $rules_dir    = '/opt/cif/etc';
my $admin       = $opts{'A'} || 'root';
my $fail_closed = $opts{'N'} || 0;
my $disable_p   = $opts{'z'};
my $goback      = $opts{'g'} || 3;

debug('fail closed: '.$fail_closed) if($debug);

die usage() if($opts{'h'} || !$rules);

sub usage {
    return <<EOF;
Usage: perl $0 -C /home/cif/.cikl -r $rules_dir/misc.cfg -f malwaredomainlist 

    -h  --help:     this message
    -f  --feed:     feed name (eg: section header in the configuration file)
    -C  --config:   specify the cikl.config file (default: $config_file)
    -r  --rules:    specify the rules file to work with (eg: etc/malwaredomains.cfg)
    -d  --debug:    debug 
    
Advanced:
    -g  --go-back:          change the default 'goback' behavior
                            (how far back in-days to process a given feed, default: $goback)
                            
    -N  --fail-closed:      error out if one of the jobs fail, mail the -A $admin
                            (default: $fail_closed)
                            
    -A  --admin:            designate an admin email address where errors should go if we fail open
                            (default: $admin)
                        
Examples:
    $0 -C /home/cif/.cikl -r $rules_dir/spyeyetracker.cfg -f binaries  
    $0 -C /home/cif/.cikl -r $rules_dir/malwaredomains.cfg -f domains  -d
    $0 -C /home/cif/.cikl -r $rules_dir/misc.cfg -f spamhaus_drop -d -p ip,malware
    $0 -r $rules_dir/misc.cfg -f spamhaus_drop -d 
EOF
}


my $ret;
my $handler;
my $err;

my $config = Config::Simple->new($config_file) 
    or die("Failed to open config file $config_file: " . $!);
my $smrt_config = $config->param(-block => 'cikl_smrt');

$goback = $goback || $smrt_config->{'goback'} || 3;
my $not_before = DateTime->now()->subtract(days => $goback);
if ($debug) {
  debug("Ignoring events prior to " . $not_before->datetime());
}

my %handler_args = (
      apikey => $smrt_config->{'apikey'},
      global_config => $config,
      proxy => $smrt_config->{proxy},
      not_before => $not_before
    );

my $handler_class = "Cikl::Smrt::Handlers::ConfigBasedHandler";
#my $handler_class = "Cikl::Smrt::Handlers::Alexa";
if ($handler_class eq "Cikl::Smrt::Handlers::ConfigBasedHandler") {
  my $feedparser_config = Cikl::Smrt::FeedParserConfig->new($rules, $feed);
  $handler_args{feedparser_config} = $feedparser_config;
}

try {
  $handler = $handler_class->new(%handler_args);
} catch {
  $err = shift;
};

if($err){
    print(usage()."\n\n");
    print('!!!ERROR!!!'."\n");
    print($err."\n\n");
    exit(-1);
}

($err,$ret) = $handler->process();
unless($err){
    debug('done...') if($debug);
    exit(0);
}

use Data::Dumper;
print '[cif-smrt] failure: '.$rules."\n";
print $err."\n";

if(!$fail_closed){
    my $msg = MIME::Lite->new(
        To      => $admin,
        Subject => 'cif-smrt failure: '.$rules.' -- '.$feed,
        Data    => "$err\nfeed: $feed"
    )->send();
    if($err =~ /contact system administrator/){
        exit(-1);
    } else {
        exit(0);
    }
} else {
    exit(-1) ;
}
