package Parp::Mail::Deliverable;

use strict;
use warnings;

=head1 NAME

Parp::Mail::Deliverable - actions taken on the e-mail being filtered

=head1 SYNOPSIS

See L<Parp::Mail>.

=head1 DESCRIPTION

This class provides delivery methods for Parp::Mail objects.

=cut

use Parp::Config  qw(config);
use Parp::Folders qw(append_to_folder folder_substs);
use Parp::Options qw(opt delivery_mode);
use Parp::Utils   qw(diagnose);

=head1 METHODS

=cut

=head2 deliver_to_main

Marks the mail for delivery to the folder specified by
the C<main_folder> method of C<Parp::Config::User>.

=cut

sub deliver_to_main {
  my $m = shift;
  $m->deliver_to(config->main_folder, @_);
}

=head2 deliver_to_inbox($inbox)

Marks the mail for delivery to the given inbox, contained in the inbox
directory specified by the C<inbox_dir> method of
C<Parp::Config::User>.

=cut

sub deliver_to_inbox {
  my $m = shift;
  my ($inbox) = @_;
  $m->deliver_to(config->inbox($inbox), @_);
}

sub maybe_backup {
  my $m = shift;

  $m->deliver_to(config->backup_folder) if $m->{backup};
}

=head2 deliver_to($mailbox)

Marks the mail for delivery to the given mailbox.  If the mailbox is
not an absolute path, it is taken as being relative to the directory
specified by the C<mail_dir> method of C<Parp::Config::User>.

=cut

sub deliver_to {
  return if opt('wrong_class');

  my ($m, $folder) = @_;

  my $file = ($folder =~ m!^/!) ? $folder : config->mail_dir . "/$folder";
  $file = folder_substs($file);

  if (delivery_mode()) {
    append_to_folder($file, $m);
    diagnose "Delivered to $file\n";
  }
  else {
    diagnose "Would deliver to $file\n";
  }
}

sub accept_mail {
  return if opt('wrong_class');

  my $m = shift;
  my ($reason_ident, @details) = @_;

  $m->{accepted} = [ $reason_ident, @details ];

  my $text = "$reason_ident" .
             (@details ? " (@details)" : '');

  $m->header->add('X-Parp-Accepted', $text);
  diagnose "Accepted: $text\n";
}

sub ditch_mail {
  my $m = shift;
  diagnose "Delivered to /dev/null",
              @_ ? " (@_)" : '',
              "\n";
}

sub reject_junk_mail {
  return if opt('wrong_class');
  my $m = shift;
  $m->reject_mail(@_);
#  $m->{backup} = 0;
  $m->deliver_to_inbox('junk-mail');
}

sub reject_mail {
  return if opt('wrong_class');

  my $m = shift;
  my ($reason_ident, @details) = @_;

  $m->{rejected} = [ $reason_ident, @details ];

  my $text = $reason_ident .
             (@details ? " (@details)" : '') .
             "\n";

  $m->header->add('X-Parp-Rejected', $text);
  diagnose "REJECTED: $text";
}

=head2 pipe_forward($pipe_command)

Pipes the mail to the given command.  This is useful for
passing the mail on to other filter programs.

=cut

sub pipe_forward {
  return if opt('wrong_class');

  my $m = shift;
  my ($pipe_command) = @_;

  if (opt('dry_pipes') || opt('test_run')) {
    diagnose "Would pipe | $pipe_command\n";
  }
  else {
    diagnose "Piping | $pipe_command ... ";
    if (! open(PIPE, "| $pipe_command")) {
      error("Couldn't open pipe command $pipe_command: $!");
    }
    else {
      print PIPE $m->{mail}->as_mbox_string;
      close(PIPE) or error("close(| $pipe_command) failed: $!\n");
      diagnose "done.\n";
    }
  }
}

sub as_mbox_string {
  my $self = shift;
  my $text = $self->mail->as_mbox_string;
  $text =~ s/^Mail-From: /From /;
  $text =~ s/\n+$/\n\n/;
  return $text;
}

1;
