package RT::Interface::Email::OneTicketPerRequestor;

use strict;
use warnings;

use Role::Basic 'with';
with 'RT::Interface::Email::Role';

use Email::Address;
use Encode;
use RT::Interface::Email ();
use RT::Plugin;
use RT::Tickets;
use YAML::Tiny;

my %QUEUES = ();
my $plugin_self = RT::Plugin->new(name => "RT-Extension-Conservancy");
foreach my $confdir ($plugin_self->Path("etc"), $RT::LocalEtcPath, $RT::EtcPath) {
    next unless (defined($confdir) && $confdir);
    my $conf_path = "$confdir/OneTicketPerRequestor.yml";
    if (-r $conf_path) {
        %QUEUES = %{YAML::Tiny->read($conf_path)->[0]};
        last if (%QUEUES);
    }
}

# Compile the user's configuration into arguments for RT::Tickets->OrderBy.
while (my ($key, $sort_orders) = each %QUEUES) {
    if (!ref($sort_orders)) {
        $sort_orders = [($sort_orders ? $sort_orders : ())];
    }
    if (!@$sort_orders) {
        push(@$sort_orders, "Created DESC");
    }
    $QUEUES{$key} = [map {
        my ($field, $order) = split;
        $order = uc($order || "ASC");
        [FIELD => $field, ORDER => $order];
                    } @$sort_orders];
}

sub ReadHeader {
    my $headers = shift;
    my $header_name = shift;
    return Encode::decode("UTF-8", $headers->get($header_name) || "");
}

sub BeforeDecrypt {
    my %args = (
        Message       => undef,
        RawMessage    => undef,
        Actions       => undef,
        Queue         => undef,
        @_
        );

    my $queue_name = $args{Queue}->Name;
    my $sort_orders = $QUEUES{$queue_name};
    if (!defined($sort_orders)) {
        return;
    }
    elsif (RT::Interface::Email::ExtractTicketId($args{Message})) {
        return;
    }
    my $headers = $args{Message}->head();
    my @from_addrs = Email::Address->parse(ReadHeader($headers, "From"));
    my $from_address;
    foreach my $address (@from_addrs) {
        $from_address = $address->address;
        last if $from_address;
    }
    unless (defined($from_address) && $from_address) {
        $RT::Logger->debug("OTPR stopping: Message has no From address (?!)");
        return;
    }

    my $ticket_search = RT::Tickets->new($RT::SystemUser);
    $ticket_search->LimitQueue(
        OPERATOR => "=",
        VALUE => $queue_name,
        );
    $ticket_search->LimitWatcher(
        TYPE => "Requestor",
        OPERATOR => "=",
        VALUE => $from_address,
        );
    foreach my $sort_args (@$sort_orders) {
        $ticket_search->OrderBy(@$sort_args);
    }

    my $dest_ticket = $ticket_search->First;
    if (!defined($dest_ticket)) {
        return;
    }
    $RT::Logger->info(sprintf("OTPR: Redirecting email from <%s> to ticket #%s",
                              $from_address, $dest_ticket->id));
    my $subject = ReadHeader($headers, "Subject");
    $headers->replace("Subject", RT::Interface::Email::AddSubjectTag($subject, $dest_ticket->id));
}

1;