package Parp::Options;

=head1 NAME

Parp::Options - Parse command-line options

=head1 SYNOPSIS

  do_debugging() if opt('verbose');

=head1 DESCRIPTION

Contains routines for parsing and retrieving options set on the
command-line when parp is invoked.

=head1 ROUTINES

=cut

use strict;
use warnings;

use Carp qw(croak);
use Getopt::Std;

use base qw(Exporter);
our @EXPORT_OK = qw(usage opt delivery_mode);

my %options = (
  daemon          => 0,
  filter_files    => 0,
  kill_daemon     => 0,
  extract_friends => 0,
  test_run        => 0,
  wrong_class     => 0,
  regression_test => 0,
);

sub usage {
  warn join '', @_, "\n" if @_;

  warn <<EOF;
parp $::VERSION -- Perl Anti-spam Replacement for Procmail
(c) 1999--2001 Adam Spiers <adam\@spiers.net>

Usage:
  parp [ options ] < email
  parp [ options ] -f folder1 [ folder2 ... ]

Options:
  -d       enable recording/discarding of duplicates (by Message-Id header)
  -D<DIR>  run in daemon mode, using DIR as the incoming queue
  -e       only extract e-mail addresses and add them to friends database
  -f       operate on given files rather than as a filter
  -k       gracefully kill a running daemon
  -p       dry run for pipes - don't actually execute pipe commands
  -r       enable blacklist checking (see http://mail-abuse.org/rss/)
  -R       run in regression testing mode
  -s<NUM>  with -f, only sample a maximum of <num> messages per folder
  -t       test run - just show what would have been done
  -v       increase verbosity
  -w       only log that filter's spam detection heuristics failed on
           the supplied mails; don't do anything else
EOF

  exit 2;
}

my %long_names = (
  'd' => 'no_dups',
  'D' => 'daemon',
  'e' => 'extract_friends', 
  'f' => 'filter_files',
  'k' => 'kill_daemon',
  'p' => 'dry_pipes', 
  'r' => 'do_blacklist',
  'R' => 'regression_test',
  's' => 'sample', 
  't' => 'test_run', 
  'v' => 'verbose', 
  'w' => 'wrong_class', 
);
my %valid = reverse %long_names;

sub process {
  my %opts = ();
  getopts('edD:fhkmprRs:tvw', \%opts);
  usage() if $opts{h};

  foreach my $letter (keys %long_names) {
    $options{$long_names{$letter}} = $opts{$letter} if defined $opts{$letter};
  }

  get_input_mode();

  usage("Conflicting filter modes specified.\n")
    if (  $options{extract_friends}
        + $options{test_run}
        + $options{wrong_class}
        + $options{regression_test}
        + $options{kill_daemon}
       ) > 1;
  $options{test_run}++ if $options{extract_friends};

  usage() if -t && get_input_mode() eq 'filter';
  
  eval {
    local $SIG{__DIE__} = sub { die $_[0] }; # blegh
    require Net::DNS;
  } if $options{do_blacklist};
}

=head2 opt($option)

Returns the value of a given option.  See C<%long_names> in the source
(sorry) for valid options.

=cut

sub opt  {
  my ($opt) = @_;
  croak "No such option $opt" unless $valid{$opt};
  return $options{$opt};
}

=head2 delivery_mode

Returns true if this process will actually deliver e-mails.

=cut

sub delivery_mode {
  ! (opt('test_run')        ||
     opt('wrong_class')     ||
     opt('regression_test') ||
     opt('extract_friends'));
}

=head2 get_input_mode

Returns one of 'filter', 'files', or 'daemon', if an input mode has
been selected, otherwise false (e.g. with -k option).

=cut

{
  my $input_mode;

  sub get_input_mode {
    return $input_mode if $input_mode;

    usage("Conflicting input modes specified.\n")
      if (  ($options{daemon} && 1)
          + $options{filter_files}
          + $options{kill_daemon}
         ) > 1;
    
    $input_mode = 'filter';
    $input_mode = 'files'  if $options{filter_files};
    $input_mode = 'daemon' if $options{daemon};
    $input_mode = ''       if $options{kill_daemon};

    return $input_mode;
  }
}

1;
