%# BEGIN BPS TAGGED BLOCK {{{
%#
%# COPYRIGHT:
%#
%# This software is Copyright (c) 1996-2025 Best Practical Solutions, LLC
%#                                          <sales@bestpractical.com>
%#
%# (Except where explicitly superseded by other copyright notices)
%#
%#
%# LICENSE:
%#
%# This work is made available to you under the terms of Version 2 of
%# the GNU General Public License. A copy of that license should have
%# been provided with this software, but in any event can be snarfed
%# from www.gnu.org.
%#
%# This work is distributed in the hope that it will be useful, but
%# WITHOUT ANY WARRANTY; without even the implied warranty of
%# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
%# General Public License for more details.
%#
%# You should have received a copy of the GNU General Public License
%# along with this program; if not, write to the Free Software
%# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
%# 02110-1301 or visit their web page on the internet at
%# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html.
%#
%#
%# CONTRIBUTION SUBMISSION POLICY:
%#
%# (The following paragraph is not intended to limit the rights granted
%# to you to modify and distribute this software under the terms of
%# the GNU General Public License and is only of importance to you if
%# you choose to contribute your changes and enhancements to the
%# community by submitting them to Best Practical Solutions, LLC.)
%#
%# By intentionally submitting any modifications, corrections or
%# derivatives to this work, or any other work intended for use with
%# Request Tracker, to Best Practical Solutions, LLC, you confirm that
%# you are the copyright holder for those contributions and you grant
%# Best Practical Solutions,  LLC a nonexclusive, worldwide, irrevocable,
%# royalty-free, perpetual, license to use, copy, create derivative
%# works based on those contributions, and sublicense and distribute
%# those contributions and any derivatives thereof.
%#
%# END BPS TAGGED BLOCK }}}
  <&| /Elements/LabeledValue, Label => loc('Topics') &>

  <input type="hidden" name="EditTopics" value="1" />
<select multiple size="10" name="Topics" class="tall selection-box">
% if (@Classes) {
%   unless ($OnlyThisClass) {
<optgroup label="Current classes (<% join(" ", map {$_->Name} @Classes) %>)">
%   }
%   $inTree->traverse(sub {
%     my $tree = shift;
%     my $topic = $tree->getNodeValue;
<option value="<% $topic->Id %>" <% exists $topics{$topic->Id} ? "selected" : "" %> >\
<% "&nbsp;" x ($tree->getDepth*5) |n %><% $topic->Name || loc("(no name)") %></option>
%   });
% }
% unless ($OnlyThisClass) {
%   my $class = $Classes[-1]->Id;
%   $otherTree->traverse(sub {
%     my $tree = shift;
%     my $topic = $tree->getNodeValue;
%     unless ($topic->ObjectId == $class) {
%       $class = $topic->ObjectId;
</optgroup>
%       my $c = RT::Class->new($session{'CurrentUser'});
%       $c->Load($topic->ObjectId);
<optgroup label="<% $c->Name %>">
%     }
<option value="<% $topic->Id %>" <% exists $topics{$topic->Id} ? "selected" : "" %> >\
<% "&nbsp;" x ($tree->getDepth*5) |n %><% $topic->Name || loc("(no name)") %></option>
%   });
</optgroup>
% }
</select>
</&>
<%INIT>
use Tree::Simple;

my $inClass = RT::Topics->new($session{'CurrentUser'});
# global topics should always be available
push @Classes,$RT::System unless grep { $_ == $RT::System } @Classes;
$inClass->LimitToObject($_) for @Classes;
$inClass->OrderByCols({FIELD => 'Name'});
my $inTree = buildTree($inClass);

my $otherClass = RT::Topics->new($session{'CurrentUser'});
if (@Classes) {
  $otherClass->Limit(FIELD => 'ObjectType', VALUE => 'RT::Class');
  for (@Classes) {
    $otherClass->Limit(FIELD => 'ObjectId', OPERATOR => '!=', VALUE => $_->Id);
  }
} else {
    $otherClass->UnLimit;
}
my $otherTree = buildTree($otherClass);

my $articleTopics = RT::ObjectTopics->new($session{'CurrentUser'});
$articleTopics->LimitToObject($ArticleObj);
my %topics;
while (my $topicObj = $articleTopics->Next) {
    $topics{$topicObj->Topic} = 1;
}
$topics{$_} = 1 for @Topics;

sub buildTree {
    my $query = shift;
    
    use Tree::Simple;
    my $tree = Tree::Simple->new(Tree::Simple->ROOT);
    my %lookup = (0 => $tree);

    my @todo;
    while (my $topic = $query->Next) {
        push @todo, $topic;
    }

    {
        my $changed = 0;
        my @work = @todo;
        @todo = ();
        for my $topic (@work) {
            if (defined $lookup{$topic->Parent}) {
                $lookup{$topic->Id} = Tree::Simple->new($topic, $lookup{$topic->Parent});
                $changed = 1;
            } else {
                push @todo, $topic;
            }
        }
        redo unless $changed == 0;
    }
    return $tree;
}

</%INIT>
<%ARGS>
$ArticleObj => RT::Article->new($session{'CurrentUser'})
@Classes => ()
@Topics => ()
$OnlyThisClass => undef
</%ARGS>
