<%args>
$next
$next_for_validation => undef
$include_header      => 1
$include_page_layout => 1
$include_tabs        => 0
$ShowBar             => 1
$enable_persisting   => 1
$forbid_persisting   => {}
$form_id             => undef
$form_name           => undef
$form_classes        => undef
$self_service        => 0
$results_ref         => []
$form_config         => undef
</%args>
<%init>
use RT::Extension::FormTools;
my $content = $m->content;

$form_id   = $m->interp->apply_escapes( $form_id,   'h')
    if defined $form_id;
$form_name = $m->interp->apply_escapes( $form_name, 'h')
    if defined $form_name;

my $header_component = $self_service ? '/SelfService/Elements/Header' : '/Elements/Header';

my %cfs = map { $_ => 1} @{ $m->notes('cfs_on_page') || [] };
my %core_fields = map { $_ => 1} @{ $m->notes('core_fields_on_page') || [] };

my %request_args = %$DECODED_ARGS;

my @results;
my $real_next = delete $request_args{_form_tools_next};
if ($real_next) {
    my $queue = $m->notes('queue');
    # registered validation
    if (my $validation = $m->notes('validation')) {
        while (my ($key, $validator) = each (%$validation)) {
            if (ref($validator) eq 'CODE') {
                # no op
            }
            elsif (!ref($validator)) {
                 my $method_name = $validator;
                 $validator = RT::Extension::FormTools->can($method_name);
            }
            else {
                warn "unknown validator for $key, ignoring.";
                next;
            }

            my ($ok, $res) = $validator->($request_args{$key}, \%request_args);
            push @results, "$key: $res" unless $ok;
        }
    }

    my %labels = map { $_->{arguments}{name} => $_->{arguments}{label} }
        grep { ( $_->{comp_name} // '' ) eq 'Field' && $_->{arguments}{name} && $_->{arguments}{label} }
        map { @{ $_->{content} } } values %{ $form_config->{'formtools-pages'} };

    my ($status, @msg) = $m->comp(
        '/Elements/ValidateCustomFields',
        CustomFields    => $queue->TicketCustomFields,
        ARGSRef         => \%request_args,
        Labels          => \%labels,
    );
    unless ($status) {
        push @results, @msg;
    }

    $m->callback( CallbackName => 'AfterValidateCustomFields', ARGSRef => \%request_args, results => \@results );

    unless ( @results || ( $request_args{AddMoreAttach} && $request_args{AddMoreAttach} eq 'Add More Files' ) ) {
        # Flag to show validation passed
        $ARGS{'validation_ok'} = 1;

        $real_next = $m->caller(1)->dir_path . '/' . $real_next
            unless $real_next =~ m'^/';
        $m->subexec(
            $real_next,
            map {
                my $type = ref($_);
                ( !$type )
                    ? Encode::encode( 'UTF-8', $_, Encode::FB_PERLQQ )
                    : ( $type eq 'ARRAY' )
                    ? [ map { ref($_) ? $_ : Encode::encode( 'UTF-8', $_, Encode::FB_PERLQQ ) } @$_ ]
                    : ( $type eq 'HASH' )
                    ? { map { ref($_) ? $_ : Encode::encode( 'UTF-8', $_, Encode::FB_PERLQQ ) } %$_ }
                    : $_

            } %ARGS, %request_args
        );
        $m->abort;
    }
}

foreach my $key (keys %request_args) {
   next unless ($key =~ /CustomField-(\d+)/ );
   my $cf = $1;
   delete $request_args{$key} if ($cfs{$cf});
}

foreach my $key (keys %request_args) {
   next unless RT::Extension::FormTools::is_core_field($key);
   delete $request_args{$key} if ($core_fields{$key});
}

# Add in any @results passed in. These should not be errors,
# so they will be shown on the next page.
push @results, @{$results_ref};

$next_for_validation ||= $m->caller(1)->path;

</%init>
% if ($include_header) {
      <& $header_component, Title => $m->notes('page_title'), ShowBar => $ShowBar &>
%     # SelfService Header already calls /Elements/Tabs (which calls /Elements/PageLayout)
%     # Thus it only makes sense to display either the Tabs or the PageLayout if we
%     # are not rendering the SelfService environment.
%     if (! $self_service) {
%         if ($include_tabs) {
              <& /Elements/Tabs &>
%         } elsif ($include_page_layout) {
%             # /Elements/Tabs already unconditionally calls the PageLayout component.
%             # Thus it only makes sense to call it if we aren't "including" the tabs.
              <& /Elements/PageLayout &>
%         }
%     }
% }
% $m->callback( CallbackName => 'BeforeListActions', ARGSRef => \%ARGS );
<& /Elements/ListActions, actions => \@results &>
<div id="formtools-form-body" class="container p-4 formtools-base-style">
<form
    method="POST"
    action="<% RT->Config->Get('WebPath') . $next_for_validation %>"
    enctype="multipart/form-data"
    <% defined $form_id ? ' id="'.$form_id.'"' : '' |n %>
    <% defined $form_name ? ' name="'.$form_name.'"' : '' |n %>
    <% defined $form_classes ? ' class="'.$form_classes.'"' : '' |n %>
>
<input type="hidden" name="_form_tools_next" value="<%$next%>" />
<%$content|n%>

<%perl>
if ($enable_persisting) {
    foreach my $key (keys %request_args) {
        next if (ref $request_args{$key} && ref $request_args{$key} ne 'ARRAY');
        foreach my $val ( ref ($request_args{$key}) ? @{$request_args{$key}} : ($request_args{$key})) {
            next if $forbid_persisting->{$key};
            next if ($key eq 'user' or $key eq 'pass');
            next if $key eq 'Submit'; # No need to pass through "Next" button value
            next if $key eq 'Attach';
            next if $key eq 'AddMoreAttach';
            next if $key =~ /^(?:validation|validation_ok|next_for_validation|sc)$/;

            # ContentType is added automatically when the Content form input is built,
            # so we don't need to persist it as a hidden value. This isn't a user-set value.
            next if $key eq 'ContentType';

            # create_ticket is added automatically on the page that should run CreateTicket.
            # It is not a user-set value, so doesn't need to be persisted.
            next if $key eq 'create_ticket';

            $m->out('<input type="hidden" name="' . $key . '" value="' . $m->interp->apply_escapes( $val, 'h' ) . '" />');
        }
    }
}
</%perl>

</form>
</div>
