%ARGS>
$TreeviewMagic => undef
$id => undef
$Query => undef
$Format => undef
$Rows => undef
$OrderBy => undef
$Order => undef
$Page => undef
$MaxDepth => 7
$ShowChildren => undef
$ShowDependencies => undef
@ShowStatus => ();
%ARGS>
<%init>
my @statuses = RT::Queue->new($session{'CurrentUser'})->StatusArray;
unless ($TreeviewMagic) {
    unless (defined $ShowChildren) {
        $ShowChildren = 1;
    }
    unless (defined $ShowDependencies) {
	$ShowDependencies = 1;
    }
    unless( @ShowStatus ) {
	@ShowStatus = qw(new open stalled);
    }
}
# {{{ Generic setup
my $title = loc('Tree view');
my $QueryString = "?".
    $m->comp(
    '/Elements/QueryString',
    Query            => $Query,
    Format           => $Format,
    Rows             => $Rows,
    OrderBy          => $OrderBy,
    Order            => $Order,
    Page             => $Page,
    MaxDepth         => $MaxDepth,
    ShowChildren     => $ShowChildren,
    ShowDependencies => $ShowDependencies,
  );
# QueryString couldn't handle array refs
$QueryString = join( '&', $QueryString,
			  map { 'ShowStatus='. $m->interp->apply_escapes($_,'u') }
			  	@ShowStatus);
# }}}
# {{{ If we load a ticket, this search is on a given ticket and we'll get the
# ticket menus instead of the tree ones
my $Ticket;
if ($id) {
    $Ticket = RT::Ticket->new( $session{'CurrentUser'} );
    $Ticket->Load($id);
    $Query = "id = $id";
}
# }}}
# {{{ Scrub the html of the format string to remove any potential nasties.
$Format = $m->comp( '/Elements/ScrubHTML', Content => ($Format||
			           $RT::DefaultSearchResultFormat));
my (@Format) =
  $m->comp( '/Elements/CollectionAsTable/ParseFormat', Format => $Format );
# Alter the format to do treeview indents.
foreach my $entry (@Format) {
    my @output;
    foreach my $item ( @{ $entry->{'output'} } ) {
        if ( $item eq '__Subject__' ) {
	    # add indent whitespaces before link
	    unshift @output, '___RT_TreeView_Indent__';
	    push @output, $item;
        }
        else {
            push @output, $item;
        }
    }
    if( lc $entry->{'attribute'} eq 'id' ) {
	for my $item ( @output ) {
	    $item =~ s/{'output'} = \@output;
}
# }}}
my $tickets = RT::Tickets->new( $session{'CurrentUser'} );
$tickets->FromSQL($Query);
$tickets->OrderBy( FIELD => $OrderBy, ORDER => $Order );
my @tickets = @{ $tickets->ItemsArrayRef || [] };
my $TopTickets = {};
$TopTickets->{ $_->id } = $_ foreach( @tickets );
my @tree;
foreach my $ticket (@tickets) {
    # If the parent ticket hasn't been invalidated by being displayed deeper...
    # recurse now and add it in
    next unless exists $TopTickets->{ $ticket->id };
    my $kids = build_subtree(
        Ticket           => $ticket,
        TopTickets       => $TopTickets,
        Depth            => 1,
        MaxDepth         => $MaxDepth,
        ShowChildren     => $ShowChildren,
        ShowDependencies => $ShowDependencies,
	ShowStatus       => \@ShowStatus,
    );
    unless( $kids && @$kids ) {
	next unless grep $_ eq $ticket->Status, @ShowStatus;
    }
    push @tree, [ $ticket, $kids ];
}
# Ok. Let's build up our tree of tickets, recursing down.
sub build_subtree {
    my %args = (
        Ticket           => undef,
        TopTickets       => undef,
        ShowChildren     => undef,
        ShowDependencies => undef,
	ShowStatus       => undef,
        Depth            => undef,
        MaxDepth         => undef,
        @_
    );
    return if ( $args{'Depth'} > $args{'MaxDepth'} );
    my @query;
    push @query, 'DependsOn = ' . $args{'Ticket'}->id
		  if ( $args{'ShowDependencies'} );
    push @query, 'MemberOf = ' . $args{'Ticket'}->id
		  if ( $args{'ShowChildren'} );
    my $deps = RT::Tickets->new( $session{'CurrentUser'} );
    $deps->FromSQL( join( ' OR ', @query ) );
    $deps->OrderBy( FIELD => $args{'OrderBy'}, ORDER => $args{'Order'} );
    my @tickets;
    while ( my $dep = $deps->Next ) {
        delete $args{'TopTickets'}->{ $dep->id };
        my $kids = undef;
        $kids = build_subtree(
	    %args,
            Ticket     => $dep,
            Depth      => $args{'Depth'} + 1,
          );
	unless( $kids && @$kids ) {
	    next unless grep $_ eq $dep->Status, @{ $args{'ShowStatus'} };
        }
        push @tickets, [ $dep, $kids ];
    }
    return ( \@tickets );
}
%init>
<& /Elements/Header, Title => $title, Refresh => $session{'tickets_refresh_interval'} &>
<& /Ticket/Elements/Tabs, 
    current_tab => "Search/Tree.html".$QueryString,
    Ticket => $Ticket,
    Title => $title,
    Format => $Format,
    Query => $Query,
    Rows => $Rows,
    OrderBy => $OrderBy,
    Order => $Order &>