package RT::Workflow::Run;

use strict;

sub import {
    my ($class, $action, $self) = @_;
    my $code = $class->can($action) or die "Cannot find $action to run";
    $::RV = $code->($self);
}

# Find all the tickets that depend on this (that this is approving)
sub AllApproved {
    my $self = shift;

    my $Ticket = $self->TicketObj;
    my @TOP    = $Ticket->AllDependedOnBy( Type => 'ticket' );
    my $links  = $Ticket->DependedOnBy;
    my $passed = 0;

    while (my $link = $links->Next) {
        my $obj = $link->BaseObj;
        next if ($obj->HasUnresolvedDependencies( Type => 'approval' ));

        if ($obj->Type eq 'ticket') {
            $obj->Comment(
                Content	=> $self->loc("Your request has been approved."),
            ) unless $T::Approved{$obj->Id}++;
            $T::Approval  = $Ticket;    # so we can access it inside templates
            $self->{TicketObj} = $obj;  # we want the original id in the token line
            $passed = 1;
        }
        elsif ($obj->Type eq 'approval') {
            $obj->SetStatus( Status => 'open', Force => 1 );

            # Approve tickets automatically if the owner no longer exist.
            if ($obj->OwnerObj->Name eq 'Nobody' or $obj->OwnerObj->Disabled) {
                $obj->SetStatus( Status => 'resolved', Force => 1 );
            }
        }
        elsif ($RT::UseCodeTickets and $obj->Type eq 'code') {
            my $code = $obj->Transactions->First->Content;
            my $rv;

            foreach my $TOP (@TOP) {
                local $@;
                $rv++ if eval $code;
                $RT::Logger->error("Cannot eval code: $@") if $@;
            }

            if ($rv or !@TOP) {
                $obj->SetStatus( Status	=> 'resolved', Force	=> 1,);
            }
            else {
                $obj->SetStatus( Status	=> 'rejected', Force	=> 1,);
            }
        }
    }

    # Now magically turn myself into a Requestor Notify object...
    require RT::Action::Notify; bless($self, 'RT::Action::Notify');
    $self->{Argument} = 'Requestor'; $self->Prepare;

    return 0; # ignore $passed;
}

sub AnyApproved {
    my $self = shift;

    return(0) unless ($self->TicketObj->Type eq 'approval');

    my $note;
    my $t = $self->TicketObj->Transactions;
    while (my $o = $t->Next) {
        $note = $o->Content . "\n" if $o->ContentObj
                and $o->Content !~ /Default Approval/;
    }

    foreach my $obj ($self->TicketObj->AllDependedOnBy( Type => 'ticket' )) {
        $obj->Comment(
            Content => $self->loc( "Your request has been approved by [_1]. Other approvals may still be pending.", # loc
                $self->TransactionObj->CreatorObj->Name,
            ) . "\n" . $self->loc( "Approver's notes: [_1]", # loc
                $note
            ),
        );
        $T::Approval = $self->TicketObj; # so we can access it inside templates
        $self->{TicketObj} = $obj;  # we want the original id in the token line
    }

    # Now magically turn myself into a Requestor Notify object...
    require RT::Action::Notify; bless($self, 'RT::Action::Notify');
    $T::Note = $note; $self->{Argument} = 'Requestor'; $self->Prepare;

    return 1;
}

sub Rejected {
    my $self = shift;

    return(0) unless (
        lc($self->TransactionObj->NewValue) eq "rejected" or
        lc($self->TransactionObj->NewValue) eq "deleted"
    );

    my $note;
    my $t = $self->TicketObj->Transactions;
    while (my $o = $t->Next) {
        $note = $o->Content . "\n" if $o->ContentObj
                and $o->Content !~ /Default Approval/;
    }

    my $rejected = 0;
    my $links = $self->TicketObj->DependedOnBy;
    foreach my $link (@{ $links->ItemsArrayRef }) {
        my $obj = $link->BaseObj;
        if ($obj->QueueObj->IsActiveStatus($obj->Status)) {
            if ($obj->Type eq 'ticket') {
                $obj->Comment(
                    Content => $self->loc( "Your request was rejected by [_1].", # loc
                        $self->TransactionObj->CreatorObj->Name,
                    ) . "\n" . $self->loc( "Approver's notes: [_1]", # loc
                        $note
                    ),
                ) unless $self->TransactionObj->CreatorObj->Name eq 'RT_System';
                $obj->SetStatus(
                    Status	=> 'rejected',
                    Force	=> 1,
                );

                $T::Approval = $self->TicketObj; # so we can access it inside templates
                $self->{TicketObj} = $obj;  # we want the original id in the token line
                $rejected = 1;
            }
            else {
                $obj->SetStatus(
                    Status	=> 'deleted',
                    Force	=> 1,
                );
            }
        }
    }

    $links = $self->TicketObj->DependsOn;
    foreach my $link (@{ $links->ItemsArrayRef }) {
        my $obj = $link->TargetObj;
        if ($obj->QueueObj->IsActiveStatus($obj->Status)) {
            $obj->SetStatus(
                Status	=> 'deleted',
                Force	=> 1,
            );
        }
    }

    # Now magically turn myself into a Requestor Notify object...
    require RT::Action::Notify; bless($self, 'RT::Action::Notify');
    $T::Note = $note; $self->{Argument} = 'Requestor,ResolvedApprovers'; $self->Prepare;

    return $rejected;
    # ------------------------------------------------------------------- #
}

eval "require RT::Workflow::Run_Vendor";
die $@ if ($@ && $@ !~ qr{^Can't locate RT/Workflow/Run_Vendor.pm});
eval "require RT::Workflow::Run_Local";
die $@ if ($@ && $@ !~ qr{^Can't locate RT/Workflow/Run_Local.pm});

1;
