# --
# Modified version of the work: Copyright (C) 2006-2023 KIX Service Software GmbH, https://www.kixdesk.com
# based on the original work of:
# Copyright (C) 2001-2023 OTRS AG, https://otrs.com/
# --
# This software comes with ABSOLUTELY NO WARRANTY. For details, see
# the enclosed file LICENSE for license information (AGPL). If you
# did not receive this file, see https://www.gnu.org/licenses/agpl.txt.
# --

package Kernel::Modules::AgentTicketProcess;

use strict;
use warnings;

use Kernel::Language qw(Translatable);
use Kernel::System::VariableCheck qw(:all);

our $ObjectManagerDisabled = 1;

sub new {
    my ( $Type, %Param ) = @_;

    # allocate new hash for object
    my $Self = {%Param};
    bless $Self, $Type;

    # global config hash for id dissolution
    $Self->{NameToID} = {
        Title           => 'Title',
        State           => 'StateID',
        StateID         => 'StateID',
        Lock            => 'LockID',
        LockID          => 'LockID',
        Priority        => 'PriorityID',
        PriorityID      => 'PriorityID',
        Queue           => 'QueueID',
        QueueID         => 'QueueID',
        Customer        => 'CustomerID',
        CustomerID      => 'CustomerID',
        CustomerNo      => 'CustomerID',
        CustomerUserID  => 'CustomerUserID',
        Owner           => 'OwnerID',
        OwnerID         => 'OwnerID',
        Type            => 'TypeID',
        TypeID          => 'TypeID',
        SLA             => 'SLAID',
        SLAID           => 'SLAID',
        Service         => 'ServiceID',
        ServiceID       => 'ServiceID',
        Responsible     => 'ResponsibleID',
        ResponsibleID   => 'ResponsibleID',
        PendingTime     => 'PendingTime',
        Article         => 'Article',
        HorizontalLine  => 'horizontalline',
        HorizontalLine1 => 'horizontalline',
        HorizontalLine2 => 'horizontalline',
        HorizontalLine3 => 'horizontalline',
        HorizontalLine4 => 'horizontalline',
        HorizontalLine5 => 'horizontalline',
        HorizontalLine6 => 'horizontalline',
        HorizontalLine7 => 'horizontalline',
        HorizontalLine8 => 'horizontalline',
        HorizontalLine9 => 'horizontalline',
    };

    return $Self;
}

sub Run {
    my ( $Self, %Param ) = @_;

    # get param object
    my $ParamObject = $Kernel::OM->Get('Kernel::System::Web::Request');

    my $TicketID               = $ParamObject->GetParam( Param => 'TicketID' );
    my $ActivityDialogEntityID = $ParamObject->GetParam( Param => 'ActivityDialogEntityID' );
    my $ActivityDialogHashRef;

    # get needed objects
    my $ActivityDialogObject = $Kernel::OM->Get('Kernel::System::ProcessManagement::ActivityDialog');
    my $LayoutObject         = $Kernel::OM->Get('Kernel::Output::HTML::Layout');
    my $TicketObject         = $Kernel::OM->Get('Kernel::System::Ticket');

    if ($TicketID) {

        # check if there is a configured required permission
        # for the ActivityDialog (if there is one)
        my $ActivityDialogPermission = 'rw';
        if ($ActivityDialogEntityID) {
            $ActivityDialogHashRef = $ActivityDialogObject->ActivityDialogGet(
                ActivityDialogEntityID => $ActivityDialogEntityID,
                Interface              => 'AgentInterface',
            );

            if ( !IsHashRefWithData($ActivityDialogHashRef) ) {
                return $LayoutObject->ErrorScreen(
                    Message => $LayoutObject->{LanguageObject}->Translate(
                        'Couldn\'t get ActivityDialogEntityID "%s"!',
                        $ActivityDialogEntityID,
                    ),
                    Comment => Translatable('Please contact the administrator.'),
                );
            }

            if ( $ActivityDialogHashRef->{Permission} ) {
                $ActivityDialogPermission = $ActivityDialogHashRef->{Permission};
            }
        }

        # check permissions
        my $Access = $TicketObject->TicketPermission(
            Type     => $ActivityDialogPermission,
            TicketID => $Self->{TicketID},
            UserID   => $Self->{UserID}
        );

        # error screen, don't show ticket
        if ( !$Access ) {
            return $LayoutObject->NoPermission(
                Message =>
                    $LayoutObject->{LanguageObject}->Translate( 'You need %s permissions!', $ActivityDialogPermission ),
                WithHeader => 'yes',
            );
        }

        # get ACL restrictions
        my %PossibleActions = ( 1 => $Self->{Action} );

        my $ACL = $TicketObject->TicketAcl(
            Data          => \%PossibleActions,
            Action        => $Self->{Action},
            TicketID      => $Self->{TicketID},
            ReturnType    => 'Action',
            ReturnSubType => '-',
            UserID        => $Self->{UserID},
        );
        my %AclAction = $TicketObject->TicketAclActionData();

        # check if ACL restrictions exist
        if ( $ACL || IsHashRefWithData( \%AclAction ) ) {

            my %AclActionLookup = reverse %AclAction;

            # show error screen if ACL prohibits this action
            if ( !$AclActionLookup{ $Self->{Action} } ) {
                return $LayoutObject->NoPermission( WithHeader => 'yes' );
            }
        }

        if ( IsHashRefWithData($ActivityDialogHashRef) ) {

            # check if it's already locked by somebody else
            if ( $ActivityDialogHashRef->{RequiredLock} ) {

                if ( $TicketObject->TicketLockGet( TicketID => $TicketID ) ) {
                    my $AccessOk = $TicketObject->OwnerCheck(
                        TicketID => $TicketID,
                        OwnerID  => $Self->{UserID},
                    );
                    if ( !$AccessOk ) {
                        my $Output = $LayoutObject->Header(
                            Type => 'Small',
                        );
                        $Output .= $LayoutObject->Warning(
                            Message => Translatable('Sorry, you need to be the ticket owner to perform this action.'),
                            Comment => Translatable('Please change the owner first.'),
                        );
                        $Output .= $LayoutObject->Footer(
                            Type => 'Small',
                        );
                        return $Output;
                    }
                }
                else {

                    # set lock
                    $TicketObject->TicketLockSet(
                        TicketID => $TicketID,
                        Lock     => 'lock',
                        UserID   => $Self->{UserID},
                    );

                    # set user id
                    $TicketObject->TicketOwnerSet(
                        TicketID  => $TicketID,
                        UserID    => $Self->{UserID},
                        NewUserID => $Self->{UserID},
                    );

                    # reload the parent window to show the updated lock state
                    $Param{ParentReload} = 1;

                    # show lock state link
                    $Param{RenderLocked} = 1;

                    my $TicketNumber = $TicketObject->TicketNumberLookup(
                        TicketID => $TicketID,
                        UserID   => $Self->{UserID},
                    );

                    # notify the agent that the ticket was locked
                    push @{ $Param{Notify} }, {
                        Priority => 'Notice',
                        Data     => "$TicketNumber: " . $LayoutObject->{LanguageObject}->Translate("Ticket locked."),
                    };
                }
            }

            my $PossibleActivityDialogs = { 1 => $ActivityDialogEntityID };

            # get ACL restrictions
            $ACL = $TicketObject->TicketAcl(
                Data                   => $PossibleActivityDialogs,
                ActivityDialogEntityID => $ActivityDialogEntityID,
                TicketID               => $TicketID,
                ReturnType             => 'ActivityDialog',
                ReturnSubType          => '-',
                Action                 => $Self->{Action},
                UserID                 => $Self->{UserID},
            );

            if ($ACL) {
                %{$PossibleActivityDialogs} = $TicketObject->TicketAclData();
            }

            # check if ACL restrictions exist
            if ( !IsHashRefWithData($PossibleActivityDialogs) ) {
                return $LayoutObject->NoPermission( WithHeader => 'yes' );
            }
        }
    }

    # load KIXSidebar
    $Param{KIXSidebarContent} = $LayoutObject->AgentKIXSidebar(%Param);

    # list only Active processes by default
    my @ProcessStates = ('Active');

    # set IsMainWindow, IsAjaxRequest, IsProcessEnroll for proper error responses, screen display
    # and process list
    $Self->{IsMainWindow}    = $ParamObject->GetParam( Param => 'IsMainWindow' )    || '';
    $Self->{IsAjaxRequest}   = $ParamObject->GetParam( Param => 'IsAjaxRequest' )   || '';
    $Self->{IsProcessEnroll} = $ParamObject->GetParam( Param => 'IsProcessEnroll' ) || '';

    # fetch also FadeAway processes to continue working with existing tickets, but not to start new
    #    ones
    if ( !$Self->{IsMainWindow} && $Self->{Subaction} ) {
        push @ProcessStates, 'FadeAway'
    }

    # create process object
    $Kernel::OM->ObjectParamAdd(
        'Kernel::System::ProcessManagement::Process' => {
            ActivityObject         => $Kernel::OM->Get('Kernel::System::ProcessManagement::Activity'),
            ActivityDialogObject   => $ActivityDialogObject,
            TransitionObject       => $Kernel::OM->Get('Kernel::System::ProcessManagement::Transition'),
            TransitionActionObject => $Kernel::OM->Get('Kernel::System::ProcessManagement::TransitionAction'),
            }
    );
    my $ProcessObject = $Kernel::OM->Get('Kernel::System::ProcessManagement::Process');

    # get the list of processes that an agent can start
    my $ProcessList = $ProcessObject->ProcessList(
        ProcessState => \@ProcessStates,
        Interface    => ['AgentInterface'],
    );

    # also get the list of processes initiated by customers, as an activity dialog might be
    # configured for the agent interface
    my $FollowupProcessList = $ProcessObject->ProcessList(
        ProcessState => \@ProcessStates,
        Interface    => [ 'AgentInterface', 'CustomerInterface' ],
    );

    my $ProcessEntityID = $ParamObject->GetParam( Param => 'ProcessEntityID' );

    if ( !IsHashRefWithData($ProcessList) && !IsHashRefWithData($FollowupProcessList) ) {
        return $LayoutObject->ErrorScreen(
            Message => Translatable('No Process configured!'),
            Comment => Translatable('Please contact the administrator.'),
        );
    }

    # prepare process list for ACLs, use only entities instead of names, convert from
    #   P1 => Name to P1 => P1. As ACLs should work only against entities
    my %ProcessListACL = map { $_ => $_ } sort keys %{$ProcessList};

    # validate the ProcessList with stored ACLs
    my $ACL = $TicketObject->TicketAcl(
        ReturnType    => 'Process',
        ReturnSubType => '-',
        Data          => \%ProcessListACL,
        Action        => $Self->{Action},
        UserID        => $Self->{UserID},
        TicketID      => $TicketID,
    );

    if ( IsHashRefWithData($ProcessList) && $ACL ) {

        # get ACL results
        my %ACLData = $TicketObject->TicketAclData();

        # recover process names
        my %ReducedProcessList = map { $_ => $ProcessList->{$_} } sort keys %ACLData;

        # replace original process list with the reduced one
        $ProcessList = \%ReducedProcessList;
    }

    # get form id
    $Self->{FormID} = $ParamObject->GetParam( Param => 'FormID' );

    # create form id
    if ( !$Self->{FormID} ) {
        $Self->{FormID} = $Kernel::OM->Get('Kernel::System::Web::UploadCache')->FormIDCreate();
    }

    # if we have no subaction display the process list to start a new one
    if ( !$Self->{Subaction} ) {

        # to display the process list is mandatory to have processes that agent can start
        if ( !IsHashRefWithData($ProcessList) ) {
            return $LayoutObject->ErrorScreen(
                Message => Translatable('No Process configured!'),
                Comment => Translatable('Please contact the administrator.'),
            );
        }

        # get process id (if any, a process should be pre-selected)
        $Param{ProcessID} = $ParamObject->GetParam( Param => 'ID' );
        if ( $Param{ProcessID} ) {
            $Param{PreSelectProcess} = 1;
        }

        return $Self->_DisplayProcessList(
            %Param,
            ProcessList     => $ProcessList,
            ProcessEntityID => $ProcessEntityID,
            TicketID        => $TicketID,
        );
    }

    # check if the selected process from the list is valid, prevent tamper with process selection
    #    list (not existing, invalid an fade away processes must not be able to start a new process
    #    ticket)
    elsif (
        $Self->{Subaction} eq 'DisplayActivityDialogAJAX'
        && !$ProcessList->{$ProcessEntityID}
        && $Self->{IsMainWindow}
    ) {

        # translate the error message (as it will be injected in the HTML)
        my $ErrorMessage = $LayoutObject->{LanguageObject}->Translate("The selected process is invalid!");

        # return a predefined HTML structure as the AJAX call is expecting and HTML response
        return $LayoutObject->Attachment(
            ContentType => 'text/html; charset=' . $LayoutObject->{Charset},
            Content     => '<div class="ServerError" data-message="' . $ErrorMessage . '"></div>',
            Type        => 'inline',
            NoCache     => 1,
        );
    }

    # if invalid process is detected on a ActivityDilog popup screen show an error message
    elsif (
        $Self->{Subaction} eq 'DisplayActivityDialog'
        && !$FollowupProcessList->{$ProcessEntityID}
        && !$Self->{IsMainWindow}
    ) {
        $LayoutObject->FatalError(
            Message => $LayoutObject->{LanguageObject}->Translate( 'Process %s is invalid!', $ProcessEntityID ),
            Comment => Translatable('Please contact the administrator.'),
        );
    }

    # Get the necessary parameters
    # collects a mixture of present values bottom to top:
    # SysConfig DefaultValues, ActivityDialog DefaultValues, TicketValues, SubmittedValues
    # including ActivityDialogEntityID and ProcessEntityID
    # is used for:
    # - Parameter checking before storing
    # - will be used for ACL checking later on
    my $GetParam = $Self->_GetParam(
        ProcessEntityID => $ProcessEntityID,
    );

    if ( $Self->{Subaction} eq 'StoreActivityDialog' && $ProcessEntityID ) {
        $LayoutObject->ChallengeTokenCheck();

        return $Self->_StoreActivityDialog(
            %Param,
            ProcessName     => $ProcessList->{$ProcessEntityID},
            ProcessEntityID => $ProcessEntityID,
            GetParam        => $GetParam,
        );
    }
    if ( $Self->{Subaction} eq 'DisplayActivityDialog' && $ProcessEntityID ) {

        return $Self->_OutputActivityDialog(
            %Param,
            ProcessEntityID => $ProcessEntityID,
            GetParam        => $GetParam,
        );
    }
    if ( $Self->{Subaction} eq 'DisplayActivityDialogAJAX' && $ProcessEntityID ) {

        my $ActivityDialogHTML = $Self->_OutputActivityDialog(
            %Param,
            ProcessEntityID => $ProcessEntityID,
            GetParam        => $GetParam,
        );
        return $LayoutObject->Attachment(
            ContentType => 'text/html; charset=' . $LayoutObject->{Charset},
            Content     => $ActivityDialogHTML,
            Type        => 'inline',
            NoCache     => 1,
        );

    }
    elsif ( $Self->{Subaction} eq 'AJAXUpdate' ) {

        return $Self->_RenderAjax(
            %Param,
            ProcessEntityID => $ProcessEntityID,
            GetParam        => $GetParam,
        );
    }
    return $LayoutObject->ErrorScreen(
        Message => Translatable('Subaction is invalid!'),
        Comment => Translatable('Please contact the administrator.'),
    );
}

sub _RenderAjax {
    my ( $Self, %Param ) = @_;

    # get needed object
    my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout');
    my $ConfigObject = $Kernel::OM->Get('Kernel::Config');

    for my $Needed (qw(ProcessEntityID)) {
        if ( !$Param{$Needed} ) {
            $LayoutObject->FatalError(
                Message => $LayoutObject->{LanguageObject}
                    ->Translate( 'Parameter %s is missing in %s.', $Needed, '_RenderAjax' ),
            );
        }
    }
    my $ActivityDialogEntityID = $Param{GetParam}{ActivityDialogEntityID};
    if ( !$ActivityDialogEntityID ) {
        $LayoutObject->FatalError(
            Message => $LayoutObject->{LanguageObject}
                ->Translate( 'Parameter %s is missing in %s.', 'ActivityDialogEntityID', '_RenderAjax' ),
        );
    }
    my $ActivityDialog = $Kernel::OM->Get('Kernel::System::ProcessManagement::ActivityDialog')->ActivityDialogGet(
        ActivityDialogEntityID => $ActivityDialogEntityID,
        Interface              => 'AgentInterface',
    );

    if ( !IsHashRefWithData($ActivityDialog) ) {
        $LayoutObject->FatalError(
            Message => $LayoutObject->{LanguageObject}->Translate(
                'No ActivityDialog configured for %s in _RenderAjax!',
                $ActivityDialogEntityID,
            ),
        );
    }

    # get list type
    my $TreeView = 0;
    if ( $ConfigObject->Get('Ticket::Frontend::ListType') eq 'tree' ) {
        $TreeView = 1;
    }

    my %FieldsProcessed;
    my @JSONCollector;
    my $Services;

    # All submitted DynamicFields
    # get dynamic field values form http request
    my %DynamicFieldValues;

    # get needed object
    my $ParamObject               = $Kernel::OM->Get('Kernel::System::Web::Request');
    my $DynamicFieldBackendObject = $Kernel::OM->Get('Kernel::System::DynamicField::Backend');

    # cycle trough the activated Dynamic Fields for this screen
    DYNAMICFIELD:
    for my $DynamicFieldConfig ( @{ $Self->{DynamicField} } ) {

        next DYNAMICFIELD if !IsHashRefWithData($DynamicFieldConfig);

        # extract the dynamic field value form the web request
        $DynamicFieldValues{ $DynamicFieldConfig->{Name} } = $DynamicFieldBackendObject->EditFieldValueGet(
            DynamicFieldConfig => $DynamicFieldConfig,
            ParamObject        => $ParamObject,
            LayoutObject       => $LayoutObject,
        );
    }

    # convert dynamic field values into a structure for ACLs
    my %DynamicFieldCheckParam;
    DYNAMICFIELD:
    for my $DynamicFieldItem ( sort keys %DynamicFieldValues ) {
        next DYNAMICFIELD if !$DynamicFieldItem;
        next DYNAMICFIELD if !defined $DynamicFieldValues{$DynamicFieldItem};

        $DynamicFieldCheckParam{ 'DynamicField_' . $DynamicFieldItem } = $DynamicFieldValues{$DynamicFieldItem};
    }
    $Param{GetParam}->{DynamicField} = \%DynamicFieldCheckParam;

    # run acl to prepare TicketAclFormData
    my $ACL = $Kernel::OM->Get('Kernel::System::Ticket')->TicketAcl(
        %{ $Param{GetParam} },
        Action        => $Self->{Action},
        ReturnType    => 'Ticket',
        ReturnSubType => '-',
        Data          => {},
        UserID        => $Self->{UserID},
    );

    # update 'Shown' for $Self->{DynamicField}
    $Self->_GetShownDynamicFields();

    my %DynamicFieldHTML;
    my $AJAXUpdatableFields = $Self->_GetAJAXUpdatableFields(
        ActivityDialogFields => $ActivityDialog->{Fields},
    );

    # Get the activity dialog's Submit Param's or Config Params
    DIALOGFIELD:
    for my $CurrentField ( @{ $ActivityDialog->{FieldOrder} } ) {

        # Skip if we're working on a field that was already done with or without ID
        if (
            $Self->{NameToID}{$CurrentField}
            && $FieldsProcessed{ $Self->{NameToID}{$CurrentField} }
        ) {
            next DIALOGFIELD;
        }

        if ( $CurrentField =~ m{^DynamicField_(.*)}xms ) {
            my $DynamicFieldName = $1;

            my $DynamicFieldConfig = ( grep { $_->{Name} eq $DynamicFieldName } @{ $Self->{DynamicField} } )[0];

            next DIALOGFIELD if !$DynamicFieldConfig->{Shown};

            next DIALOGFIELD if !IsHashRefWithData($DynamicFieldConfig);

            $DynamicFieldHTML{ $DynamicFieldConfig->{Name} } = $DynamicFieldBackendObject->EditFieldRender(
                DynamicFieldConfig => $DynamicFieldConfig,
                LayoutObject       => $LayoutObject,
                ParamObject        => $ParamObject,
                AJAXUpdate         => 1,
                UseDefaultValue    => 1,
                UpdatableFields    => $AJAXUpdatableFields,
            );

            my $IsACLReducible = $DynamicFieldBackendObject->HasBehavior(
                DynamicFieldConfig => $DynamicFieldConfig,
                Behavior           => 'IsACLReducible',
            );
            next DIALOGFIELD if !$IsACLReducible;

            my $PossibleValues = $DynamicFieldBackendObject->PossibleValuesGet(
                DynamicFieldConfig => $DynamicFieldConfig,
            );

            # convert possible values key => value to key => key for ACLs using a Hash slice
            my %AclData = %{$PossibleValues};
            @AclData{ keys %AclData } = keys %AclData;

            # get ticket object
            my $TicketObject = $Kernel::OM->Get('Kernel::System::Ticket');

            # set possible values filter from ACLs
            $ACL = $TicketObject->TicketAcl(
                %{ $Param{GetParam} },
                ReturnType    => 'Ticket',
                ReturnSubType => 'DynamicField_' . $DynamicFieldConfig->{Name},
                Data          => \%AclData,
                Action        => $Self->{Action},
                UserID        => $Self->{UserID},
            );

            if ($ACL) {
                my %Filter = $TicketObject->TicketAclData();

                # convert Filer key => key back to key => value using map
                %{$PossibleValues} = map { $_ => $PossibleValues->{$_} } keys %Filter;
            }

            my $DataValues = $DynamicFieldBackendObject->BuildSelectionDataGet(
                DynamicFieldConfig => $DynamicFieldConfig,
                PossibleValues     => $PossibleValues,
                Value              => $DynamicFieldValues{ $DynamicFieldConfig->{Name} },
            ) || $PossibleValues;

            # add dynamic field to the JSONCollector
            push(
                @JSONCollector,
                {
                    Name        => 'DynamicField_' . $DynamicFieldConfig->{Name},
                    Data        => $DataValues,
                    SelectedID  => $DynamicFieldValues{ $DynamicFieldConfig->{Name} } // $DynamicFieldConfig->{Config}->{DefaultValue},
                    Translation => $DynamicFieldConfig->{Config}->{TranslatableValues} || 0,
                    Max         => 100,
                }
            );
        }
        elsif ( $Self->{NameToID}{$CurrentField} eq 'OwnerID' ) {
            next DIALOGFIELD if $FieldsProcessed{ $Self->{NameToID}{$CurrentField} };

            my $Data = $Self->_GetOwners(
                %{ $Param{GetParam} },
            );

            my $PossibleNone = 1;
            if ( $ActivityDialog->{Fields}->{$CurrentField}->{Display} == 2 ) {
                $PossibleNone = 0;
            }

            # add Owner to the JSONCollector
            push(
                @JSONCollector,
                {
                    Name         => $Self->{NameToID}{$CurrentField},
                    Data         => $Data,
                    SelectedID   => $Param{GetParam}{ $Self->{NameToID}{$CurrentField} },
                    PossibleNone => $PossibleNone,
                    Translation  => 0,
                    Max          => 100,
                },
            );
            $FieldsProcessed{ $Self->{NameToID}{$CurrentField} } = 1;
        }
        elsif ( $Self->{NameToID}{$CurrentField} eq 'ResponsibleID' ) {
            next DIALOGFIELD if $FieldsProcessed{ $Self->{NameToID}{$CurrentField} };

            my $Data = $Self->_GetResponsibles(
                %{ $Param{GetParam} },
            );

            my $PossibleNone = 1;
            if ( $ActivityDialog->{Fields}->{$CurrentField}->{Display} == 2 ) {
                $PossibleNone = 0;
            }

            # add Responsible to the JSONCollector
            push(
                @JSONCollector,
                {
                    Name         => $Self->{NameToID}{$CurrentField},
                    Data         => $Data,
                    SelectedID   => $Param{GetParam}{ $Self->{NameToID}{$CurrentField} },
                    PossibleNone => $PossibleNone,
                    Translation  => 0,
                    Max          => 100,
                },
            );
            $FieldsProcessed{ $Self->{NameToID}{$CurrentField} } = 1;
        }
        elsif ( $Self->{NameToID}{$CurrentField} eq 'QueueID' ) {
            next DIALOGFIELD if $FieldsProcessed{ $Self->{NameToID}{$CurrentField} };

            my $Data = $Self->_GetQueues(
                %{ $Param{GetParam} },
            );

            # add Queue to the JSONCollector
            push(
                @JSONCollector,
                {
                    Name         => $Self->{NameToID}{$CurrentField},
                    Data         => $Data,
                    SelectedID   => $Param{GetParam}{ $Self->{NameToID}{$CurrentField} },
                    PossibleNone => 1,
                    Translation  => 0,
                    TreeView     => $TreeView,
                    Max          => 100,
                },
            );
            $FieldsProcessed{ $Self->{NameToID}{$CurrentField} } = 1;
        }

        elsif ( $Self->{NameToID}{$CurrentField} eq 'StateID' ) {
            next DIALOGFIELD if $FieldsProcessed{ $Self->{NameToID}{$CurrentField} };

            my $Data = $Self->_GetStates(
                %{ $Param{GetParam} },
            );

            # add State to the JSONCollector
            push(
                @JSONCollector,
                {
                    Name        => 'StateID',
                    Data        => $Data,
                    SelectedID  => $Param{GetParam}{ $Self->{NameToID}{$CurrentField} },
                    Translation => 1,
                    Max         => 100,
                },
            );
            $FieldsProcessed{ $Self->{NameToID}{$CurrentField} } = 1;
        }
        elsif ( $Self->{NameToID}{$CurrentField} eq 'PriorityID' ) {
            next DIALOGFIELD if $FieldsProcessed{ $Self->{NameToID}{$CurrentField} };

            my $Data = $Self->_GetPriorities(
                %{ $Param{GetParam} },
            );
# ---
# ITSMIncidentProblemManagement
# ---
            # check if priority needs to be recalculated
            if (
                (
                    $Param{GetParam}->{ElementChanged} eq 'ServiceID'
                    || $Param{GetParam}->{ElementChanged} eq 'DynamicField_ITSMImpact'
                )
                && $Param{GetParam}->{ServiceID}
                && $Param{GetParam}->{DynamicField_ITSMImpact}
                && $Param{GetParam}->{DynamicField_ITSMCriticality}
            ) {

                # calculate priority from the CIP matrix
                my $PriorityIDFromImpact = $Kernel::OM->Get('Kernel::System::ITSMCIPAllocate')->PriorityAllocationGet(
                    Criticality => $Param{GetParam}->{DynamicField_ITSMCriticality},
                    Impact      => $Param{GetParam}->{DynamicField_ITSMImpact},
                );

                # add Priority to the JSONCollector
                push(
                    @JSONCollector,
                    {
                        Name        => $Self->{NameToID}{$CurrentField},
                        Data        => $Data,
                        SelectedID  => $PriorityIDFromImpact,
                        Translation => 1,
                        Max         => 100,
                    },
                );
                $FieldsProcessed{ $Self->{NameToID}{$CurrentField} } = 1;

                next DIALOGFIELD;
            }
# ---

            # add Priority to the JSONCollector
            push(
                @JSONCollector,
                {
                    Name        => $Self->{NameToID}{$CurrentField},
                    Data        => $Data,
                    SelectedID  => $Param{GetParam}{ $Self->{NameToID}{$CurrentField} },
                    Translation => 1,
                    Max         => 100,
                },
            );
            $FieldsProcessed{ $Self->{NameToID}{$CurrentField} } = 1;
        }
        elsif ( $Self->{NameToID}{$CurrentField} eq 'ServiceID' ) {
            next DIALOGFIELD if $FieldsProcessed{ $Self->{NameToID}{$CurrentField} };

            my $Data = $Self->_GetServices(
                %{ $Param{GetParam} },
            );
            $Services = $Data;

            # add Service to the JSONCollector (Use ServiceID from web request)
            push(
                @JSONCollector,
                {
                    Name         => $Self->{NameToID}{$CurrentField},
                    Data         => $Data,
                    SelectedID   => $ParamObject->GetParam( Param => 'ServiceID' ) || '',
                    PossibleNone => 1,
                    Translation  => $ConfigObject->Get('Ticket::ServiceTranslation') || 0,
                    TreeView     => $TreeView,
                    Max          => 100,
                },
            );
            $FieldsProcessed{ $Self->{NameToID}{$CurrentField} } = 1;
        }
        elsif ( $Self->{NameToID}{$CurrentField} eq 'SLAID' ) {
            next DIALOGFIELD if $FieldsProcessed{ $Self->{NameToID}{$CurrentField} };

            # if SLA is render before service (by it order in the fields) it needs to create
            # the service list
            if ( !IsHashRefWithData($Services) ) {
                $Services = $Self->_GetServices(
                    %{ $Param{GetParam} },
                );
            }

            my $Data = $Self->_GetSLAs(
                %{ $Param{GetParam} },
                Services  => $Services,
                ServiceID => $ParamObject->GetParam( Param => 'ServiceID' ) || '',
            );

            # add SLA to the JSONCollector (Use SelectedID from web request)
            push(
                @JSONCollector,
                {
                    Name         => $Self->{NameToID}{$CurrentField},
                    Data         => $Data,
                    SelectedID   => $ParamObject->GetParam( Param => 'SLAID' ) || '',
                    PossibleNone => 1,
                    Translation  => $ConfigObject->Get('Ticket::SLATranslation') || 0,
                    Max          => 100,
                },
            );
            $FieldsProcessed{ $Self->{NameToID}{$CurrentField} } = 1;
        }
        elsif ( $Self->{NameToID}{$CurrentField} eq 'TypeID' ) {
            next DIALOGFIELD if $FieldsProcessed{ $Self->{NameToID}{$CurrentField} };

            my $Data = $Self->_GetTypes(
                %{ $Param{GetParam} },
            );

            # Add Type to the JSONCollector (Use SelectedID from web request).
            push(
                @JSONCollector,
                {
                    Name         => $Self->{NameToID}{$CurrentField},
                    Data         => $Data,
                    SelectedID   => $ParamObject->GetParam( Param => 'TypeID' ) || '',
                    PossibleNone => 1,
                    Translation  => 0,
                    Max          => 100,
                },
            );
            $FieldsProcessed{ $Self->{NameToID}{$CurrentField} } = 1;
        }
    }

    my %Output;
    DYNAMICFIELD:
    for my $DynamicFieldConfig ( @{ $Self->{DynamicField} } ) {
        if ( $DynamicFieldHTML{ $DynamicFieldConfig->{Name} } ) {

            $Output{ ( "DynamicField_" . $DynamicFieldConfig->{Name} ) } = (
                $DynamicFieldHTML{ $DynamicFieldConfig->{Name} }->{Label}
                    . qq~\n<div class="Field">~
                    . $DynamicFieldHTML{ $DynamicFieldConfig->{Name} }->{Field}
                    . qq~\n</div>\n<div class="Clear"></div>\n~
            );
        }
        else {
            $Output{ ( "DynamicField_" . $DynamicFieldConfig->{Name} ) } = "";
        }
    }

    if ( IsHashRefWithData( \%Output ) ) {
        push @JSONCollector, {
            Name => 'FormDisplay',
            Data => \%Output,
            Max  => 10000,
        };
    }

    my $JSON = $LayoutObject->BuildSelectionJSON( [@JSONCollector] );

    return $LayoutObject->Attachment(
        ContentType => 'application/json; charset=' . $LayoutObject->{Charset},
        Content     => $JSON,
        Type        => 'inline',
        NoCache     => 1,
    );
}

# =item _GetParam()
#
# returns the current data state of the submitted information
#
# This contains the following data for the different callers:
#
#     Initial call with selected Process:
#         ProcessEntityID
#         ActivityDialogEntityID
#         DefaultValues for the configured Fields in that ActivityDialog
#         DefaultValues for the 4 required Fields Queue State Lock Priority
#
#     First Store call submitting an Activity Dialog:
#         ProcessEntityID
#         ActivityDialogEntityID
#         SubmittedValues for the current ActivityDialog
#         ActivityDialog DefaultValues for invisible fields of that ActivityDialog
#         DefaultValues for the 4 required Fields Queue State Lock Priority
#             if not configured in the ActivityDialog
#
#     ActivityDialog fillout request on existing Ticket:
#         ProcessEntityID
#         ActivityDialogEntityID
#         TicketValues
#
#     ActivityDialog store request or AjaxUpdate request on existing Tickets:
#         ProcessEntityID
#         ActivityDialogEntityID
#         TicketValues for all not-Submitted Values
#         Submitted Values
#
#     my $GetParam = _GetParam(
#         ProcessEntityID => $ProcessEntityID,
#     );
#
# =cut

sub _GetParam {
    my ( $Self, %Param ) = @_;

    #my $IsAJAXUpdate = $Param{AJAX} || '';

    # get needed objects
    my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout');
    my $ParamObject  = $Kernel::OM->Get('Kernel::System::Web::Request');

    for my $Needed (qw(ProcessEntityID)) {
        if ( !$Param{$Needed} ) {
            $LayoutObject->FatalError(
                Message => $LayoutObject->{LanguageObject}
                    ->Translate( 'Parameter %s is missing in %s.', $Needed, '_GetParam' ),
            );
        }
    }
    my %GetParam;
    my %Ticket;
    my $ProcessEntityID        = $Param{ProcessEntityID};
    my $TicketID               = $ParamObject->GetParam( Param => 'TicketID' );
    my $ActivityDialogEntityID = $ParamObject->GetParam(
        Param => 'ActivityDialogEntityID',
    );
    my $ActivityEntityID;
    my %ValuesGotten;
    my $Value;

    # get activity dialog object
    my $ActivityDialogObject = $Kernel::OM->Get('Kernel::System::ProcessManagement::ActivityDialog');

    # create process object
    $Kernel::OM->ObjectParamAdd(
        'Kernel::System::ProcessManagement::Process' => {
            ActivityObject         => $Kernel::OM->Get('Kernel::System::ProcessManagement::Activity'),
            ActivityDialogObject   => $ActivityDialogObject,
            TransitionObject       => $Kernel::OM->Get('Kernel::System::ProcessManagement::Transition'),
            TransitionActionObject => $Kernel::OM->Get('Kernel::System::ProcessManagement::TransitionAction'),
            }
    );
    my $ProcessObject = $Kernel::OM->Get('Kernel::System::ProcessManagement::Process');

    # If we got no ActivityDialogEntityID and no TicketID
    # we have to get the Processes' Startpoint
    if ( !$ActivityDialogEntityID && ( !$TicketID || $Self->{IsProcessEnroll} ) ) {
        my $ActivityActivityDialog = $ProcessObject->ProcessStartpointGet(
            ProcessEntityID => $ProcessEntityID,
        );
        if (
            !$ActivityActivityDialog->{ActivityDialog}
            || !$ActivityActivityDialog->{Activity}
        ) {
            my $Message = $LayoutObject->{LanguageObject}->Translate(
                'Got no Start ActivityEntityID or Start ActivityDialogEntityID for Process: %s in _GetParam!',
                $ProcessEntityID,
            );

            # does not show header and footer again
            if ( $Self->{IsMainWindow} ) {
                return $LayoutObject->Error(
                    Message => $Message,
                );
            }

            $LayoutObject->FatalError(
                Message => $Message,
            );
        }
        $ActivityDialogEntityID = $ActivityActivityDialog->{ActivityDialog};
        $ActivityEntityID       = $ActivityActivityDialog->{Activity};
    }

    my $ActivityDialog = $ActivityDialogObject->ActivityDialogGet(
        ActivityDialogEntityID => $ActivityDialogEntityID,
        Interface              => 'AgentInterface',
    );

    if ( !IsHashRefWithData($ActivityDialog) ) {
        return $LayoutObject->ErrorScreen(
            Message => $LayoutObject->{LanguageObject}->Translate(
                'Couldn\'t get ActivityDialogEntityID "%s"!',
                $ActivityDialogEntityID,
            ),
            Comment => Translatable('Please contact the administrator.'),
        );
    }

    # get config object
    my $ConfigObject = $Kernel::OM->Get('Kernel::Config');

    # if there is a ticket then is not an AJAX request
    if ($TicketID) {
        %Ticket = $Kernel::OM->Get('Kernel::System::Ticket')->TicketGet(
            TicketID      => $TicketID,
            UserID        => $Self->{UserID},
            DynamicFields => 1,
        );

        %GetParam = %Ticket;
        if ( !IsHashRefWithData( \%GetParam ) ) {
            $LayoutObject->FatalError(
                Message => $LayoutObject->{LanguageObject}->Translate(
                    'Couldn\'t get Ticket for TicketID: %s in _GetParam!',
                    $TicketID,
                ),
            );
        }

        if ( !$Self->{IsProcessEnroll} ) {
            $ActivityEntityID = $Ticket{
                'DynamicField_'
                    . $ConfigObject->Get("Process::DynamicFieldProcessManagementActivityID")
            };
            if ( !$ActivityEntityID ) {
                $LayoutObject->FatalError(
                    Message => Translatable(
                        'Couldn\'t determine ActivityEntityID. DynamicField or Config isn\'t set properly!'
                    ),
                );
            }
        }

    }
    $GetParam{ActivityDialogEntityID} = $ActivityDialogEntityID;
    $GetParam{ActivityEntityID}       = $ActivityEntityID;
    $GetParam{ProcessEntityID}        = $ProcessEntityID;

    # prepare field filter
    my %FieldFilter = ();
    for my $CurrentField ( @{ $ActivityDialog->{FieldOrder} } ) {
        if ( $CurrentField =~ m{^DynamicField_(.*)}xms ) {
            my $DynamicFieldName = $1;

            $FieldFilter{$DynamicFieldName} = 1;
        }
    }

    # get all relevant dynamic fields
    $Self->{DynamicField} = $Kernel::OM->Get('Kernel::System::DynamicField')->DynamicFieldListGet(
        Valid       => 1,
        ObjectType  => 'Ticket',
        FieldFilter => \%FieldFilter,
    );

    # Get the activitydialogs's Submit Param's or Config Params
    DIALOGFIELD:
    for my $CurrentField ( @{ $ActivityDialog->{FieldOrder} } ) {

        # Skip if we're working on a field that was already done with or without ID
        if ( $Self->{NameToID}{$CurrentField} && $ValuesGotten{ $Self->{NameToID}{$CurrentField} } ) {
            next DIALOGFIELD;
        }

        if ( $CurrentField =~ m{^DynamicField_(.*)}xms ) {
            my $DynamicFieldName = $1;

            # Get the Config of the current DynamicField (the first element of the grep result array)
            my $DynamicFieldConfig = ( grep { $_->{Name} eq $DynamicFieldName } @{ $Self->{DynamicField} } )[0];

            if ( !IsHashRefWithData($DynamicFieldConfig) ) {
                my $Message =
                    "DynamicFieldConfig missing for field: $DynamicFieldName, or is not a Ticket Dynamic Field!";

                # log error but does not stop the execution as it could be an old Article
                # DynamicField, see bug#11666
                $Kernel::OM->Get('Kernel::System::Log')->Log(
                    Priority => 'error',
                    Message  => $Message,
                );

                next DIALOGFIELD;
            }

            # Get DynamicField Values
            $Value = $Kernel::OM->Get('Kernel::System::DynamicField::Backend')->EditFieldValueGet(
                DynamicFieldConfig => $DynamicFieldConfig,
                ParamObject        => $ParamObject,
                LayoutObject       => $LayoutObject,
            );
# ---
# ITSMIncidentProblemManagement
# ---
            # set the criticality from the service
            if ( $DynamicFieldName eq 'ITSMCriticality' && $ParamObject->GetParam( Param => 'ServiceID' ) ) {

                # get service
                my %Service = $Kernel::OM->Get('Kernel::System::Service')->ServiceGet(
                    ServiceID => $ParamObject->GetParam( Param => 'ServiceID' ),
                    UserID    => $Self->{UserID},
                );

                # set the criticality
                $Value = $Service{Criticality};
            }
# ---

            # If we got a submitted param, take it and next out
            if (
                defined $Value
                && (
                    $Value eq ''
                    || IsStringWithData($Value)
                    || IsArrayRefWithData($Value)
                    || IsHashRefWithData($Value)
                )
            ) {
                $GetParam{$CurrentField} = $Value;
                next DIALOGFIELD;
            }

            # If we didn't have a Param Value try the ticket Value
            # next out if it was successful
            if (
                defined $Ticket{$CurrentField}
                && (
                    $Ticket{$CurrentField} eq ''
                    || IsStringWithData( $Ticket{$CurrentField} )
                    || IsArrayRefWithData( $Ticket{$CurrentField} )
                    || IsHashRefWithData( $Ticket{$CurrentField} )
                )
            ) {
                $GetParam{$CurrentField} = $Ticket{$CurrentField};
                next DIALOGFIELD;
            }

            # If we had neither submitted nor ticket param get the ActivityDialog's default Value
            # next out if it was successful
            $Value = $ActivityDialog->{Fields}{$CurrentField}{DefaultValue};
            if ( defined $Value && length $Value ) {
                $GetParam{$CurrentField} = $Value;
                next DIALOGFIELD;
            }

            # If we had no submitted, ticket or ActivityDialog default value
            # use the DynamicField's default value and next out
            $Value = $DynamicFieldConfig->{Config}{DefaultValue};
            if ( defined $Value && length $Value ) {
                $GetParam{$CurrentField} = $Value;
                next DIALOGFIELD;
            }

            # if all that failed then the field should not have a defined value otherwise
            # if a value (even empty) is sent, fields like Date or DateTime will mark the field as
            # used with the field display value, this could lead to unwanted field sets,
            # see bug#9159
            next DIALOGFIELD;
        }

        # get article fields
        if ( $CurrentField eq 'Article' ) {

            $GetParam{Subject} = $ParamObject->GetParam( Param => 'Subject' );
            $GetParam{Body}    = $ParamObject->GetParam( Param => 'Body' );
            @{ $GetParam{InformUserID} } = $ParamObject->GetArray(
                Param => 'InformUserID',
            );

            $ValuesGotten{Article} = 1 if ( $GetParam{Subject} && $GetParam{Body} );

            $GetParam{TimeUnits} = $ParamObject->GetParam( Param => 'TimeUnits' );
        }

        if ( $CurrentField eq 'CustomerID' ) {
            $GetParam{Customer} = $ParamObject->GetParam(
                Param => 'SelectedCustomerUser',
            ) || '';
            $GetParam{CustomerUserID} = $ParamObject->GetParam(
                Param => 'SelectedCustomerUser',
            ) || '';
        }

        if ( $CurrentField eq 'PendingTime' ) {
            my $Prefix = 'PendingTime';

            # Ok, we need to try to find the target state now
            my %StateData;

            # get state object
            my $StateObject = $Kernel::OM->Get('Kernel::System::State');

            # Was something submitted from the GUI?
            my $TargetStateID = $ParamObject->GetParam( Param => 'StateID' );
            if ($TargetStateID) {
                %StateData = $StateObject->StateGet(
                    ID => $TargetStateID,
                );
            }

            # Fallback 1: default value of dialog field State
            if ( !%StateData && $ActivityDialog->{Fields}{State}{DefaultValue} ) {
                %StateData = $StateObject->StateGet(
                    Name => $ActivityDialog->{Fields}{State}{DefaultValue},
                );
            }

            # Fallback 2: default value of dialog field StateID
            if ( !%StateData && $ActivityDialog->{Fields}{StateID}{DefaultValue} ) {
                %StateData = $StateObject->StateGet(
                    ID => $ActivityDialog->{Fields}{StateID}{DefaultValue},
                );
            }

            # Fallback 3: existing ticket state
            if ( !%StateData && %Ticket ) {
                %StateData = $StateObject->StateGet(
                    ID => $Ticket{StateID},
                );
            }

            # get pending time values
            # depends on StateType containing '^pending'
            if (
                IsHashRefWithData( \%StateData )
                && $StateData{TypeName}
                && $StateData{TypeName} =~ /^pending/i
            ) {

                my %DateParam = ( Prefix => $Prefix );

                # map the GetParam's Date Values to our DateParamHash
                %DateParam = map {
                    ( $Prefix . $_ )
                        => $ParamObject->GetParam( Param => ( $Prefix . $_ ) )
                    }
                    qw(Year Month Day Hour Minute);

                # if all values are present
                if (
                    defined $DateParam{ $Prefix . 'Year' }
                    && defined $DateParam{ $Prefix . 'Month' }
                    && defined $DateParam{ $Prefix . 'Day' }
                    && defined $DateParam{ $Prefix . 'Hour' }
                    && defined $DateParam{ $Prefix . 'Minute' }
                ) {

                    # recalculate time according to the user's timezone
                    %DateParam = $LayoutObject->TransformDateSelection(
                        %DateParam,
                    );

                    # reformat for storing (e.g. take out Prefix)
                    %{ $GetParam{$CurrentField} }
                        = map { $_ => $DateParam{ $Prefix . $_ } } qw(Year Month Day Hour Minute);
                    $ValuesGotten{PendingTime} = 1;
                }
            }
        }

        # Non DynamicFields
        # 1. try to get the required param
        $Value = $ParamObject->GetParam( Param => $Self->{NameToID}{$CurrentField} );

        if ($Value) {

            # if we have an ID field make sure the value without ID won't be in the
            # %GetParam Hash any more
            if ( $Self->{NameToID}{$CurrentField} =~ m{(.*)ID$}xms ) {
                $GetParam{$1} = undef;
            }
            $GetParam{ $Self->{NameToID}{$CurrentField} }     = $Value;
            $ValuesGotten{ $Self->{NameToID}{$CurrentField} } = 1;
            next DIALOGFIELD;
        }

        # If we got ticket params, the GetParam Hash was already filled before the loop
        # and we can next out
        if ( $GetParam{ $Self->{NameToID}{$CurrentField} } ) {
            $ValuesGotten{ $Self->{NameToID}{$CurrentField} } = 1;
            next DIALOGFIELD;
        }

        # if no Submitted nore Ticket Param get ActivityDialog Config's Param
        if ( $CurrentField ne 'CustomerID' ) {
            $Value = $ActivityDialog->{Fields}{$CurrentField}{DefaultValue};
        }
        if ($Value) {
            $ValuesGotten{ $Self->{NameToID}{$CurrentField} } = 1;
            $GetParam{$CurrentField} = $Value;
            next DIALOGFIELD;
        }
    }
    REQUIREDFIELDLOOP:
    for my $CurrentField (qw(Queue State Lock Priority)) {
        $Value = undef;
        if ( !$ValuesGotten{ $Self->{NameToID}{$CurrentField} } ) {
            $Value = $ConfigObject->Get("Process::Default$CurrentField");
            if ( !$Value ) {

                my $Message = $LayoutObject->{LanguageObject}->Translate(
                    'Process::Default%s Config Value missing!',
                    $CurrentField,
                );

                # does not show header and footer again
                if ( $Self->{IsMainWindow} ) {
                    return $LayoutObject->Error(
                        Message => $Message,
                    );
                }

                $LayoutObject->FatalError(
                    Message => $Message,
                );
            }
            $GetParam{$CurrentField} = $Value;
            $ValuesGotten{ $Self->{NameToID}{$CurrentField} } = 1;
        }
    }

    my $Dest = $ParamObject->GetParam( Param => 'Dest' ) || '';
    if ($Dest) {

        my @QueueParts = split( /\|\|/, $Dest );

        $GetParam{QueueID} = $QueueParts[0];
        $GetParam{Queue}   = $QueueParts[1];

        $ValuesGotten{QueueID} = 1;
    }

    # get also the IDs for the Required files (if they are not present)
    if ( $GetParam{Queue} && !$GetParam{QueueID} ) {
        $GetParam{QueueID} = $Kernel::OM->Get('Kernel::System::Queue')->QueueLookup( Queue => $GetParam{Queue} );
    }
    if ( $GetParam{State} && !$GetParam{StateID} ) {
        $GetParam{StateID} = $Kernel::OM->Get('Kernel::System::State')->StateLookup( State => $GetParam{State} );
    }
    if ( $GetParam{Lock} && !$GetParam{LockID} ) {
        $GetParam{LockID} = $Kernel::OM->Get('Kernel::System::Lock')->LockLookup( Lock => $GetParam{Lock} );
    }
    if ( $GetParam{Priority} && !$GetParam{PriorityID} ) {
        $GetParam{PriorityID} = $Kernel::OM->Get('Kernel::System::Priority')->PriorityLookup(
            Priority => $GetParam{Priority},
        );
    }

    # and finally we'll have the special parameters:
    $GetParam{ResponsibleAll} = $ParamObject->GetParam( Param => 'ResponsibleAll' );
    $GetParam{OwnerAll}       = $ParamObject->GetParam( Param => 'OwnerAll' );
    $GetParam{ElementChanged} = $ParamObject->GetParam( Param => 'ElementChanged' );

    # All Ticket DynamicFields
    # used for ACL checking
    my %DynamicFieldCheckParam = map { $_ => $GetParam{$_} }
        grep {m{^DynamicField_}xms} ( keys %GetParam );

    # run acl to prepare TicketAclFormData
    my $ACL = $Kernel::OM->Get('Kernel::System::Ticket')->TicketAcl(
        %GetParam,
        Action        => $Self->{Action},
        DynamicField  => \%DynamicFieldCheckParam,
        ReturnType    => 'Ticket',
        ReturnSubType => '-',
        Data          => {},
        UserID        => $Self->{UserID},
    );

    # update 'Shown' for $Self->{DynamicField}
    $Self->_GetShownDynamicFields();

    return \%GetParam;
}

sub _OutputActivityDialog {
    my ( $Self, %Param ) = @_;
    my $TicketID               = $Param{GetParam}{TicketID};
    my $ActivityDialogEntityID = $Param{GetParam}{ActivityDialogEntityID};

    # get layout object
    my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout');

    # Check needed parameters:
    # ProcessEntityID only
    # TicketID ActivityDialogEntityID
    if ( !$Param{ProcessEntityID} || ( !$TicketID && !$ActivityDialogEntityID ) ) {
        my $Message = Translatable('Got no ProcessEntityID or TicketID and ActivityDialogEntityID!');

        # does not show header and footer again
        if ( $Self->{IsMainWindow} ) {
            return $LayoutObject->Error(
                Message => $Message,
            );
        }

        $LayoutObject->FatalError(
            Message => $Message,
        );
    }

    my $ActivityActivityDialog;
    my %Ticket;
    my %Error         = ();
    my %ErrorMessages = ();

    # If we had Errors, we got an Errorhash
    %Error         = %{ $Param{Error} }         if ( IsHashRefWithData( $Param{Error} ) );
    %ErrorMessages = %{ $Param{ErrorMessages} } if ( IsHashRefWithData( $Param{ErrorMessages} ) );

    # get needed objects
    my $ConfigObject         = $Kernel::OM->Get('Kernel::Config');
    my $ActivityObject       = $Kernel::OM->Get('Kernel::System::ProcessManagement::Activity');
    my $ActivityDialogObject = $Kernel::OM->Get('Kernel::System::ProcessManagement::ActivityDialog');
    my $TicketObject         = $Kernel::OM->Get('Kernel::System::Ticket');

    # create process object
    $Kernel::OM->ObjectParamAdd(
        'Kernel::System::ProcessManagement::Process' => {
            ActivityObject         => $ActivityObject,
            ActivityDialogObject   => $ActivityDialogObject,
            TransitionObject       => $Kernel::OM->Get('Kernel::System::ProcessManagement::Transition'),
            TransitionActionObject => $Kernel::OM->Get('Kernel::System::ProcessManagement::TransitionAction'),
            }
    );
    my $ProcessObject = $Kernel::OM->Get('Kernel::System::ProcessManagement::Process');


    if ( !$TicketID || $Self->{IsProcessEnroll} ) {
        $ActivityActivityDialog = $ProcessObject->ProcessStartpointGet(
            ProcessEntityID => $Param{ProcessEntityID},
        );

        if ( !IsHashRefWithData($ActivityActivityDialog) ) {
            my $Message = $LayoutObject->{LanguageObject}->Translate(
                'Can\'t get StartActivityDialog and StartActivityDialog for the ProcessEntityID "%s"!',
                $Param{ProcessEntityID},
            );

            # does not show header and footer again
            if ( $Self->{IsMainWindow} ) {
                return $LayoutObject->Error(
                    Message => $Message,
                );
            }

            $LayoutObject->FatalError(
                Message => $Message,
            );
        }
    }
    else {

        # no AJAX update in this part
        %Ticket = $TicketObject->TicketGet(
            TicketID      => $TicketID,
            UserID        => $Self->{UserID},
            DynamicFields => 1,
        );

        if ( !IsHashRefWithData( \%Ticket ) ) {
            $LayoutObject->FatalError(
                Message => $LayoutObject->{LanguageObject}->Translate( 'Can\'t get Ticket "%s"!', $Param{TicketID} ),
            );
        }

        my $DynamicFieldProcessID = 'DynamicField_'
            . $ConfigObject->Get('Process::DynamicFieldProcessManagementProcessID');
        my $DynamicFieldActivityID = 'DynamicField_'
            . $ConfigObject->Get('Process::DynamicFieldProcessManagementActivityID');

        if ( !$Ticket{$DynamicFieldProcessID} || !$Ticket{$DynamicFieldActivityID} ) {
            $LayoutObject->FatalError(
                Message => $LayoutObject->{LanguageObject}->Translate(
                    'Can\'t get ProcessEntityID or ActivityEntityID for Ticket "%s"!',
                    $Param{TicketID},
                ),
            );
        }

        $ActivityActivityDialog = {
            Activity       => $Ticket{$DynamicFieldActivityID},
            ActivityDialog => $ActivityDialogEntityID,
        };
    }

    if ( !%Ticket && $Self->{IsProcessEnroll} ) {
        %Ticket = $TicketObject->TicketGet(
            TicketID      => $TicketID,
            UserID        => $Self->{UserID},
            DynamicFields => 1,
        );
    }

    my $Activity = $ActivityObject->ActivityGet(
        Interface        => 'AgentInterface',
        ActivityEntityID => $ActivityActivityDialog->{Activity}
    );
    if ( !$Activity ) {
        my $Message = $LayoutObject->{LanguageObject}->Translate(
            'Can\'t get Activity configuration for ActivityEntityID "%s"!',
            $ActivityActivityDialog->{Activity},
        );

        # does not show header and footer again
        if ( $Self->{IsMainWindow} ) {
            return $LayoutObject->Error(
                Message => $Message,
            );
        }

        $LayoutObject->FatalError(
            Message => $Message,
        );
    }
    if (
        !IsHashRefWithData( $Activity->{ActivityDialog} )
        || !grep { $_ eq $ActivityActivityDialog->{ActivityDialog} } values( %{ $Activity->{ActivityDialog} } )
    ) {
        my $Message = $LayoutObject->{LanguageObject}->Translate(
            'ActivityDialog does not belong to Activity!',
        );

        # does not show header and footer again
        if ( $Self->{IsMainWindow} ) {
            return $LayoutObject->Error(
                Message => $Message,
            );
        }

        $LayoutObject->FatalError(
            Message => $Message,
        );
    }

    my $ActivityDialog = $ActivityDialogObject->ActivityDialogGet(
        ActivityDialogEntityID => $ActivityActivityDialog->{ActivityDialog},
        Interface              => 'AgentInterface',
    );
    if ( !IsHashRefWithData($ActivityDialog) ) {
        my $Message = $LayoutObject->{LanguageObject}->Translate(
            'Can\'t get ActivityDialog configuration for ActivityDialogEntityID "%s"!',
            $ActivityActivityDialog->{ActivityDialog},
        );

        # does not show header and footer again
        if ( $Self->{IsMainWindow} ) {
            return $LayoutObject->Error(
                Message => $Message,
            );
        }

        $LayoutObject->FatalError(
            Message => $Message,
        );
    }

    # Add PageHeader, Navbar, Formheader (Process/ActivityDialogHeader)
    my $Output;
    my $MainBoxClass;

    if ( !$Self->{IsMainWindow} && !$Self->{IsProcessEnroll} ) {
        $Output = $LayoutObject->Header(
            Type  => 'Small',
            Value => $Ticket{Number},
        );

        # display given notify messages if this is not an AJAX request
        if ( IsArrayRefWithData( $Param{Notify} ) ) {

            for my $NotifyData ( @{ $Param{Notify} } ) {
                $Output .= $LayoutObject->Notify( %{$NotifyData} );
            }
        }

        $LayoutObject->Block(
            Name => 'Header',
            Data => {
                Name =>
                    $LayoutObject->{LanguageObject}->Translate( $ActivityDialog->{Name} )
                    || '',
            },
        );
    }
    elsif (
        ( $Self->{IsMainWindow} || $Self->{IsProcessEnroll} )
        && ( IsHashRefWithData( \%Error ) || $Param{IsUpload} )
    ) {

        # add rich text editor
        if ( $LayoutObject->{BrowserRichText} ) {

            # use height/width defined for this screen
            $Param{RichTextHeight} = $Self->{Config}->{RichTextHeight} || 0;
            $Param{RichTextWidth}  = $Self->{Config}->{RichTextWidth}  || 0;

            $LayoutObject->Block(
                Name => 'RichText',
                Data => \%Param,
            );
        }

        # display complete header and navigation bar in AJAX dialogs when there is a server error
        #    unless we are in a process enrollment (only when IsMainWindow is active)
        my $Type = $Self->{IsMainWindow} ? '' : 'Small';
        $Output = $LayoutObject->Header(
            Type => $Type,
        );
        if ( $Self->{IsMainWindow} ) {
            $Output .= $LayoutObject->NavigationBar();
        }

        # display original header texts (the process list maybe is not necessary)
        $Output .= $LayoutObject->Output(
            TemplateFile => 'AgentTicketProcess' . $Type,
            Data         => {
                %Param,
                FormID          => $Self->{FormID},
                IsProcessEnroll => $Self->{IsProcessEnroll},
            },
        );

        # set the MainBox class to add correct borders to the screen
        $MainBoxClass = 'MainBox';
    }

    # display process information
    if ( $Self->{IsMainWindow} ) {

        # get process data
        my $Process = $ProcessObject->ProcessGet(
            ProcessEntityID => $Param{ProcessEntityID},
        );

        # output main process information
        $LayoutObject->Block(
            Name => 'ProcessInfoSidebar',
            Data => {
                Process        => $Process->{Name}        || '',
                Activity       => $Activity->{Name}       || '',
                ActivityDialog => $ActivityDialog->{Name} || '',
            },
        );

        # output activity dialog short description (if any)
        if (
            defined $ActivityDialog->{DescriptionShort}
            && $ActivityDialog->{DescriptionShort} ne ''
        ) {
            $LayoutObject->Block(
                Name => 'ProcessInfoSidebarActivityDialogDesc',
                Data => {
                    ActivityDialogDescription => $ActivityDialog->{DescriptionShort} || '',
                },
            );
        }
    }

    # show descriptions
    if ( $ActivityDialog->{DescriptionShort} ) {
        $LayoutObject->Block(
            Name => 'DescriptionShort',
            Data => {
                DescriptionShort
                    => $LayoutObject->{LanguageObject}->Translate(
                    $ActivityDialog->{DescriptionShort},
                    ),
            },
        );
    }
    if ( $ActivityDialog->{DescriptionLong} ) {
        $LayoutObject->Block(
            Name => 'DescriptionLong',
            Data => {
                DescriptionLong
                    => $LayoutObject->{LanguageObject}->Translate(
                    $ActivityDialog->{DescriptionLong},
                ),
            },
        );
    }

    # show close & cancel link if necessary
    if ( !$Self->{IsMainWindow} && !$Self->{IsProcessEnroll} ) {
        if ( $Param{RenderLocked} ) {
            $LayoutObject->Block(
                Name => 'PropertiesLock',
                Data => {
                    %Param,
                    TicketID => $TicketID,
                },
            );
        }
        else {
            $LayoutObject->Block(
                Name => 'CancelLink',
            );
        }
    }

    $Output .= $LayoutObject->Output(
        TemplateFile => 'ProcessManagement/ActivityDialogHeader',
        Data         => {
            FormName               => 'ActivityDialogDialog' . $ActivityActivityDialog->{ActivityDialog},
            FormID                 => $Self->{FormID},
            Subaction              => 'StoreActivityDialog',
            TicketID               => $Ticket{TicketID} || '',
            ActivityDialogEntityID => $ActivityActivityDialog->{ActivityDialog},
            ProcessEntityID        => $Param{ProcessEntityID}
                || $Ticket{
                'DynamicField_'
                    . $ConfigObject->Get(
                    'Process::DynamicFieldProcessManagementProcessID'
                    )
                },
            IsMainWindow    => $Self->{IsMainWindow},
            IsProcessEnroll => $Self->{IsProcessEnroll},
            MainBoxClass    => $MainBoxClass || '',
        },
    );

    my %RenderedFields = ();

    # get the list of fields where the AJAX loader icon should appear on AJAX updates triggered
    # by ActivityDialog fields
    my $AJAXUpdatableFields = $Self->_GetAJAXUpdatableFields(
        ActivityDialogFields => $ActivityDialog->{Fields},
    );

    # Loop through ActivityDialogFields and render their output
    DIALOGFIELD:
    for my $CurrentField ( @{ $ActivityDialog->{FieldOrder} } ) {
        if ( !IsHashRefWithData( $ActivityDialog->{Fields}{$CurrentField} ) ) {
            my $Message = $LayoutObject->{LanguageObject}->Translate(
                'Can\'t get data for Field "%s" of ActivityDialog "%s"!',
                $CurrentField,
                $ActivityActivityDialog->{ActivityDialog},
            );

            # does not show header and footer again
            if ( $Self->{IsMainWindow} ) {
                return $LayoutObject->Error(
                    Message => $Message,
                );
            }

            $LayoutObject->FatalError(
                Message => $Message,
            );
        }

        my %FieldData = %{ $ActivityDialog->{Fields}{$CurrentField} };

        # We render just visible ActivityDialogFields
        next DIALOGFIELD if !$FieldData{Display};

        # render DynamicFields
        if ( $CurrentField =~ m{^DynamicField_(.*)}xms ) {
            my $DynamicFieldName = $1;
            my $Response         = $Self->_RenderDynamicField(
                ActivityDialogField => $ActivityDialog->{Fields}{$CurrentField},
                FieldName           => $DynamicFieldName,
                DescriptionShort    => $ActivityDialog->{Fields}{$CurrentField}{DescriptionShort},
                DescriptionLong     => $ActivityDialog->{Fields}{$CurrentField}{DescriptionLong},
                Ticket              => \%Ticket || {},
                Error               => \%Error || {},
                ErrorMessages       => \%ErrorMessages || {},
                FormID              => $Self->{FormID},
                GetParam            => $Param{GetParam},
                AJAXUpdatableFields => $AJAXUpdatableFields,
            );

            if ( !$Response->{Success} ) {

                # does not show header and footer again
                if ( $Self->{IsMainWindow} ) {
                    return $LayoutObject->Error(
                        Message => $Response->{Message},
                    );
                }

                $LayoutObject->FatalError(
                    Message => $Response->{Message},
                );
            }

            $Output .= $Response->{HTML};

            $RenderedFields{$CurrentField} = 1;

        }

        # render State
        elsif ( $Self->{NameToID}->{$CurrentField} eq 'StateID' ) {

            # We don't render Fields twice,
            # if there was already a Config without ID, skip this field
            next DIALOGFIELD if $RenderedFields{ $Self->{NameToID}->{$CurrentField} };

            my $Response = $Self->_RenderState(
                ActivityDialogField => $ActivityDialog->{Fields}{$CurrentField},
                FieldName           => $CurrentField,
                DescriptionShort    => $ActivityDialog->{Fields}{$CurrentField}{DescriptionShort},
                DescriptionLong     => $ActivityDialog->{Fields}{$CurrentField}{DescriptionLong},
                Ticket              => \%Ticket || {},
                Error               => \%Error || {},
                FormID              => $Self->{FormID},
                GetParam            => $Param{GetParam},
                AJAXUpdatableFields => $AJAXUpdatableFields,
            );

            if ( !$Response->{Success} ) {

                # does not show header and footer again
                if ( $Self->{IsMainWindow} ) {
                    return $LayoutObject->Error(
                        Message => $Response->{Message},
                    );
                }

                $LayoutObject->FatalError(
                    Message => $Response->{Message},
                );
            }

            $Output .= $Response->{HTML};

            $RenderedFields{ $Self->{NameToID}->{$CurrentField} } = 1;
        }

        # render Queue
        elsif ( $Self->{NameToID}->{$CurrentField} eq 'QueueID' ) {
            next DIALOGFIELD if $RenderedFields{ $Self->{NameToID}->{$CurrentField} };

            my $Response = $Self->_RenderQueue(
                ActivityDialogField => $ActivityDialog->{Fields}{$CurrentField},
                FieldName           => $CurrentField,
                DescriptionShort    => $ActivityDialog->{Fields}{$CurrentField}{DescriptionShort},
                DescriptionLong     => $ActivityDialog->{Fields}{$CurrentField}{DescriptionLong},
                Ticket              => \%Ticket || {},
                Error               => \%Error || {},
                FormID              => $Self->{FormID},
                GetParam            => $Param{GetParam},
                AJAXUpdatableFields => $AJAXUpdatableFields,
            );

            if ( !$Response->{Success} ) {

                # does not show header and footer again
                if ( $Self->{IsMainWindow} ) {
                    return $LayoutObject->Error(
                        Message => $Response->{Message},
                    );
                }

                $LayoutObject->FatalError(
                    Message => $Response->{Message},
                );
            }

            $Output .= $Response->{HTML};

            $RenderedFields{ $Self->{NameToID}->{$CurrentField} } = 1;
        }

        # render Priority
        elsif ( $Self->{NameToID}->{$CurrentField} eq 'PriorityID' ) {
            next DIALOGFIELD if $RenderedFields{ $Self->{NameToID}->{$CurrentField} };

            my $Response = $Self->_RenderPriority(
                ActivityDialogField => $ActivityDialog->{Fields}{$CurrentField},
                FieldName           => $CurrentField,
                DescriptionShort    => $ActivityDialog->{Fields}{$CurrentField}{DescriptionShort},
                DescriptionLong     => $ActivityDialog->{Fields}{$CurrentField}{DescriptionLong},
                Ticket              => \%Ticket || {},
                Error               => \%Error || {},
                FormID              => $Self->{FormID},
                GetParam            => $Param{GetParam},
                AJAXUpdatableFields => $AJAXUpdatableFields,
            );

            if ( !$Response->{Success} ) {

                # does not show header and footer again
                if ( $Self->{IsMainWindow} ) {
                    return $LayoutObject->Error(
                        Message => $Response->{Message},
                    );
                }

                $LayoutObject->FatalError(
                    Message => $Response->{Message},
                );
            }

            $Output .= $Response->{HTML};

            $RenderedFields{ $Self->{NameToID}->{$CurrentField} } = 1;
        }

        # render HorizontalLine
        elsif ( $Self->{NameToID}->{$CurrentField} eq 'horizontalline' ) {
            my $Response = $Self->_RenderHorizontalLine(
                ActivityDialogField => $ActivityDialog->{Fields}{$CurrentField},
                FieldName           => $CurrentField,
                DescriptionShort    => $ActivityDialog->{Fields}{$CurrentField}{DescriptionShort},
                DescriptionLong     => $ActivityDialog->{Fields}{$CurrentField}{DescriptionLong},
                Ticket              => \%Ticket || {},
                Error               => \%Error || {},
                FormID              => $Self->{FormID},
                GetParam            => $Param{GetParam},
                AJAXUpdatableFields => $AJAXUpdatableFields,
            );

            if ( !$Response->{Success} ) {

                # does not show header and footer again
                if ( $Self->{IsMainWindow} ) {
                    return $LayoutObject->Error(
                        Message => $Response->{Message},
                    );
                }

                $LayoutObject->FatalError(
                    Message => $Response->{Message},
                );
            }

            $Output .= $Response->{HTML};
        }

        # render Lock
        elsif ( $Self->{NameToID}->{$CurrentField} eq 'LockID' ) {
            next DIALOGFIELD if $RenderedFields{ $Self->{NameToID}->{$CurrentField} };

            my $Response = $Self->_RenderLock(
                ActivityDialogField => $ActivityDialog->{Fields}{$CurrentField},
                FieldName           => $CurrentField,
                DescriptionShort    => $ActivityDialog->{Fields}{$CurrentField}{DescriptionShort},
                DescriptionLong     => $ActivityDialog->{Fields}{$CurrentField}{DescriptionLong},
                Ticket              => \%Ticket || {},
                Error               => \%Error || {},
                FormID              => $Self->{FormID},
                GetParam            => $Param{GetParam},
                AJAXUpdatableFields => $AJAXUpdatableFields,
            );

            if ( !$Response->{Success} ) {

                # does not show header and footer again
                if ( $Self->{IsMainWindow} ) {
                    return $LayoutObject->Error(
                        Message => $Response->{Message},
                    );
                }

                $LayoutObject->FatalError(
                    Message => $Response->{Message},
                );
            }

            $Output .= $Response->{HTML};

            $RenderedFields{ $Self->{NameToID}->{$CurrentField} } = 1;
        }

        # render Service
        elsif ( $Self->{NameToID}->{$CurrentField} eq 'ServiceID' ) {
            next DIALOGFIELD if $RenderedFields{ $Self->{NameToID}->{$CurrentField} };

            my $Response = $Self->_RenderService(
                ActivityDialogField => $ActivityDialog->{Fields}{$CurrentField},
                FieldName           => $CurrentField,
                DescriptionShort    => $ActivityDialog->{Fields}{$CurrentField}{DescriptionShort},
                DescriptionLong     => $ActivityDialog->{Fields}{$CurrentField}{DescriptionLong},
                Ticket              => \%Ticket || {},
                Error               => \%Error || {},
                FormID              => $Self->{FormID},
                GetParam            => $Param{GetParam},
                AJAXUpdatableFields => $AJAXUpdatableFields,
            );

            if ( !$Response->{Success} ) {

                # does not show header and footer again
                if ( $Self->{IsMainWindow} ) {
                    return $LayoutObject->Error(
                        Message => $Response->{Message},
                    );
                }

                $LayoutObject->FatalError(
                    Message => $Response->{Message},
                );
            }

            $Output .= $Response->{HTML};

            $RenderedFields{$CurrentField} = 1;
        }

        # render SLA
        elsif ( $Self->{NameToID}->{$CurrentField} eq 'SLAID' ) {
            next DIALOGFIELD if $RenderedFields{ $Self->{NameToID}->{$CurrentField} };

            my $Response = $Self->_RenderSLA(
                ActivityDialogField => $ActivityDialog->{Fields}{$CurrentField},
                FieldName           => $CurrentField,
                DescriptionShort    => $ActivityDialog->{Fields}{$CurrentField}{DescriptionShort},
                DescriptionLong     => $ActivityDialog->{Fields}{$CurrentField}{DescriptionLong},
                Ticket              => \%Ticket || {},
                Error               => \%Error || {},
                FormID              => $Self->{FormID},
                GetParam            => $Param{GetParam},
                AJAXUpdatableFields => $AJAXUpdatableFields,
            );

            if ( !$Response->{Success} ) {

                # does not show header and footer again
                if ( $Self->{IsMainWindow} ) {
                    return $LayoutObject->Error(
                        Message => $Response->{Message},
                    );
                }

                $LayoutObject->FatalError(
                    Message => $Response->{Message},
                );
            }

            $Output .= $Response->{HTML};

            $RenderedFields{ $Self->{NameToID}->{$CurrentField} } = 1;
        }

        # render Owner
        elsif ( $Self->{NameToID}->{$CurrentField} eq 'OwnerID' ) {
            next DIALOGFIELD if $RenderedFields{ $Self->{NameToID}->{$CurrentField} };

            my $Response = $Self->_RenderOwner(
                ActivityDialogField => $ActivityDialog->{Fields}{$CurrentField},
                FieldName           => $CurrentField,
                DescriptionShort    => $ActivityDialog->{Fields}{$CurrentField}{DescriptionShort},
                DescriptionLong     => $ActivityDialog->{Fields}{$CurrentField}{DescriptionLong},
                Ticket              => \%Ticket || {},
                Error               => \%Error || {},
                FormID              => $Self->{FormID},
                GetParam            => $Param{GetParam},
                AJAXUpdatableFields => $AJAXUpdatableFields,
            );

            if ( !$Response->{Success} ) {

                # does not show header and footer again
                if ( $Self->{IsMainWindow} ) {
                    return $LayoutObject->Error(
                        Message => $Response->{Message},
                    );
                }

                $LayoutObject->FatalError(
                    Message => $Response->{Message},
                );
            }

            $Output .= $Response->{HTML};

            $RenderedFields{ $Self->{NameToID}->{$CurrentField} } = 1;
        }

        # render responsible
        elsif ( $Self->{NameToID}->{$CurrentField} eq 'ResponsibleID' ) {
            next DIALOGFIELD if $RenderedFields{ $Self->{NameToID}->{$CurrentField} };

            my $Response = $Self->_RenderResponsible(
                ActivityDialogField => $ActivityDialog->{Fields}{$CurrentField},
                FieldName           => $CurrentField,
                DescriptionShort    => $ActivityDialog->{Fields}{$CurrentField}{DescriptionShort},
                DescriptionLong     => $ActivityDialog->{Fields}{$CurrentField}{DescriptionLong},
                Ticket              => \%Ticket || {},
                Error               => \%Error || {},
                FormID              => $Self->{FormID},
                GetParam            => $Param{GetParam},
                AJAXUpdatableFields => $AJAXUpdatableFields,
            );

            if ( !$Response->{Success} ) {

                # does not show header and footer again
                if ( $Self->{IsMainWindow} ) {
                    return $LayoutObject->Error(
                        Message => $Response->{Message},
                    );
                }

                $LayoutObject->FatalError(
                    Message => $Response->{Message},
                );
            }

            $Output .= $Response->{HTML};

            $RenderedFields{ $Self->{NameToID}->{$CurrentField} } = 1;
        }

        # render CustomerID
        elsif ( $Self->{NameToID}->{$CurrentField} eq 'CustomerID' ) {
            next DIALOGFIELD if $RenderedFields{ $Self->{NameToID}->{$CurrentField} };

            my $Response = $Self->_RenderCustomer(
                ActivityDialogField => $ActivityDialog->{Fields}{$CurrentField},
                FieldName           => $CurrentField,
                DescriptionShort    => $ActivityDialog->{Fields}{$CurrentField}{DescriptionShort},
                DescriptionLong     => $ActivityDialog->{Fields}{$CurrentField}{DescriptionLong},
                Ticket              => \%Ticket || {},
                Error               => \%Error || {},
                FormID              => $Self->{FormID},
                GetParam            => $Param{GetParam},
                AJAXUpdatableFields => $AJAXUpdatableFields,
            );

            if ( !$Response->{Success} ) {

                # does not show header and footer again
                if ( $Self->{IsMainWindow} ) {
                    return $LayoutObject->Error(
                        Message => $Response->{Message},
                    );
                }

                $LayoutObject->FatalError(
                    Message => $Response->{Message},
                );
            }

            $Output .= $Response->{HTML};

            $RenderedFields{ $Self->{NameToID}->{$CurrentField} } = 1;
        }

        elsif ( $CurrentField eq 'PendingTime' ) {

            # PendingTime is just useful if we have State or StateID
            if ( !grep {m{^(StateID|State)$}xms} @{ $ActivityDialog->{FieldOrder} } ) {
                my $Message = $LayoutObject->{LanguageObject}->Translate(
                    'PendingTime can just be used if State or StateID is configured for the same ActivityDialog. ActivityDialog: %s!',
                    $ActivityActivityDialog->{ActivityDialog},
                );

                # does not show header and footer again
                if ( $Self->{IsMainWindow} ) {
                    return $LayoutObject->Error(
                        Message => $Message,
                    );
                }

                $LayoutObject->FatalError(
                    Message => $Message,
                );
            }

            next DIALOGFIELD if $RenderedFields{ $Self->{NameToID}->{$CurrentField} };

            my $Response = $Self->_RenderPendingTime(
                ActivityDialogField => $ActivityDialog->{Fields}{$CurrentField},
                FieldName           => $CurrentField,
                DescriptionShort    => $ActivityDialog->{Fields}{$CurrentField}{DescriptionShort},
                DescriptionLong     => $ActivityDialog->{Fields}{$CurrentField}{DescriptionLong},
                Ticket              => \%Ticket || {},
                Error               => \%Error || {},
                FormID              => $Self->{FormID},
                GetParam            => $Param{GetParam},
            );

            if ( !$Response->{Success} ) {

                # does not show header and footer again
                if ( $Self->{IsMainWindow} ) {
                    return $LayoutObject->Error(
                        Message => $Response->{Message},
                    );
                }

                $LayoutObject->FatalError(
                    Message => $Response->{Message},
                );
            }

            $Output .= $Response->{HTML};

            $RenderedFields{ $Self->{NameToID}->{$CurrentField} } = 1;
        }

        # render Title
        elsif ( $Self->{NameToID}->{$CurrentField} eq 'Title' ) {
            next DIALOGFIELD if $RenderedFields{ $Self->{NameToID}->{$CurrentField} };

            my $Response = $Self->_RenderTitle(
                ActivityDialogField => $ActivityDialog->{Fields}{$CurrentField},
                FieldName           => $CurrentField,
                DescriptionShort    => $ActivityDialog->{Fields}{$CurrentField}{DescriptionShort},
                DescriptionLong     => $ActivityDialog->{Fields}{$CurrentField}{DescriptionLong},
                Ticket              => \%Ticket || {},
                Error               => \%Error || {},
                FormID              => $Self->{FormID},
                GetParam            => $Param{GetParam},
            );

            if ( !$Response->{Success} ) {

                # does not show header and footer again
                if ( $Self->{IsMainWindow} ) {
                    return $LayoutObject->Error(
                        Message => $Response->{Message},
                    );
                }

                $LayoutObject->FatalError(
                    Message => $Response->{Message},
                );
            }

            $Output .= $Response->{HTML};

            $RenderedFields{$CurrentField} = 1;
        }

        # render Article
        elsif ( $Self->{NameToID}->{$CurrentField} eq 'Article' ) {
            next DIALOGFIELD if $RenderedFields{ $Self->{NameToID}->{$CurrentField} };

            my $Response = $Self->_RenderArticle(
                ActivityDialogField => $ActivityDialog->{Fields}{$CurrentField},
                FieldName           => $CurrentField,
                DescriptionShort    => $ActivityDialog->{Fields}{$CurrentField}{DescriptionShort},
                DescriptionLong     => $ActivityDialog->{Fields}{$CurrentField}{DescriptionLong},
                Ticket              => \%Ticket || {},
                Error               => \%Error || {},
                FormID              => $Self->{FormID},
                GetParam            => $Param{GetParam},
                InformAgents        => $ActivityDialog->{Fields}->{Article}->{Config}->{InformAgents},
            );

            if ( !$Response->{Success} ) {

                # does not show header and footer again
                if ( $Self->{IsMainWindow} ) {
                    return $LayoutObject->Error(
                        Message => $Response->{Message},
                    );
                }

                $LayoutObject->FatalError(
                    Message => $Response->{Message},
                );
            }

            $Output .= $Response->{HTML};

            $RenderedFields{$CurrentField} = 1;
        }

        # render Type
        elsif ( $Self->{NameToID}->{$CurrentField} eq 'TypeID' ) {

            # We don't render Fields twice,
            # if there was already a Config without ID, skip this field
            next DIALOGFIELD if $RenderedFields{ $Self->{NameToID}->{$CurrentField} };

            my $Response = $Self->_RenderType(
                ActivityDialogField => $ActivityDialog->{Fields}{$CurrentField},
                FieldName           => $CurrentField,
                DescriptionShort    => $ActivityDialog->{Fields}{$CurrentField}{DescriptionShort},
                DescriptionLong     => $ActivityDialog->{Fields}{$CurrentField}{DescriptionLong},
                Ticket              => \%Ticket || {},
                Error               => \%Error || {},
                FormID              => $Self->{FormID},
                GetParam            => $Param{GetParam},
                AJAXUpdatableFields => $AJAXUpdatableFields,
            );

            if ( !$Response->{Success} ) {

                # does not show header and footer again
                if ( $Self->{IsMainWindow} ) {
                    return $LayoutObject->Error(
                        Message => $Response->{Message},
                    );
                }

                $LayoutObject->FatalError(
                    Message => $Response->{Message},
                );
            }

            $Output .= $Response->{HTML};

            $RenderedFields{ $Self->{NameToID}->{$CurrentField} } = 1;
        }
    }

    my $FooterCSSClass = 'Footer';

    if ( $Self->{IsAjaxRequest} ) {

        # Due to the initial loading of
        # the first ActivityDialog after Process selection
        # we have to bind the AjaxUpdate Function on
        # the selects, so we get the complete JSOnDocumentComplete code
        # and deliver it in the FooterJS block.
        # This Javascript Part is executed in
        # AgentTicketProcess.tt
        $LayoutObject->Block(
            Name => 'FooterJS',
            Data => {},
        );

        $FooterCSSClass = 'Center';
    }

    # set submit button data
    my $ButtonText  = 'Submit';
    my $ButtonTitle = 'Save';
    my $ButtonID    = 'Submit' . $ActivityActivityDialog->{ActivityDialog};
    if ( $ActivityDialog->{SubmitButtonText} ) {
        $ButtonText  = $ActivityDialog->{SubmitButtonText};
        $ButtonTitle = $ActivityDialog->{SubmitButtonText};
    }

    $LayoutObject->Block(
        Name => 'Footer',
        Data => {
            FooterCSSClass => $FooterCSSClass,
            ButtonText     => $ButtonText,
            ButtonTitle    => $ButtonTitle,
            ButtonID       => $ButtonID
        },
    );

    if ( $ActivityDialog->{SubmitAdviceText} ) {
        $LayoutObject->Block(
            Name => 'SubmitAdviceText',
            Data => {
                AdviceText => $ActivityDialog->{SubmitAdviceText},
            },
        );
    }

    # reload parent window
    if ( $Param{ParentReload} ) {
        $LayoutObject->Block(
            Name => 'ParentReload',
        );
    }

    # Add the FormFooter
    $Output .= $LayoutObject->Output(
        TemplateFile => 'ProcessManagement/ActivityDialogFooter',
        Data         => {},
    );

    # display regular footer only in non-ajax case
    if ( !$Self->{IsAjaxRequest} ) {
        $Output .= $LayoutObject->Footer( Type => $Self->{IsMainWindow} ? '' : 'Small' );
    }

    return $Output;
}

sub _RenderPendingTime {
    my ( $Self, %Param ) = @_;

    # get layout object
    my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout');

    for my $Needed (qw(FormID)) {
        if ( !$Param{$Needed} ) {
            return {
                Success => 0,
                Message => $LayoutObject->{LanguageObject}
                    ->Translate( 'Parameter %s is missing in %s.', $Needed, '_RenderPendingTime' ),
            };
        }
    }
    if ( !IsHashRefWithData( $Param{ActivityDialogField} ) ) {
        return {
            Success => 0,
            Message => $LayoutObject->{LanguageObject}
                ->Translate( 'Parameter %s is missing in %s.', 'ActivityDialogField', '_RenderPendingTime' ),
        };
    }

    my %Data = (
        Label => (
            $LayoutObject->{LanguageObject}->Translate('Pending Date')
                . ' ('
                . $LayoutObject->{LanguageObject}->Translate('for pending* states') . ')'
        ),
        FieldID => 'ResponsibleID',
        FormID  => $Param{FormID},
    );

    my $Error = '';
    if ( IsHashRefWithData( $Param{Error} ) ) {
        if ( $Param{Error}->{'PendingtTimeDay'} ) {
            $Data{PendingtTimeDayError} = $LayoutObject->{LanguageObject}->Translate("Date invalid!");
            $Error = $Param{Error}->{'PendingtTimeDay'};
        }
        if ( $Param{Error}->{'PendingtTimeHour'} ) {
            $Data{PendingtTimeHourError} = $LayoutObject->{LanguageObject}->Translate("Date invalid!");
            $Error = $Param{Error}->{'PendingtTimeDay'};
        }
    }

    my $Calendar = '';

    # get ticket object
    my $TicketObject = $Kernel::OM->Get('Kernel::System::Ticket');

    # get used calendar if we have ticket data
    if ( IsHashRefWithData( $Param{Ticket} ) ) {
        $Calendar = $TicketObject->TicketCalendarGet(
            %{ $Param{Ticket} },
        );
    }

    $Data{Content} = $LayoutObject->BuildDateSelection(
        Prefix => 'PendingTime',
        PendingTimeRequired =>
            (
            $Param{ActivityDialogField}->{Display} && $Param{ActivityDialogField}->{Display} == 2
            ) ? 1 : 0,
        Format           => 'DateInputFormatLong',
        YearPeriodPast   => 0,
        YearPeriodFuture => 5,
        DiffTime         => $Param{ActivityDialogField}->{DefaultValue}
            || $Kernel::OM->Get('Kernel::Config')->Get('Ticket::Frontend::PendingDiffTime')
            || 86400,
        Class                => $Error,
        Validate             => 1,
        ValidateDateInFuture => 1,
        Calendar             => $Calendar,
    );

    $LayoutObject->Block(
        Name => $Param{ActivityDialogField}->{LayoutBlock} || 'rw:PendingTime',
        Data => \%Data,
    );
    if ( $Param{DescriptionShort} ) {
        $LayoutObject->Block(
            Name => $Param{ActivityDialogField}->{LayoutBlock} || 'rw:PendingTime:DescriptionShort',
            Data => {
                DescriptionShort => $Param{DescriptionShort},
            },
        );
    }

    if ( $Param{DescriptionLong} ) {
        $LayoutObject->Block(
            Name => 'rw:PendingTime:DescriptionLong',
            Data => {
                DescriptionLong => $Param{DescriptionLong},
            },
        );
    }

    return {
        Success => 1,
        HTML    => $LayoutObject->Output( TemplateFile => 'ProcessManagement/PendingTime' ),
    };
}

sub _RenderDynamicField {
    my ( $Self, %Param ) = @_;

    # get layout objects
    my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout');

    for my $Needed (qw(FormID FieldName)) {
        if ( !$Param{$Needed} ) {
            return {
                Success => 0,
                Message => $LayoutObject->{LanguageObject}
                    ->Translate( 'Parameter %s is missing in %s.', $Needed, '_RenderDynamicField' ),
            };
        }
    }

    my $DynamicFieldConfig = ( grep { $_->{Name} eq $Param{FieldName} } @{ $Self->{DynamicField} } )[0];

    if ( !IsHashRefWithData($DynamicFieldConfig) ) {

        my $Message = "DynamicFieldConfig missing for field: $Param{FieldName}, or is not a Ticket Dynamic Field!";

        # log error but does not stop the execution as it could be an old Article
        # DynamicField, see bug#11666
        $Kernel::OM->Get('Kernel::System::Log')->Log(
            Priority => 'error',
            Message  => $Message,
        );

        return {
            Success => 1,
            HTML    => '',
        };
    }

    my $PossibleValuesFilter;

    # get dynamic field backend object
    my $DynamicFieldBackendObject = $Kernel::OM->Get('Kernel::System::DynamicField::Backend');

    my $IsACLReducible = $DynamicFieldBackendObject->HasBehavior(
        DynamicFieldConfig => $DynamicFieldConfig,
        Behavior           => 'IsACLReducible',
    );

    if ($IsACLReducible) {

        # get PossibleValues
        my $PossibleValues = $DynamicFieldBackendObject->PossibleValuesGet(
            DynamicFieldConfig => $DynamicFieldConfig,
        );

        # All Ticket DynamicFields
        # used for ACL checking
        my %DynamicFieldCheckParam = map { $_ => $Param{GetParam}{$_} }
            grep {m{^DynamicField_}xms} ( keys %{ $Param{GetParam} } );

        # check if field has PossibleValues property in its configuration
        if ( IsHashRefWithData($PossibleValues) ) {

            # convert possible values key => value to key => key for ACLs using a Hash slice
            my %AclData = %{$PossibleValues};
            @AclData{ keys %AclData } = keys %AclData;

            # set possible values filter from ACLs
            my $TicketObject = $Kernel::OM->Get('Kernel::System::Ticket');
            my $ACL          = $TicketObject->TicketAcl(
                %{ $Param{GetParam} },
                DynamicField  => \%DynamicFieldCheckParam,
                Action        => $Self->{Action},
                ReturnType    => 'Ticket',
                ReturnSubType => 'DynamicField_' . $DynamicFieldConfig->{Name},
                Data          => \%AclData,
                UserID        => $Self->{UserID},
            );
            if ($ACL) {
                my %Filter = $TicketObject->TicketAclData();

                # convert Filer key => key back to key => value using map
                %{$PossibleValuesFilter} = map { $_ => $PossibleValues->{$_} } keys %Filter;
            }
        }
    }

    my $ServerError;
    my $ErrorMessage;
    if ( IsHashRefWithData( $Param{Error} ) ) {
        if (
            defined $Param{Error}->{ $Param{FieldName} }
            && $Param{Error}->{ $Param{FieldName} } ne ''
        ) {
            $ServerError = 1;
        }
    }
    if ( IsHashRefWithData( $Param{ErrorMessages} ) ) {
        if (
            defined $Param{ErrorMessages}->{ $Param{FieldName} }
            && $Param{ErrorMessages}->{ $Param{FieldName} } ne ''
        ) {
            $ErrorMessage = $Param{ErrorMessages}->{ $Param{FieldName} };
        }
    }

    my $DynamicFieldHTML = $DynamicFieldBackendObject->EditFieldRender(
        DynamicFieldConfig   => $DynamicFieldConfig,
        PossibleValuesFilter => $PossibleValuesFilter,
        Value                => $Param{GetParam}{ 'DynamicField_' . $Param{FieldName} },
        LayoutObject         => $LayoutObject,
        ParamObject          => $Kernel::OM->Get('Kernel::System::Web::Request'),
        AJAXUpdate           => 1,
        Mandatory            => $Param{ActivityDialogField}->{Display} == 2,
        UpdatableFields      => $Param{AJAXUpdatableFields},
        ServerError          => $ServerError,
        ErrorMessage         => $ErrorMessage,
    );

    # set class for dynamic field depending on shown or not
    if ( !$DynamicFieldConfig->{Shown} ) {
        my $DynamicFieldName = $DynamicFieldConfig->{Name};

        $LayoutObject->AddJSOnDocumentComplete( Code => <<"END");
Core.Form.Validate.DisableValidation(\$('.Row_DynamicField_$DynamicFieldName'));
\$('.Row_DynamicField_$DynamicFieldName').addClass('Hidden hiddenFormField').find('select').prop('disabled', true);
END
    }

    my %Data = (
        Name    => $DynamicFieldConfig->{Name},
        Label   => $DynamicFieldHTML->{Label},
        Content => $DynamicFieldHTML->{Field},
    );

    $LayoutObject->Block(
        Name => $Param{ActivityDialogField}->{LayoutBlock} || 'rw:DynamicField',
        Data => \%Data,
    );
    if ( $Param{DescriptionShort} ) {
        $LayoutObject->Block(
            Name => $Param{ActivityDialogField}->{LayoutBlock}
                || 'rw:DynamicField:DescriptionShort',
            Data => {
                DescriptionShort => $Param{DescriptionShort},
            },
        );
    }

    if ( $Param{DescriptionLong} ) {
        $LayoutObject->Block(
            Name => 'rw:DynamicField:DescriptionLong',
            Data => {
                DescriptionLong => $Param{DescriptionLong},
            },
        );
    }

    return {
        Success => 1,
        HTML    => $LayoutObject->Output( TemplateFile => 'ProcessManagement/DynamicField' ),
    };
}

sub _RenderHorizontalLine {
    my ( $Self, %Param ) = @_;

    # get layout object
    my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout');

    for my $Needed (qw(FormID)) {
        if ( !$Param{$Needed} ) {
            return {
                Success => 0,
                Message => $LayoutObject->{LanguageObject}->Translate(
                    'Parameter %s is missing in %s.',
                    $Needed, '_RenderHorizontalLine'
                ),
            };
        }
    }
    if ( !IsHashRefWithData( $Param{ActivityDialogField} ) ) {
        return {
            Success => 0,
            Message => $LayoutObject->{LanguageObject}->Translate(
                'Parameter %s is missing in %s.',
                'ActivityDialogField',
                '_RenderHorizontalLine'
            ),
        };
    }

    my %Data = (
        Label            => $LayoutObject->{LanguageObject}->Translate(""),
        FieldID          => 'HorizontalLine',
        FormID           => $Param{FormID},
        Value            => '',
        Name             => 'HorizontalLine',
        MandatoryClass   => '',
        ValidateRequired => '',
    );

    $LayoutObject->Block(
        Name => $Param{ActivityDialogField}->{LayoutBlock} || 'HorizontalLine',
        Data => \%Data,
    );

    # set mandatory label marker
    if ( $Data{MandatoryClass} && $Data{MandatoryClass} ne '' ) {
        $LayoutObject->Block(
            Name => 'LabelSpan',
            Data => {},
        );
    }

    if ( $Param{DescriptionShort} ) {
        $LayoutObject->Block(
            Name => $Param{ActivityDialogField}->{LayoutBlock} || 'HorizontalLine:DescriptionShort',
            Data => {
                DescriptionShort => $Param{DescriptionShort},
            },
        );
    }

    if ( $Param{DescriptionLong} ) {
        $LayoutObject->Block(
            Name => $Param{ActivityDialogField}->{LayoutBlock} || 'HorizontalLine:DescriptionLong',
            Data => {
                DescriptionLong => $Param{DescriptionLong},
            },
        );
    }

    return {
        Success => 1,
        HTML    => $LayoutObject->Output( TemplateFile => 'ProcessManagement/HorizontalLine' ),
    };
}

sub _RenderTitle {
    my ( $Self, %Param ) = @_;

    # get layout object
    my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout');

    for my $Needed (qw(FormID)) {
        if ( !$Param{$Needed} ) {
            return {
                Success => 0,
                Message => $LayoutObject->{LanguageObject}
                    ->Translate( 'Parameter %s is missing in %s.', $Needed, '_RenderTitle' ),
            };
        }
    }
    if ( !IsHashRefWithData( $Param{ActivityDialogField} ) ) {
        return {
            Success => 0,
            Message => $LayoutObject->{LanguageObject}
                ->Translate( 'Parameter %s is missing in %s.', 'ActivityDialogField', '_RenderTitle' ),
        };
    }

    my %Data = (
        Label            => $LayoutObject->{LanguageObject}->Translate("Title"),
        FieldID          => 'Title',
        FormID           => $Param{FormID},
        Value            => $Param{GetParam}{Title},
        Name             => 'Title',
        MandatoryClass   => '',
        ValidateRequired => '',
    );

    # If field is required put in the necessary variables for
    # ValidateRequired class input field, Mandatory class for the label
    if ( $Param{ActivityDialogField}->{Display} && $Param{ActivityDialogField}->{Display} == 2 ) {
        $Data{ValidateRequired} = 'Validate_Required';
        $Data{MandatoryClass}   = 'Mandatory';
    }

    # output server errors
    if ( IsHashRefWithData( $Param{Error} ) && $Param{Error}->{'Title'} ) {
        $Data{ServerError} = 'ServerError';
    }

    $LayoutObject->Block(
        Name => $Param{ActivityDialogField}->{LayoutBlock} || 'rw:Title',
        Data => \%Data,
    );

    # set mandatory label marker
    if ( $Data{MandatoryClass} && $Data{MandatoryClass} ne '' ) {
        $LayoutObject->Block(
            Name => 'LabelSpan',
            Data => {},
        );
    }

    if ( $Param{DescriptionShort} ) {
        $LayoutObject->Block(
            Name => $Param{ActivityDialogField}->{LayoutBlock} || 'rw:Title:DescriptionShort',
            Data => {
                DescriptionShort => $Param{DescriptionShort},
            },
        );
    }

    if ( $Param{DescriptionLong} ) {
        $LayoutObject->Block(
            Name => $Param{ActivityDialogField}->{LayoutBlock} || 'rw:Title:DescriptionLong',
            Data => {
                DescriptionLong => $Param{DescriptionLong},
            },
        );
    }

    return {
        Success => 1,
        HTML    => $LayoutObject->Output( TemplateFile => 'ProcessManagement/Title' ),
    };

}

sub _RenderArticle {
    my ( $Self, %Param ) = @_;

    # get layout object
    my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout');

    for my $Needed (qw(FormID Ticket)) {
        if ( !$Param{$Needed} ) {
            return {
                Success => 0,
                Message => $LayoutObject->{LanguageObject}
                    ->Translate( 'Parameter %s is missing in %s.', $Needed, '_RenderArticle' ),
            };
        }
    }
    if ( !IsHashRefWithData( $Param{ActivityDialogField} ) ) {
        return {
            Success => 0,
            Message => $LayoutObject->{LanguageObject}
                ->Translate( 'Parameter %s is missing in %s.', 'ActivityDialogField', '_RenderArticle' ),
        };
    }

    my %Data = (
        Name             => 'Article',
        MandatoryClass   => '',
        ValidateRequired => '',
        Subject          => $Param{GetParam}{Subject},
        Body             => $Param{GetParam}{Body},
        LabelSubject     => $Param{ActivityDialogField}->{Config}->{LabelSubject}
            || $LayoutObject->{LanguageObject}->Translate("Subject"),
        LabelBody => $Param{ActivityDialogField}->{Config}->{LabelBody}
            || $LayoutObject->{LanguageObject}->Translate("Text"),
    );

    # If field is required put in the necessary variables for
    # ValidateRequired class input field, Mandatory class for the label
    if ( $Param{ActivityDialogField}->{Display} && $Param{ActivityDialogField}->{Display} == 2 ) {
        $Data{ValidateRequired} = 'Validate_Required';
        $Data{MandatoryClass}   = 'Mandatory';
    }

    # output server errors
    if ( IsHashRefWithData( $Param{Error} ) && $Param{Error}->{'ArticleSubject'} ) {
        $Data{SubjectServerError} = 'ServerError';
    }
    if ( IsHashRefWithData( $Param{Error} ) && $Param{Error}->{'ArticleBody'} ) {
        $Data{BodyServerError} = 'ServerError';
    }

    $LayoutObject->Block(
        Name => $Param{ActivityDialogField}->{LayoutBlock} || 'rw:Article',
        Data => \%Data,
    );

    # set mandatory label marker
    if ( $Data{MandatoryClass} && $Data{MandatoryClass} ne '' ) {
        $LayoutObject->Block(
            Name => 'LabelSpanSubject',
            Data => {},
        );
        $LayoutObject->Block(
            Name => 'LabelSpanBody',
            Data => {},
        );
    }

    # add rich text editor
    if ( $LayoutObject->{BrowserRichText} ) {

        # use height/width defined for this screen
        $Param{RichTextHeight} = $Self->{Config}->{RichTextHeight} || 0;
        $Param{RichTextWidth}  = $Self->{Config}->{RichTextWidth}  || 0;

        $LayoutObject->Block(
            Name => 'RichText',
            Data => \%Param,
        );
    }

    if ( $Param{DescriptionShort} ) {
        $LayoutObject->Block(
            Name => 'rw:Article:DescriptionShort',
            Data => {
                DescriptionShort => $Param{DescriptionShort},
            },
        );
    }

    if ( $Param{DescriptionLong} ) {
        $LayoutObject->Block(
            Name => 'rw:Article:DescriptionLong',
            Data => {
                DescriptionLong => $Param{DescriptionLong},
            },
        );
    }

    if ( $Param{InformAgents} ) {

        my %ShownUsers;
        my %AllGroupsMembers = $Kernel::OM->Get('Kernel::System::User')->UserList(
            Type  => 'Long',
            Valid => 1,
        );
        my $GID = $Kernel::OM->Get('Kernel::System::Queue')->GetQueueGroupID( QueueID => $Param{Ticket}->{QueueID} );
        my %MemberList = $Kernel::OM->Get('Kernel::System::Group')->PermissionGroupGet(
            GroupID => $GID,
            Type    => 'note',
        );
        for my $UserID ( sort keys %MemberList ) {
            $ShownUsers{$UserID} = $AllGroupsMembers{$UserID};
        }
        $Param{OptionStrg} = $LayoutObject->BuildSelection(
            Data       => \%ShownUsers,
            SelectedID => '',
            Name       => 'InformUserID',
            Multiple   => 1,
            Size       => 3,
            Class      => 'Modernize',
        );
        $LayoutObject->Block(
            Name => 'rw:Article:InformAgent',
            Data => \%Param,
        );
    }

    # get all attachments meta data
    my @Attachments = $Kernel::OM->Get('Kernel::System::Web::UploadCache')->FormIDGetAllFilesMeta(
        FormID => $Self->{FormID},
    );

    # show attachments
    ATTACHMENT:
    for my $Attachment (@Attachments) {
        if (
            $Attachment->{ContentID}
            && $LayoutObject->{BrowserRichText}
            && ( $Attachment->{ContentType} =~ /image/i )
            && ( $Attachment->{Disposition} eq 'inline' )
        ) {
            next ATTACHMENT;
        }
        $LayoutObject->Block(
            Name => 'Attachment',
            Data => $Attachment,
        );
    }

    # output server errors
    if ( IsHashRefWithData( $Param{Error} ) && $Param{Error}->{'TimeUnits'} ) {
        $Param{TimeUnitsInvalid} = 'ServerError';
    }

    # get config object
    my $ConfigObject = $Kernel::OM->Get('Kernel::Config');

    # show time units
    if (
        $ConfigObject->Get('Ticket::Frontend::AccountTime')
        && $Param{ActivityDialogField}->{Config}->{TimeUnits}
    ) {

        if ( $ConfigObject->Get('Ticket::Frontend::NeedAccountedTime') ) {

            $LayoutObject->Block(
                Name => 'TimeUnitsLabelMandatory',
                Data => \%Param,
            );
            $Param{TimeUnitsRequired} = 'Validate_Required';
        }
        elsif ( $Param{ActivityDialogField}->{Config}->{TimeUnits} == 1 ) {

            $LayoutObject->Block(
                Name => 'TimeUnitsLabel',
                Data => \%Param,
            );
            $Param{TimeUnitsRequired} = '';
        }
        else {

            $LayoutObject->Block(
                Name => 'TimeUnitsLabelMandatory',
                Data => \%Param,
            );
            $Param{TimeUnitsRequired} = 'Validate_Required';
        }

        # Get TimeUnits value.
        $Param{TimeUnits} = $Param{GetParam}{TimeUnits};

        $LayoutObject->Block(
            Name => 'TimeUnits',
            Data => \%Param,
        );
    }

    return {
        Success => 1,
        HTML    => $LayoutObject->Output( TemplateFile => 'ProcessManagement/Article' ),
    };
}

sub _RenderCustomer {
    my ( $Self, %Param ) = @_;

    # get layout object
    my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout');

    for my $Needed (qw(FormID)) {
        if ( !$Param{$Needed} ) {
            return {
                Success => 0,
                Message => $LayoutObject->{LanguageObject}->Translate(
                    'Parameter %s is missing in %s.',
                    $Needed,
                    '_RenderCustomer',
                ),
            };
        }
    }
    if ( !IsHashRefWithData( $Param{ActivityDialogField} ) ) {
        return {
            Success => 0,
            Message => $LayoutObject->{LanguageObject}
                ->Translate( 'Parameter %s is missing in %s.', 'ActivityDialogField', '_RenderCustomer' ),
        };
    }

    my %CustomerUserData = ();

    my $SubmittedCustomerUserID = $Param{GetParam}{CustomerUserID};

    my %Data = (
        LabelCustomerUser => $LayoutObject->{LanguageObject}->Translate("Contact"),
        LabelCustomerID   => $LayoutObject->{LanguageObject}->Translate("CustomerID"),
        FormID            => $Param{FormID},
        MandatoryClass    => '',
        ValidateRequired  => '',
    );

    # If field is required put in the necessary variables for
    # ValidateRequired class input field, Mandatory class for the label
    if ( $Param{ActivityDialogField}->{Display} && $Param{ActivityDialogField}->{Display} == 2 ) {
        $Data{ValidateRequired} = 'Validate_Required';
        $Data{MandatoryClass}   = 'Mandatory';
    }

    # output server errors
    if ( IsHashRefWithData( $Param{Error} ) && $Param{Error}->{CustomerUserID} ) {
        $Data{CustomerUserIDServerError} = 'ServerError';
    }
    if ( IsHashRefWithData( $Param{Error} ) && $Param{Error}->{CustomerID} ) {
        $Data{CustomerIDServerError} = 'ServerError';
    }

    # set some customer search autocomplete properties
    $LayoutObject->Block(
        Name => 'CustomerSearchAutoComplete',
    );

    if (
        ( IsHashRefWithData( $Param{Ticket} ) && $Param{Ticket}->{CustomerUserID} )
        || $SubmittedCustomerUserID
    ) {
        %CustomerUserData = $Kernel::OM->Get('Kernel::System::CustomerUser')->CustomerUserDataGet(
            User => $SubmittedCustomerUserID
                || $Param{Ticket}{CustomerUserID},
        );
    }

    # show customer field as "FirstName Lastname" <MailAddress>
    if ( IsHashRefWithData( \%CustomerUserData ) ) {
        $Data{CustomerUserID} = "\"$CustomerUserData{UserFirstname} " .
            "$CustomerUserData{UserLastname}\" <$CustomerUserData{UserEmail}>";
        $Data{CustomerID}           = $CustomerUserData{UserCustomerID} || '';
        $Data{SelectedCustomerUser} = $CustomerUserData{UserID}         || '';
    }

    # When there is no Customer in the DB, it could be unknown Customer, set it from the ticket.
    else {
        $Data{CustomerUserID} = $Param{Ticket}{CustomerUserID} || '';
        $Data{CustomerID}     = $Param{Ticket}{CustomerID}     || '';
    }

    # set fields that will get an AJAX loader icon when this field changes
    my $JSON = $LayoutObject->JSONEncode(
        Data     => $Param{AJAXUpdatableFields},
        NoQuotes => 0,
    );
    $Data{FieldsToUpdate} = $JSON;

    $LayoutObject->Block(
        Name => $Param{ActivityDialogField}->{LayoutBlock} || 'rw:Customer',
        Data => \%Data,
    );

    # set mandatory label marker
    if ( $Data{MandatoryClass} && $Data{MandatoryClass} ne '' ) {
        $LayoutObject->Block(
            Name => 'LabelSpanCustomerUser',
            Data => {},
        );
    }

    if ( $Param{DescriptionShort} ) {
        $LayoutObject->Block(
            Name => $Param{ActivityDialogField}->{LayoutBlock} || 'rw:Customer:DescriptionShort',
            Data => {
                DescriptionShort => $Param{DescriptionShort},
            },
        );
    }

    if ( $Param{DescriptionLong} ) {
        $LayoutObject->Block(
            Name => 'rw:Customer:DescriptionLong',
            Data => {
                DescriptionLong => $Param{DescriptionLong},
            },
        );
    }

    return {
        Success => 1,
        HTML    => $LayoutObject->Output( TemplateFile => 'ProcessManagement/Customer' ),
    };
}

sub _RenderResponsible {
    my ( $Self, %Param ) = @_;

    # get layout object
    my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout');

    for my $Needed (qw(FormID)) {
        if ( !$Param{$Needed} ) {
            return {
                Success => 0,
                Message => $LayoutObject->{LanguageObject}
                    ->Translate( 'Parameter %s is missing in %s.', $Needed, '_RenderResponsible' ),
            };
        }
    }
    if ( !IsHashRefWithData( $Param{ActivityDialogField} ) ) {
        return {
            Success => 0,
            Message => $LayoutObject->{LanguageObject}
                ->Translate( 'Parameter %s is missing in %s.', 'ActivityDialogField', '_RenderResponsible' ),
        };
    }

    my $Responsibles = $Self->_GetResponsibles( %{ $Param{GetParam} } );

    my %Data = (
        Label            => $LayoutObject->{LanguageObject}->Translate("Responsible"),
        FieldID          => 'ResponsibleID',
        FormID           => $Param{FormID},
        ResponsibleAll   => $Param{GetParam}{ResponsibleAll},
        MandatoryClass   => '',
        ValidateRequired => '',
    );

    my $PossibleNone = 1;

    # if field is required put in the necessary variables for
    #    ValidateRequired class input field, Mandatory class for the label
    #    do not allow empty selection
    if ( $Param{ActivityDialogField}->{Display} && $Param{ActivityDialogField}->{Display} == 2 ) {
        $Data{ValidateRequired} = 'Validate_Required';
        $Data{MandatoryClass}   = 'Mandatory';
        $PossibleNone           = 0;
    }

    my $SelectedValue;

    # get user object
    my $UserObject = $Kernel::OM->Get('Kernel::System::User');

    my $ResponsibleIDParam = $Param{GetParam}{ResponsibleID};
    $SelectedValue = $UserObject->UserLookup( UserID => $ResponsibleIDParam )
        if $ResponsibleIDParam;

    if ( $Param{ActivityDialogField}->{DefaultValue} ) {

        if ( $Param{FieldName} eq 'Responsible' ) {

            # Fetch DefaultValue from Config
            if ( !$SelectedValue ) {
                $SelectedValue = $UserObject->UserLookup(
                    UserLogin => $Param{ActivityDialogField}->{DefaultValue} || '',
                );
                if ($SelectedValue) {
                    $SelectedValue = $Param{ActivityDialogField}->{DefaultValue};
                }
            }
        }
        else {
            if ( !$SelectedValue ) {
                $SelectedValue = $UserObject->UserLookup(
                    UserID => $Param{ActivityDialogField}->{DefaultValue} || '',
                );
            }
        }
    }

    # if there is no user from GetParam or default and the field is mandatory get it from the ticket
    #    (if any)
    if (
        !$SelectedValue
        && !$PossibleNone
        && IsHashRefWithData( $Param{Ticket} )
    ) {
        $SelectedValue = $Param{Ticket}->{Responsible};
    }

    # use current user as fallback, for all other cases where there is still no user
    elsif ( !$SelectedValue ) {
        $SelectedValue = $UserObject->UserLookup( UserID => $Self->{UserID} );
    }

    # if we have a user already and the field is not mandatory and it is the same as in ticket, then
    #    set it to none (as it doesn't need to be changed afterall)
    elsif (
        $SelectedValue
        && $PossibleNone
        && IsHashRefWithData( $Param{Ticket} )
        && $SelectedValue eq $Param{Ticket}->{Responsible}
    ) {
        $SelectedValue = '';
    }

    # set server errors
    my $ServerError = '';
    if ( IsHashRefWithData( $Param{Error} ) && $Param{Error}->{'ResponsibleID'} ) {
        $ServerError = 'ServerError';
    }

    # look up $SelectedID
    my $SelectedID;
    if ($SelectedValue) {
        $SelectedID = $UserObject->UserLookup(
            UserLogin => $SelectedValue,
        );
    }

    # build Responsible string
    $Data{Content} = $LayoutObject->BuildSelection(
        Data         => $Responsibles,
        Name         => 'ResponsibleID',
        Translation  => 1,
        SelectedID   => $SelectedID,
        Class        => "Modernize $ServerError",
        PossibleNone => $PossibleNone,
    );

    # set fields that will get an AJAX loader icon when this field changes
    $Data{FieldsToUpdate} = $Self->_GetFieldsToUpdateStrg(
        TriggerField        => 'ResponsibleID',
        AJAXUpdatableFields => $Param{AJAXUpdatableFields},
    );

    $LayoutObject->Block(
        Name => $Param{ActivityDialogField}->{LayoutBlock} || 'rw:Responsible',
        Data => \%Data,
    );

    # set mandatory label marker
    if ( $Data{MandatoryClass} && $Data{MandatoryClass} ne '' ) {
        $LayoutObject->Block(
            Name => 'LabelSpan',
            Data => {},
        );
    }

    if ( $Param{DescriptionShort} ) {
        $LayoutObject->Block(
            Name => $Param{ActivityDialogField}->{LayoutBlock} || 'rw:Responsible:DescriptionShort',
            Data => {
                DescriptionShort => $Param{DescriptionShort},
            },
        );
    }

    if ( $Param{DescriptionLong} ) {
        $LayoutObject->Block(
            Name => 'rw:Responsible:DescriptionLong',
            Data => {
                DescriptionLong => $Param{DescriptionLong},
            },
        );
    }

    return {
        Success => 1,
        HTML    => $LayoutObject->Output( TemplateFile => 'ProcessManagement/Responsible' ),
    };

}

sub _RenderOwner {
    my ( $Self, %Param ) = @_;

    # get layout object
    my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout');

    for my $Needed (qw(FormID)) {
        if ( !$Param{$Needed} ) {
            return {
                Success => 0,
                Message => $LayoutObject->{LanguageObject}
                    ->Translate( 'Parameter %s is missing in %s.', $Needed, '_RenderOwner' ),
            };
        }
    }
    if ( !IsHashRefWithData( $Param{ActivityDialogField} ) ) {
        return {
            Success => 0,
            Message => $LayoutObject->{LanguageObject}
                ->Translate( 'Parameter %s is missing in %s.', 'ActivityDialogField', '_RenderOwner' ),
        };
    }

    my $Owners = $Self->_GetOwners( %{ $Param{GetParam} } );

    my %Data = (
        Label            => $LayoutObject->{LanguageObject}->Translate("Owner"),
        FieldID          => 'OwnerID',
        FormID           => $Param{FormID},
        OwnerAll         => $Param{GetParam}{OwnerAll},
        MandatoryClass   => '',
        ValidateRequired => '',
    );

    my $PossibleNone = 1;

    # if field is required put in the necessary variables for
    #    ValidateRequired class input field, Mandatory class for the label
    #    do not allow empty selection
    if ( $Param{ActivityDialogField}->{Display} && $Param{ActivityDialogField}->{Display} == 2 ) {
        $Data{ValidateRequired} = 'Validate_Required';
        $Data{MandatoryClass}   = 'Mandatory';
        $PossibleNone           = 0;
    }

    my $SelectedValue;

    # get user object
    my $UserObject = $Kernel::OM->Get('Kernel::System::User');

    my $OwnerIDParam = $Param{GetParam}{OwnerID};
    if ($OwnerIDParam) {
        $SelectedValue = $UserObject->UserLookup(
            UserID => $OwnerIDParam,
        );
    }

    if ( $Param{ActivityDialogField}->{DefaultValue} ) {

        if ( $Param{FieldName} eq 'Owner' ) {

            if ( !$SelectedValue ) {

                # Fetch DefaultValue from Config
                $SelectedValue = $UserObject->UserLookup(
                    UserLogin => $Param{ActivityDialogField}->{DefaultValue} || '',
                );
                if ($SelectedValue) {
                    $SelectedValue = $Param{ActivityDialogField}->{DefaultValue};
                }
            }
        }
        else {
            if ( !$SelectedValue ) {
                $SelectedValue = $UserObject->UserLookup(
                    UserID => $Param{ActivityDialogField}->{DefaultValue} || '',
                );
            }
        }
    }

    # if there is no user from GetParam or default and the field is mandatory get it from the ticket
    #    (if any)
    if (
        !$SelectedValue
        && !$PossibleNone
        && IsHashRefWithData( $Param{Ticket} )
    ) {
        $SelectedValue = $Param{Ticket}->{Owner};
    }

    # use current user as fallback, for all other cases where there is still no user
    elsif ( !$SelectedValue ) {
        $SelectedValue = $UserObject->UserLookup( UserID => $Self->{UserID} );
    }

    # if we have a user already and the field is not mandatory and it is the same as in ticket, then
    #    set it to none (as it doesn't need to be changed afterall)
    elsif (
        $SelectedValue
        && $PossibleNone
        && IsHashRefWithData( $Param{Ticket} )
        && $SelectedValue eq $Param{Ticket}->{Owner}
    ) {
        $SelectedValue = '';
    }

    # set server errors
    my $ServerError = '';
    if ( IsHashRefWithData( $Param{Error} ) && $Param{Error}->{'OwnerID'} ) {
        $ServerError = 'ServerError';
    }

    # look up $SelectedID
    my $SelectedID;
    if ($SelectedValue) {
        $SelectedID = $UserObject->UserLookup(
            UserLogin => $SelectedValue,
        );
    }

    # build Owner string
    $Data{Content} = $LayoutObject->BuildSelection(
        Data         => $Owners,
        Name         => 'OwnerID',
        Translation  => 1,
        SelectedID   => $SelectedID || '',
        Class        => "Modernize $ServerError",
        PossibleNone => $PossibleNone,
    );

    # set fields that will get an AJAX loader icon when this field changes
    $Data{FieldsToUpdate} = $Self->_GetFieldsToUpdateStrg(
        TriggerField        => 'OwnerID',
        AJAXUpdatableFields => $Param{AJAXUpdatableFields},
    );

    $LayoutObject->Block(
        Name => $Param{ActivityDialogField}->{LayoutBlock} || 'rw:Owner',
        Data => \%Data,
    );

    # set mandatory label marker
    if ( $Data{MandatoryClass} && $Data{MandatoryClass} ne '' ) {
        $LayoutObject->Block(
            Name => 'LabelSpan',
            Data => {},
        );
    }

    if ( $Param{DescriptionShort} ) {
        $LayoutObject->Block(
            Name => $Param{ActivityDialogField}->{LayoutBlock} || 'rw:Owner:DescriptionShort',
            Data => {
                DescriptionShort => $Param{DescriptionShort},
            },
        );
    }

    if ( $Param{DescriptionLong} ) {
        $LayoutObject->Block(
            Name => 'rw:Owner:DescriptionLong',
            Data => {
                DescriptionLong => $Param{DescriptionLong},
            },
        );
    }

    return {
        Success => 1,
        HTML    => $LayoutObject->Output( TemplateFile => 'ProcessManagement/Owner' ),
    };
}

sub _RenderSLA {
    my ( $Self, %Param ) = @_;

    # get layout object
    my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout');
    my $ConfigObject = $Kernel::OM->Get('Kernel::Config');

    for my $Needed (qw(FormID)) {
        if ( !$Param{$Needed} ) {
            return {
                Success => 0,
                Message => $LayoutObject->{LanguageObject}
                    ->Translate( 'Parameter %s is missing in %s.', $Needed, '_RenderSLA' ),
            };
        }
    }
    if ( !IsHashRefWithData( $Param{ActivityDialogField} ) ) {
        return {
            Success => 0,
            Message => $LayoutObject->{LanguageObject}
                ->Translate( 'Parameter %s is missing in %s.', 'ActivityDialogField', '_RenderSLA' ),
        };
    }

    # create a local copy of the GetParam
    my %GetServicesParam = %{ $Param{GetParam} };

    # use ticket information as a fall back if customer was already set, otherwise when the
    # activity dialog displays the service list will be initially empty, see bug#10059
    if ( IsHashRefWithData( $Param{Ticket} ) ) {
        $GetServicesParam{CustomerUserID} ||= $Param{Ticket}->{CustomerUserID} ||= '';
    }

    my $Services = $Self->_GetServices(
        %GetServicesParam,
    );

    my $SLAs = $Self->_GetSLAs(
        %{ $Param{GetParam} },
        Services => $Services,
    );

    my %Data = (
        Label            => $LayoutObject->{LanguageObject}->Translate("SLA"),
        FieldID          => 'SLAID',
        FormID           => $Param{FormID},
        MandatoryClass   => '',
        ValidateRequired => '',
    );

    # If field is required put in the necessary variables for
    # ValidateRequired class input field, Mandatory class for the label
    if ( $Param{ActivityDialogField}->{Display} && $Param{ActivityDialogField}->{Display} == 2 ) {
        $Data{ValidateRequired} = 'Validate_Required';
        $Data{MandatoryClass}   = 'Mandatory';
    }

    my $SelectedValue;

    # get SLA object
    my $SLAObject = $Kernel::OM->Get('Kernel::System::SLA');

    my $SLAIDParam = $Param{GetParam}{SLAID};
    if ($SLAIDParam) {
        $SelectedValue = $SLAObject->SLALookup( SLAID => $SLAIDParam );
    }

    if ( $Param{FieldName} eq 'SLA' ) {

        if ( !$SelectedValue ) {

            # Fetch DefaultValue from Config
            if (
                defined $Param{ActivityDialogField}->{DefaultValue}
                && $Param{ActivityDialogField}->{DefaultValue} ne ''
            ) {
                $SelectedValue = $SLAObject->SLALookup(
                    SLA => $Param{ActivityDialogField}->{DefaultValue},
                );
            }

            if ($SelectedValue) {
                $SelectedValue = $Param{ActivityDialogField}->{DefaultValue};
            }
        }
    }
    else {
        if ( !$SelectedValue ) {
            if (
                defined $Param{ActivityDialogField}->{DefaultValue}
                && $Param{ActivityDialogField}->{DefaultValue} ne ''
            ) {
                $SelectedValue = $SLAObject->SLALookup(
                    SLA => $Param{ActivityDialogField}->{DefaultValue},
                );
            }
        }
    }

    # Get TicketValue
    if ( IsHashRefWithData( $Param{Ticket} ) && !$SelectedValue ) {
        $SelectedValue = $Param{Ticket}->{SLA};
    }

    # set server errors
    my $ServerError = '';
    if ( IsHashRefWithData( $Param{Error} ) && $Param{Error}->{'SLAID'} ) {
        $ServerError = 'ServerError';
    }

    # build SLA string
    $Data{Content} = $LayoutObject->BuildSelection(
        Data          => $SLAs,
        Name          => 'SLAID',
        SelectedValue => $SelectedValue,
        PossibleNone  => 1,
        Sort          => 'AlphanumericValue',
        Translation   => $ConfigObject->Get('Ticket::SLATranslation') || 0,
        Class         => "Modernize $ServerError",
        Max           => 200,
    );

    # set fields that will get an AJAX loader icon when this field changes
    $Data{FieldsToUpdate} = $Self->_GetFieldsToUpdateStrg(
        TriggerField        => 'SLAID',
        AJAXUpdatableFields => $Param{AJAXUpdatableFields},
    );

    $LayoutObject->Block(
        Name => $Param{ActivityDialogField}->{LayoutBlock} || 'rw:SLA',
        Data => \%Data,
    );

    # set mandatory label marker
    if ( $Data{MandatoryClass} && $Data{MandatoryClass} ne '' ) {
        $LayoutObject->Block(
            Name => 'LabelSpan',
            Data => {},
        );
    }

    if ( $Param{DescriptionShort} ) {
        $LayoutObject->Block(
            Name => $Param{ActivityDialogField}->{LayoutBlock} || 'rw:SLA:DescriptionShort',
            Data => {
                DescriptionShort => $Param{DescriptionShort},
            },
        );
    }

    if ( $Param{DescriptionLong} ) {
        $LayoutObject->Block(
            Name => 'rw:SLA:DescriptionLong',
            Data => {
                DescriptionLong => $Param{DescriptionLong},
            },
        );
    }

    return {
        Success => 1,
        HTML    => $LayoutObject->Output( TemplateFile => 'ProcessManagement/SLA' ),
    };
}

sub _RenderService {
    my ( $Self, %Param ) = @_;

    # get needed objects
    my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout');
    my $ConfigObject = $Kernel::OM->Get('Kernel::Config');

    for my $Needed (qw(FormID)) {
        if ( !$Param{$Needed} ) {
            return {
                Success => 0,
                Message => $LayoutObject->{LanguageObject}
                    ->Translate( 'Parameter %s is missing in %s.', $Needed, '_RenderService' ),
            };
        }
    }
    if ( !IsHashRefWithData( $Param{ActivityDialogField} ) ) {
        return {
            Success => 0,
            Message => $LayoutObject->{LanguageObject}
                ->Translate( 'Parameter %s is missing in %s.', 'ActivityDialogField', '_RenderService' ),
        };
    }

    # create a local copy of the GetParam
    my %GetServicesParam = %{ $Param{GetParam} };

    # use ticket information as a fall back if customer was already set, otherwise when the
    # activity dialog displays the service list will be initially empty, see bug#10059
    if ( IsHashRefWithData( $Param{Ticket} ) ) {
        $GetServicesParam{CustomerUserID} ||= $Param{Ticket}->{CustomerUserID} ||= '';
    }

    my $Services = $Self->_GetServices(
        %GetServicesParam,
    );

    my %Data = (
        Label            => $LayoutObject->{LanguageObject}->Translate("Service"),
        FieldID          => 'ServiceID',
        FormID           => $Param{FormID},
        MandatoryClass   => '',
        ValidateRequired => '',
    );

    # If field is required put in the necessary variables for
    # ValidateRequired class input field, Mandatory class for the label
    if ( $Param{ActivityDialogField}->{Display} && $Param{ActivityDialogField}->{Display} == 2 ) {
        $Data{ValidateRequired} = 'Validate_Required';
        $Data{MandatoryClass}   = 'Mandatory';
    }

    my $SelectedValue;

    # get service object
    my $ServiceObject = $Kernel::OM->Get('Kernel::System::Service');

    my $ServiceIDParam = $Param{GetParam}{ServiceID};
    if ($ServiceIDParam) {
        $SelectedValue = $ServiceObject->ServiceLookup(
            ServiceID => $ServiceIDParam,
        );
    }

    if ( $Param{FieldName} eq 'Service' ) {

        if ( !$SelectedValue ) {

            # Fetch DefaultValue from Config
            if (
                defined $Param{ActivityDialogField}->{DefaultValue}
                && $Param{ActivityDialogField}->{DefaultValue} ne ''
            ) {
                $SelectedValue = $ServiceObject->ServiceLookup(
                    Name => $Param{ActivityDialogField}->{DefaultValue},
                );
            }
            if ($SelectedValue) {
                $SelectedValue = $Param{ActivityDialogField}->{DefaultValue};
            }
        }
    }
    else {
        if ( !$SelectedValue ) {
            if (
                defined $Param{ActivityDialogField}->{DefaultValue}
                && $Param{ActivityDialogField}->{DefaultValue} ne ''
            ) {
                $SelectedValue = $ServiceObject->ServiceLookup(
                    Service => $Param{ActivityDialogField}->{DefaultValue},
                );
            }
        }
    }

    # Get TicketValue
    if ( IsHashRefWithData( $Param{Ticket} ) && !$SelectedValue ) {
        $SelectedValue = $Param{Ticket}->{Service};
    }

    # set server errors
    my $ServerError = '';
    if ( IsHashRefWithData( $Param{Error} ) && $Param{Error}->{'ServiceID'} ) {
        $ServerError = 'ServerError';
    }

    # get list type
    my $TreeView = 0;
    if ( $ConfigObject->Get('Ticket::Frontend::ListType') eq 'tree' ) {
        $TreeView = 1;
    }

    # build Service string
    $Data{Content} = $LayoutObject->BuildSelection(
        Data          => $Services,
        Name          => 'ServiceID',
        Class         => "Modernize $ServerError",
        SelectedValue => $SelectedValue,
        PossibleNone  => 1,
        TreeView      => $TreeView,
        Sort          => 'TreeView',
        Translation   => $ConfigObject->Get('Ticket::ServiceTranslation') || 0,
        Max           => 200,
    );

    # set fields that will get an AJAX loader icon when this field changes
    $Data{FieldsToUpdate} = $Self->_GetFieldsToUpdateStrg(
        TriggerField        => 'ServiceID',
        AJAXUpdatableFields => $Param{AJAXUpdatableFields},
    );

    $LayoutObject->Block(
        Name => $Param{ActivityDialogField}->{LayoutBlock} || 'rw:Service',
        Data => \%Data,
    );

    # set mandatory label marker
    if ( $Data{MandatoryClass} && $Data{MandatoryClass} ne '' ) {
        $LayoutObject->Block(
            Name => 'LabelSpan',
            Data => {},
        );
    }

    if ( $Param{DescriptionShort} ) {
        $LayoutObject->Block(
            Name => $Param{ActivityDialogField}->{LayoutBlock} || 'rw:Service:DescriptionShort',
            Data => {
                DescriptionShort => $Param{DescriptionShort},
            },
        );
    }

    if ( $Param{DescriptionLong} ) {
        $LayoutObject->Block(
            Name => 'rw:Service:DescriptionLong',
            Data => {
                DescriptionLong => $Param{DescriptionLong},
            },
        );
    }

    return {
        Success => 1,
        HTML    => $LayoutObject->Output( TemplateFile => 'ProcessManagement/Service' ),
    };

}

sub _RenderLock {

    # for lock states there's no ACL checking yet implemented so no checking...

    my ( $Self, %Param ) = @_;

    # get layout object
    my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout');

    for my $Needed (qw(FormID)) {
        if ( !$Param{$Needed} ) {
            return {
                Success => 0,
                Message => $LayoutObject->{LanguageObject}
                    ->Translate( 'Parameter %s is missing in %s.', $Needed, '_RenderLock' ),
            };
        }
    }
    if ( !IsHashRefWithData( $Param{ActivityDialogField} ) ) {
        return {
            Success => 0,
            Message => $LayoutObject->{LanguageObject}
                ->Translate( 'Parameter %s is missing in %s.', 'ActivityDialogField', '_RenderLock' ),
        };
    }

    my $Locks = $Self->_GetLocks(
        %{ $Param{GetParam} },
    );

    my %Data = (
        Label            => $LayoutObject->{LanguageObject}->Translate("Lock state"),
        FieldID          => 'LockID',
        FormID           => $Param{FormID},
        MandatoryClass   => '',
        ValidateRequired => '',
    );

    # If field is required put in the necessary variables for
    # ValidateRequired class input field, Mandatory class for the label
    if ( $Param{ActivityDialogField}->{Display} && $Param{ActivityDialogField}->{Display} == 2 ) {
        $Data{ValidateRequired} = 'Validate_Required';
        $Data{MandatoryClass}   = 'Mandatory';
    }

    my $SelectedValue;

    # get lock object
    my $LockObject = $Kernel::OM->Get('Kernel::System::Lock');

    my $LockIDParam = $Param{GetParam}{LockID};
    $SelectedValue = $LockObject->LockLookup( LockID => $LockIDParam )
        if ($LockIDParam);

    if ( $Param{FieldName} eq 'Lock' ) {

        if ( !$SelectedValue ) {

            # Fetch DefaultValue from Config
            $SelectedValue = $LockObject->LockLookup(
                Lock => $Param{ActivityDialogField}->{DefaultValue} || '',
            );
            if ($SelectedValue) {
                $SelectedValue = $Param{ActivityDialogField}->{DefaultValue};
            }
        }
    }
    else {
        $SelectedValue = $LockObject->LockLookup(
            LockID => $Param{ActivityDialogField}->{DefaultValue} || ''
            )
            if !$SelectedValue;
    }

    # Get TicketValue
    if ( IsHashRefWithData( $Param{Ticket} ) && !$SelectedValue ) {
        $SelectedValue = $Param{Ticket}->{Lock};
    }

    # set server errors
    my $ServerError = '';
    if ( IsHashRefWithData( $Param{Error} ) && $Param{Error}->{'LockID'} ) {
        $ServerError = 'ServerError';
    }

    # build lock string
    $Data{Content} = $LayoutObject->BuildSelection(
        Data          => $Locks,
        Name          => 'LockID',
        Translation   => 1,
        SelectedValue => $SelectedValue,
        Class         => "Modernize $ServerError",
    );

    # set fields that will get an AJAX loader icon when this field changes
    $Data{FieldsToUpdate} = $Self->_GetFieldsToUpdateStrg(
        TriggerField        => 'LockID',
        AJAXUpdatableFields => $Param{AJAXUpdatableFields},
    );

    $LayoutObject->Block(
        Name => $Param{ActivityDialogField}->{LayoutBlock} || 'rw:Lock',
        Data => \%Data,
    );

    # set mandatory label marker
    if ( $Data{MandatoryClass} && $Data{MandatoryClass} ne '' ) {
        $LayoutObject->Block(
            Name => 'LabelSpan',
            Data => {},
        );
    }

    if ( $Param{DescriptionShort} ) {
        $LayoutObject->Block(
            Name => $Param{ActivityDialogField}->{LayoutBlock} || 'rw:Lock:DescriptionShort',
            Data => {
                DescriptionShort => $Param{DescriptionShort},
            },
        );
    }

    if ( $Param{DescriptionLong} ) {
        $LayoutObject->Block(
            Name => 'rw:Lock:DescriptionLong',
            Data => {
                DescriptionLong => $Param{DescriptionLong},
            },
        );
    }

    return {
        Success => 1,
        HTML    => $LayoutObject->Output( TemplateFile => 'ProcessManagement/Lock' ),
    };
}

sub _RenderPriority {
    my ( $Self, %Param ) = @_;

    # get layout object
    my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout');

    for my $Needed (qw(FormID)) {
        if ( !$Param{$Needed} ) {
            return {
                Success => 0,
                Message => $LayoutObject->{LanguageObject}
                    ->Translate( 'Parameter %s is missing in %s.', $Needed, '_RenderPriority' ),
            };
        }
    }
    if ( !IsHashRefWithData( $Param{ActivityDialogField} ) ) {
        return {
            Success => 0,
            Message => $LayoutObject->{LanguageObject}
                ->Translate( 'Parameter %s is missing in %s.', 'ActivityDialogField', '_RenderPriority' ),
        };
    }

    my $Priorities = $Self->_GetPriorities(
        %{ $Param{GetParam} },
    );

    my %Data = (
        Label            => $LayoutObject->{LanguageObject}->Translate("Priority"),
        FieldID          => 'PriorityID',
        FormID           => $Param{FormID},
        MandatoryClass   => '',
        ValidateRequired => '',
    );

    # If field is required put in the necessary variables for
    # ValidateRequired class input field, Mandatory class for the label
    if ( $Param{ActivityDialogField}->{Display} && $Param{ActivityDialogField}->{Display} == 2 ) {
        $Data{ValidateRequired} = 'Validate_Required';
        $Data{MandatoryClass}   = 'Mandatory';
    }

    my $SelectedValue;

    # get priority object
    my $PriorityObject = $Kernel::OM->Get('Kernel::System::Priority');

    my $PriorityIDParam = $Param{GetParam}{PriorityID};
    if ($PriorityIDParam) {
        $SelectedValue = $PriorityObject->PriorityLookup(
            PriorityID => $PriorityIDParam,
        );
    }

    if ( $Param{FieldName} eq 'Priority' ) {

        if ( !$SelectedValue ) {

            # Fetch DefaultValue from Config
            $SelectedValue = $PriorityObject->PriorityLookup(
                Priority => $Param{ActivityDialogField}->{DefaultValue} || '',
            );
            if ($SelectedValue) {
                $SelectedValue = $Param{ActivityDialogField}->{DefaultValue};
            }
        }
    }
    else {
        if ( !$SelectedValue ) {
            $SelectedValue = $PriorityObject->PriorityLookup(
                PriorityID => $Param{ActivityDialogField}->{DefaultValue} || '',
            );
        }
    }

    # Get TicketValue
    if ( IsHashRefWithData( $Param{Ticket} ) && !$SelectedValue ) {
        $SelectedValue = $Param{Ticket}->{Priority};
    }

    # set server errors
    my $ServerError = '';
    if ( IsHashRefWithData( $Param{Error} ) && $Param{Error}->{'PriorityID'} ) {
        $ServerError = 'ServerError';
    }

    # build next Priorities string
    $Data{Content} = $LayoutObject->BuildSelection(
        Data          => $Priorities,
        Name          => 'PriorityID',
        Translation   => 1,
        SelectedValue => $SelectedValue,
        Class         => "Modernize $ServerError",
    );

    # set fields that will get an AJAX loader icon when this field changes
    $Data{FieldsToUpdate} = $Self->_GetFieldsToUpdateStrg(
        TriggerField        => 'PriorityID',
        AJAXUpdatableFields => $Param{AJAXUpdatableFields},
    );

    $LayoutObject->Block(
        Name => $Param{ActivityDialogField}->{LayoutBlock} || 'rw:Priority',
        Data => \%Data,
    );

    # set mandatory label marker
    if ( $Data{MandatoryClass} && $Data{MandatoryClass} ne '' ) {
        $LayoutObject->Block(
            Name => 'LabelSpan',
            Data => {},
        );
    }

    if ( $Param{DescriptionShort} ) {
        $LayoutObject->Block(
            Name => $Param{ActivityDialogField}->{LayoutBlock} || 'rw:Priority:DescriptionShort',
            Data => {
                DescriptionShort => $Param{DescriptionShort},
            },
        );
    }

    if ( $Param{DescriptionLong} ) {
        $LayoutObject->Block(
            Name => 'rw:Priority:DescriptionLong',
            Data => {
                DescriptionLong => $Param{DescriptionLong},
            },
        );
    }

    return {
        Success => 1,
        HTML    => $LayoutObject->Output( TemplateFile => 'ProcessManagement/Priority' ),
    };
}

sub _RenderQueue {
    my ( $Self, %Param ) = @_;

    # get layout object
    my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout');

    for my $Needed (qw(FormID)) {
        if ( !$Param{$Needed} ) {
            return {
                Success => 0,
                Message => $LayoutObject->{LanguageObject}
                    ->Translate( 'Parameter %s is missing in %s.', $Needed, '_RenderQueue' ),
            };
        }
    }
    if ( !IsHashRefWithData( $Param{ActivityDialogField} ) ) {
        return {
            Success => 0,
            Message => $LayoutObject->{LanguageObject}
                ->Translate( 'Parameter %s is missing in %s.', 'ActivityDialogField', '_RenderQueue' ),
        };
    }

    my $Queues = $Self->_GetQueues(
        %{ $Param{GetParam} },
    );

    my %Data = (
        Label            => $LayoutObject->{LanguageObject}->Translate("To queue"),
        FieldID          => 'QueueID',
        FormID           => $Param{FormID},
        MandatoryClass   => '',
        ValidateRequired => '',
    );

    # If field is required put in the necessary variables for
    # ValidateRequired class input field, Mandatory class for the label
    if ( $Param{ActivityDialogField}->{Display} && $Param{ActivityDialogField}->{Display} == 2 ) {
        $Data{ValidateRequired} = 'Validate_Required';
        $Data{MandatoryClass}   = 'Mandatory';
    }
    my $SelectedValue;

    # get queue object
    my $QueueObject = $Kernel::OM->Get('Kernel::System::Queue');

    # if we got QueueID as Param from the GUI
    my $QueueIDParam = $Param{GetParam}{QueueID};
    if ($QueueIDParam) {
        $SelectedValue = $QueueObject->QueueLookup(
            QueueID => $QueueIDParam,
        );
    }

    if ( $Param{FieldName} eq 'Queue' ) {

        if ( !$SelectedValue ) {

            # Fetch DefaultValue from Config
            $SelectedValue = $QueueObject->QueueLookup(
                Queue => $Param{ActivityDialogField}->{DefaultValue} || '',
            );
            if ($SelectedValue) {
                $SelectedValue = $Param{ActivityDialogField}->{DefaultValue};
            }
        }
    }
    else {
        if ( !$SelectedValue ) {
            $SelectedValue = $QueueObject->QueueLookup(
                QueueID => $Param{ActivityDialogField}->{DefaultValue} || '',
            );
        }
    }

    # Get TicketValue
    if ( IsHashRefWithData( $Param{Ticket} ) && !$SelectedValue ) {
        $SelectedValue = $Param{Ticket}->{Queue};
    }

    # set server errors
    my $ServerError = '';
    if ( IsHashRefWithData( $Param{Error} ) && $Param{Error}->{'QueueID'} ) {
        $ServerError = 'ServerError';
    }

    # get list type
    my $TreeView = 0;
    if ( $Kernel::OM->Get('Kernel::Config')->Get('Ticket::Frontend::ListType') eq 'tree' ) {
        $TreeView = 1;
    }

    # build next queues string
    $Data{Content} = $LayoutObject->BuildSelection(
        Data          => $Queues,
        Name          => 'QueueID',
        Translation   => 1,
        SelectedValue => $SelectedValue,
        Class         => "Modernize $ServerError",
        TreeView      => $TreeView,
        Sort          => 'TreeView',
        PossibleNone  => 1,
    );

    $Data{FieldsToUpdate} = $Self->_GetFieldsToUpdateStrg(
        TriggerField        => 'QueueID',
        AJAXUpdatableFields => $Param{AJAXUpdatableFields},
    );

    $LayoutObject->Block(
        Name => $Param{ActivityDialogField}->{LayoutBlock} || 'rw:Queue',
        Data => \%Data,
    );

    # set mandatory label marker
    if ( $Data{MandatoryClass} && $Data{MandatoryClass} ne '' ) {
        $LayoutObject->Block(
            Name => 'LabelSpan',
            Data => {},
        );
    }

    if ( $Param{DescriptionShort} ) {
        $LayoutObject->Block(
            Name => $Param{ActivityDialogField}->{LayoutBlock} || 'rw:Queue:DescriptionShort',
            Data => {
                DescriptionShort => $Param{DescriptionShort},
            },
        );
    }

    if ( $Param{DescriptionLong} ) {
        $LayoutObject->Block(
            Name => 'rw:Queue:DescriptionLong',
            Data => {
                DescriptionLong => $Param{DescriptionLong},
            },
        );
    }

    return {
        Success => 1,
        HTML    => $LayoutObject->Output( TemplateFile => 'ProcessManagement/Queue' ),
    };
}

sub _RenderState {
    my ( $Self, %Param ) = @_;

    # get layout object
    my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout');

    for my $Needed (qw(FormID)) {
        if ( !$Param{$Needed} ) {
            return {
                Success => 0,
                Message => $LayoutObject->{LanguageObject}
                    ->Translate( 'Parameter %s is missing in %s.', $Needed, '_RenderState' ),
            };
        }
    }
    if ( !IsHashRefWithData( $Param{ActivityDialogField} ) ) {
        return {
            Success => 0,
            Message => $LayoutObject->{LanguageObject}
                ->Translate( 'Parameter %s is missing in %s.', 'ActivityDialogField', '_RenderState' ),
        };
    }

    my $States = $Self->_GetStates( %{ $Param{GetParam} } );

    my %Data = (
        Label            => $LayoutObject->{LanguageObject}->Translate("Next ticket state"),
        FieldID          => 'StateID',
        FormID           => $Param{FormID},
        MandatoryClass   => '',
        ValidateRequired => '',
    );

    # If field is required put in the necessary variables for
    # ValidateRequired class input field, Mandatory class for the label
    if ( $Param{ActivityDialogField}->{Display} && $Param{ActivityDialogField}->{Display} == 2 ) {
        $Data{ValidateRequired} = 'Validate_Required';
        $Data{MandatoryClass}   = 'Mandatory';
    }
    my $SelectedValue;

    # get state object
    my $StateObject = $Kernel::OM->Get('Kernel::System::State');

    my $StateIDParam = $Param{GetParam}{StateID};
    if ($StateIDParam) {
        $SelectedValue = $StateObject->StateLookup( StateID => $StateIDParam );
    }

    if ( $Param{FieldName} eq 'State' ) {

        if ( !$SelectedValue ) {

            # Fetch DefaultValue from Config
            $SelectedValue = $StateObject->StateLookup(
                State => $Param{ActivityDialogField}->{DefaultValue} || '',
            );
            if ($SelectedValue) {
                $SelectedValue = $Param{ActivityDialogField}->{DefaultValue};
            }
        }
    }
    else {
        if ( !$SelectedValue ) {
            $SelectedValue = $StateObject->StateLookup(
                StateID => $Param{ActivityDialogField}->{DefaultValue} || '',
            );
        }
    }

    # Get TicketValue
    if ( IsHashRefWithData( $Param{Ticket} ) && !$SelectedValue ) {
        $SelectedValue = $Param{Ticket}->{State};
    }

    # set server errors
    my $ServerError = '';
    if ( IsHashRefWithData( $Param{Error} ) && $Param{Error}->{'StateID'} ) {
        $ServerError = 'ServerError';
    }

    # build next states string
    $Data{Content} = $LayoutObject->BuildSelection(
        Data          => $States,
        Name          => 'StateID',
        Translation   => 1,
        SelectedValue => $SelectedValue,
        Class         => "Modernize $ServerError",
    );

    # set fields that will get an AJAX loader icon when this field changes
    $Data{FieldsToUpdate} = $Self->_GetFieldsToUpdateStrg(
        TriggerField        => 'StateID',
        AJAXUpdatableFields => $Param{AJAXUpdatableFields},
    );

    $LayoutObject->Block(
        Name => $Param{ActivityDialogField}->{LayoutBlock} || 'rw:State',
        Data => \%Data,
    );

    # set mandatory label marker
    if ( $Data{MandatoryClass} && $Data{MandatoryClass} ne '' ) {
        $LayoutObject->Block(
            Name => 'LabelSpan',
            Data => {},
        );
    }

    if ( $Param{DescriptionShort} ) {
        $LayoutObject->Block(
            Name => $Param{ActivityDialogField}->{LayoutBlock} || 'rw:State:DescriptionShort',
            Data => {
                DescriptionShort => $Param{DescriptionShort},
            },
        );
    }

    if ( $Param{DescriptionLong} ) {
        $LayoutObject->Block(
            Name => 'rw:State:DescriptionLong',
            Data => {
                DescriptionLong => $Param{DescriptionLong},
            },
        );
    }

    return {
        Success => 1,
        HTML    => $LayoutObject->Output( TemplateFile => 'ProcessManagement/State' ),
    };
}

sub _RenderType {
    my ( $Self, %Param ) = @_;

    # get layout object
    my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout');

    for my $Needed (qw(FormID)) {
        if ( !$Param{$Needed} ) {
            return {
                Success => 0,
                Message => $LayoutObject->{LanguageObject}
                    ->Translate( 'Parameter %s is missing in %s.', $Needed, '_RenderType' ),
            };
        }
    }
    if ( !IsHashRefWithData( $Param{ActivityDialogField} ) ) {
        return {
            Success => 0,
            Message => $LayoutObject->{LanguageObject}
                ->Translate( 'Parameter %s is missing in %s.', 'ActivityDialogField', '_RenderType' ),
        };
    }

    my $Types = $Self->_GetTypes(
        %{ $Param{GetParam} },
    );

    my %Data = (
        Label            => $LayoutObject->{LanguageObject}->Translate("Type"),
        FieldID          => 'TypeID',
        FormID           => $Param{FormID},
        MandatoryClass   => '',
        ValidateRequired => '',
    );

    # If field is required put in the necessary variables for
    # ValidateRequired class input field, Mandatory class for the label
    if ( $Param{ActivityDialogField}->{Display} && $Param{ActivityDialogField}->{Display} == 2 ) {
        $Data{ValidateRequired} = 'Validate_Required';
        $Data{MandatoryClass}   = 'Mandatory';
    }

    my $SelectedValue;

    # get type object
    my $TypeObject = $Kernel::OM->Get('Kernel::System::Type');

    my $TypeIDParam = $Param{GetParam}{TypeID};
    if ($TypeIDParam) {
        $SelectedValue = $TypeObject->TypeLookup(
            TypeID => $TypeIDParam,
        );
    }

    if ( $Param{FieldName} eq 'Type' ) {

        if ( !$SelectedValue ) {

            # Fetch DefaultValue from Config
            if (
                defined $Param{ActivityDialogField}->{DefaultValue}
                && $Param{ActivityDialogField}->{DefaultValue} ne ''
            ) {
                $SelectedValue = $TypeObject->TypeLookup(
                    Type => $Param{ActivityDialogField}->{DefaultValue},
                );
            }
            if ($SelectedValue) {
                $SelectedValue = $Param{ActivityDialogField}->{DefaultValue};
            }
        }
    }
    else {
        if ( !$SelectedValue ) {
            if (
                defined $Param{ActivityDialogField}->{DefaultValue}
                && $Param{ActivityDialogField}->{DefaultValue} ne ''
            ) {
                $SelectedValue = $TypeObject->TypeLookup(
                    Type => $Param{ActivityDialogField}->{DefaultValue},
                );
            }
        }
    }

    # Get TicketValue
    if ( IsHashRefWithData( $Param{Ticket} ) && !$SelectedValue ) {
        $SelectedValue = $Param{Ticket}->{Type};
    }

    # set server errors
    my $ServerError = '';
    if ( IsHashRefWithData( $Param{Error} ) && $Param{Error}->{'TypeID'} ) {
        $ServerError = 'ServerError';
    }

    # build Service string
    $Data{Content} = $LayoutObject->BuildSelection(
        Data          => $Types,
        Name          => 'TypeID',
        Class         => "Modernize $ServerError",
        SelectedValue => $SelectedValue,
        PossibleNone  => 1,
        Sort          => 'AlphanumericValue',
        Translation   => 0,
        Max           => 200,
    );

    # set fields that will get an AJAX loader icon when this field changes
    $Data{FieldsToUpdate} = $Self->_GetFieldsToUpdateStrg(
        TriggerField        => 'TypeID',
        AJAXUpdatableFields => $Param{AJAXUpdatableFields},
    );

    $LayoutObject->Block(
        Name => $Param{ActivityDialogField}->{LayoutBlock} || 'rw:Type',
        Data => \%Data,
    );

    # set mandatory label marker
    if ( $Data{MandatoryClass} && $Data{MandatoryClass} ne '' ) {
        $LayoutObject->Block(
            Name => 'LabelSpan',
            Data => {},
        );
    }

    if ( $Param{DescriptionShort} ) {
        $LayoutObject->Block(
            Name => $Param{ActivityDialogField}->{LayoutBlock} || 'rw:Type:DescriptionShort',
            Data => {
                DescriptionShort => $Param{DescriptionShort},
            },
        );
    }

    if ( $Param{DescriptionLong} ) {
        $LayoutObject->Block(
            Name => 'rw:Type:DescriptionLong',
            Data => {
                DescriptionLong => $Param{DescriptionLong},
            },
        );
    }

    return {
        Success => 1,
        HTML    => $LayoutObject->Output( TemplateFile => 'ProcessManagement/Type' ),
    };
}

sub _StoreActivityDialog {
    my ( $Self, %Param ) = @_;

    my $TicketID       = $Param{GetParam}->{TicketID};
    my $UpdateTicketID = $Param{GetParam}->{TicketID};
    my $ProcessStartpoint;
    my %Ticket;
    my $ProcessEntityID;
    my $ActivityEntityID;
    my %Error;
    my %ErrorMessages;

    my %TicketParam;

    # get layout object
    my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout');

    my $ActivityDialogEntityID = $Param{GetParam}->{ActivityDialogEntityID};
    if ( !$ActivityDialogEntityID ) {
        $LayoutObject->FatalError(
            Message => Translatable('ActivityDialogEntityID missing!'),
        );
    }

    # get activity dialog object
    my $ActivityDialogObject = $Kernel::OM->Get('Kernel::System::ProcessManagement::ActivityDialog');
    my $ActivityDialog       = $ActivityDialogObject->ActivityDialogGet(
        ActivityDialogEntityID => $ActivityDialogEntityID,
        Interface              => 'AgentInterface',
    );

    if ( !IsHashRefWithData($ActivityDialog) ) {
        $LayoutObject->FatalError(
            Message => $LayoutObject->{LanguageObject}->Translate(
                'Couldn\'t get Config for ActivityDialogEntityID "%s"!',
                $ActivityDialogEntityID,
            ),
        );
    }

    # If is an action about attachments
    my $IsUpload = 0;

    # get param object
    my $ParamObject = $Kernel::OM->Get('Kernel::System::Web::Request');

    # attachment delete
    my @AttachmentIDs = ();
    for my $Name ( $ParamObject->GetParamNames() ) {
        if ( $Name =~ m{ \A AttachmentDelete (\d+) \z }xms ) {
            push (@AttachmentIDs, $1);
        };
    }

    # get upload cache object
    my $UploadCacheObject = $Kernel::OM->Get('Kernel::System::Web::UploadCache');

    COUNT:
    for my $Count ( reverse sort @AttachmentIDs ) {
        my $Delete = $ParamObject->GetParam( Param => "AttachmentDelete$Count" );
        next COUNT if !$Delete;
        $UploadCacheObject->FormIDRemoveFile(
            FormID => $Self->{FormID},
            FileID => $Count,
        );
        $IsUpload = 1;
        $Error{AttachmentDelete} = 1;
    }

    # attachment upload
    if ( $ParamObject->GetParam( Param => 'AttachmentUpload' ) ) {
        my %UploadStuff = $ParamObject->GetUploadAll(
            Param => 'FileUpload',
        );
        $UploadCacheObject->FormIDAddFile(
            FormID      => $Self->{FormID},
            Disposition => 'attachment',
            %UploadStuff,
        );
        $IsUpload = 1;
        $Error{AttachmentUpload} = 1;
    }

    # get dynamic field backend object
    my $DynamicFieldBackendObject = $Kernel::OM->Get('Kernel::System::DynamicField::Backend');

    if ( !$IsUpload ) {

        # check each Field of an Activity Dialog and fill the error hash if something goes horribly wrong
        my %CheckedFields;
        DIALOGFIELD:
        for my $CurrentField ( @{ $ActivityDialog->{FieldOrder} } ) {
            if ( $CurrentField =~ m{^DynamicField_(.*)}xms ) {
                my $DynamicFieldName = $1;

                # Get the Config of the current DynamicField (the first element of the grep result array)
                my $DynamicFieldConfig = ( grep { $_->{Name} eq $DynamicFieldName } @{ $Self->{DynamicField} } )[0];

                if ( !IsHashRefWithData($DynamicFieldConfig) ) {

                    my $Message
                        = "DynamicFieldConfig missing for field: $DynamicFieldName, or is not a Ticket Dynamic Field!";

                    # log error but does not stop the execution as it could be an old Article
                    # DynamicField, see bug#11666
                    $Kernel::OM->Get('Kernel::System::Log')->Log(
                        Priority => 'error',
                        Message  => $Message,
                    );

                    next DIALOGFIELD;
                }

                # Will be extended later on for ACL Checking:
                my $PossibleValuesFilter;

                # if we have an invisible field, use config's default value
                if ( $ActivityDialog->{Fields}->{$CurrentField}->{Display} == 0 ) {
                    if (
                        defined $ActivityDialog->{Fields}->{$CurrentField}->{DefaultValue}
                        && length $ActivityDialog->{Fields}->{$CurrentField}->{DefaultValue}
                    ) {
                        $TicketParam{$CurrentField} = $ActivityDialog->{Fields}->{$CurrentField}->{DefaultValue};
                    }
                    else {
                        $TicketParam{$CurrentField} = '';
                    }
# ---
# ITSMIncidentProblemManagement
# ---
                    # make sure ITSMCriticality is stored, even if this field is invisible
                    if ( $DynamicFieldName eq 'ITSMCriticality' ) {
                        $TicketParam{$CurrentField} = $Param{GetParam}->{DynamicField_ITSMCriticality} || $TicketParam{$CurrentField};
                    }
# ---
                }

                # set as empty if field is hidden
                elsif ( !$DynamicFieldConfig->{Shown} ) {
                    $TicketParam{$CurrentField} = '';
                }

                # only validate visible fields
                else {
                    # Check DynamicField Values
                    my $ValidationResult = $DynamicFieldBackendObject->EditFieldValueValidate(
                        DynamicFieldConfig   => $DynamicFieldConfig,
                        PossibleValuesFilter => $PossibleValuesFilter,
                        ParamObject          => $ParamObject,
                        Mandatory            => $ActivityDialog->{Fields}->{$CurrentField}->{Display} == 2,
                    );

                    if ( !IsHashRefWithData($ValidationResult) ) {
                        $LayoutObject->FatalError(
                            Message => $LayoutObject->{LanguageObject}->Translate(
                                'Could not perform validation on field %s!',
                                $DynamicFieldConfig->{Label},
                            ),
                        );
                    }

                    if ( $ValidationResult->{ServerError} ) {
                        $Error{ $DynamicFieldConfig->{Name} }         = 1;
                        $ErrorMessages{ $DynamicFieldConfig->{Name} } = $ValidationResult->{ErrorMessage} || '';
                    }

                    $TicketParam{$CurrentField} =
                        $DynamicFieldBackendObject->EditFieldValueGet(
                        DynamicFieldConfig => $DynamicFieldConfig,
                        ParamObject        => $ParamObject,
                        LayoutObject       => $LayoutObject,
                        );
                }

                # In case of DynamicFields there is no NameToID translation
                # so just take the DynamicField name
                $CheckedFields{$CurrentField} = 1;
            }
            elsif (
                $Self->{NameToID}->{$CurrentField} eq 'CustomerID'
                || $Self->{NameToID}->{$CurrentField} eq 'CustomerUserID'
            ) {

                next DIALOGFIELD if $CheckedFields{ $Self->{NameToID}->{'CustomerID'} };

                # is not possible to a have an invisible field for this particular value
                # on agent interface
                if ( $ActivityDialog->{Fields}->{$CurrentField}->{Display} == 0 ) {
                    $LayoutObject->FatalError(
                        Message => Translatable('Couldn\'t use CustomerID as an invisible field.'),
                        Comment => Translatable('Please contact the administrator.'),
                    );
                }

                # CustomerID should not be mandatory as in other screens
                $TicketParam{CustomerID} = $Param{GetParam}->{CustomerID} || '';

                # Unfortunately TicketCreate needs 'CustomerUser' as param instead of 'CustomerUserID'
                my $CustomerUserID = $ParamObject->GetParam( Param => 'SelectedCustomerUser' );

                # fall-back, if customer auto-complete does not shown any results, then try to use
                # the content of the original field as customer user id
                if ( !$CustomerUserID ) {

                    $CustomerUserID = $ParamObject->GetParam( Param => 'CustomerUserID' );

                    # check email address
                    for my $Email ( Mail::Address->parse($CustomerUserID) ) {
                        if (
                            !$Kernel::OM->Get('Kernel::System::CheckItem')->CheckEmail( Address => $Email->address() )
                        ) {
                            $Error{'CustomerUserID'} = 1;
                        }
                    }
                }

                if ( !$CustomerUserID ) {
                    $Error{'CustomerUserID'} = 1;
                }
                else {
                    $TicketParam{CustomerUser} = $CustomerUserID;
                }
                $CheckedFields{ $Self->{NameToID}->{'CustomerID'} }     = 1;
                $CheckedFields{ $Self->{NameToID}->{'CustomerUserID'} } = 1;

            }
            elsif ( $CurrentField eq 'PendingTime' ) {
                my $Prefix = 'PendingTime';

                # Make sure we have Values otherwise take an empty string
                if (
                    IsHashRefWithData( $Param{GetParam}->{PendingTime} )
                    && defined $Param{GetParam}->{PendingTime}->{Year}
                    && defined $Param{GetParam}->{PendingTime}->{Month}
                    && defined $Param{GetParam}->{PendingTime}->{Day}
                    && defined $Param{GetParam}->{PendingTime}->{Hour}
                    && defined $Param{GetParam}->{PendingTime}->{Minute}
                ) {
                    $TicketParam{$CurrentField} = $Param{GetParam}->{PendingTime};
                }

                # if we have no Pending status we have no time to set
                else {
                    $TicketParam{$CurrentField} = '';
                }
                $CheckedFields{'PendingTime'} = 1;
            }

            else {

                # skip if we've already checked ID or Name
                next DIALOGFIELD if $CheckedFields{ $Self->{NameToID}->{$CurrentField} };

                my $Result = $Self->_CheckField(
                    Field => $Self->{NameToID}->{$CurrentField},
                    %{ $ActivityDialog->{Fields}->{$CurrentField} },
                );

                if ( !$Result ) {

                    # special case for Article (Subject & Body)
                    if ( $CurrentField eq 'Article' ) {
                        for my $ArticlePart (qw(Subject Body)) {
                            if ( !$Param{GetParam}->{$ArticlePart} ) {

                                # set error for each part (if any)
                                $Error{ 'Article' . $ArticlePart } = 1;
                            }
                        }
                    }

                    # all other fields
                    elsif ( $ActivityDialog->{Fields}->{$CurrentField}->{Display} == 2 ) {
                        $Error{ $Self->{NameToID}->{$CurrentField} } = 1;
                    }
                }

                if (
                    $CurrentField eq 'Article'
                    && $ActivityDialog->{Fields}->{$CurrentField}->{Config}->{TimeUnits}
                    && $ActivityDialog->{Fields}->{$CurrentField}->{Config}->{TimeUnits} == 2
                ) {
                    if ( !$Param{GetParam}->{TimeUnits} ) {

                        # set error for the time-units (if any)
                        $Error{'TimeUnits'} = 1;
                    }
                }

                elsif ($Result) {
                    $TicketParam{ $Self->{NameToID}->{$CurrentField} } = $Result;
                }
                $CheckedFields{ $Self->{NameToID}->{$CurrentField} } = 1;
            }
        }
    }

    # get needed objects
    my $ConfigObject = $Kernel::OM->Get('Kernel::Config');
    $Kernel::OM->ObjectParamAdd(
        'Kernel::System::ProcessManagement::Process' => {
            ActivityObject         => $Kernel::OM->Get('Kernel::System::ProcessManagement::Activity'),
            ActivityDialogObject   => $ActivityDialogObject,
            TransitionObject       => $Kernel::OM->Get('Kernel::System::ProcessManagement::Transition'),
            TransitionActionObject => $Kernel::OM->Get('Kernel::System::ProcessManagement::TransitionAction'),
            }
    );
    my $ProcessObject = $Kernel::OM->Get('Kernel::System::ProcessManagement::Process');
    my $TicketObject  = $Kernel::OM->Get('Kernel::System::Ticket');

    my @Notify;

    if ( !$TicketID ) {

        $ProcessEntityID = $Param{GetParam}->{ProcessEntityID};
        if ( !$ProcessEntityID ) {
            return $LayoutObject->FatalError(
                Message => Translatable('Missing ProcessEntityID, check your ActivityDialogHeader.tt!'),
            );
        }

        $ProcessStartpoint = $ProcessObject->ProcessStartpointGet(
            ProcessEntityID => $Param{ProcessEntityID},
        );

        if (
            !$ProcessStartpoint
            || !IsHashRefWithData($ProcessStartpoint)
            || !$ProcessStartpoint->{Activity} || !$ProcessStartpoint->{ActivityDialog}
        ) {
            $LayoutObject->FatalError(
                Message => $LayoutObject->{LanguageObject}->Translate(
                    'No StartActivityDialog or StartActivityDialog for Process "%s" configured!',
                    $Param{ProcessEntityID},
                ),
            );
        }

        $ActivityEntityID = $ProcessStartpoint->{Activity};

        NEEDEDLOOP:
        for my $Needed (qw(Queue State Lock Priority)) {

            if ( !$TicketParam{ $Self->{NameToID}->{$Needed} } ) {

                # if a required field has no value call _CheckField as filed is hidden
                # (No Display param = Display => 0) and no DefaultValue, to use global default as
                # fall-back. One reason for this to happen is that ActivityDialog DefaultValue tried
                # to set before, was not valid.
                my $Result = $Self->_CheckField(
                    Field => $Self->{NameToID}->{$Needed},
                );

                if ( !$Result ) {
                    $Error{ $Self->{NameToID}->{$Needed} } = ' ServerError';
                }
                elsif ($Result) {
                    $TicketParam{ $Self->{NameToID}->{$Needed} } = $Result;
                }
            }
        }

        # If we had no Errors, we can create the Ticket and Set ActivityEntityID as well as
        # ProcessEntityID
        if ( !IsHashRefWithData( \%Error ) ) {

            $TicketParam{UserID} = $Self->{UserID};

            if ( !$TicketParam{OwnerID} ) {

                $TicketParam{OwnerID} = $Param{GetParam}->{OwnerID} || 1;
            }

            # if StartActivityDialog does not provide a ticket title set a default value
            if ( !$TicketParam{Title} ) {

                # get the current server Timestamp
                my $CurrentTimeStamp = $Kernel::OM->Get('Kernel::System::Time')->CurrentTimestamp();
                $TicketParam{Title} = "$Param{ProcessName} - $CurrentTimeStamp";

                # use article subject from the web request if any
                if ( IsStringWithData( $Param{GetParam}->{Subject} ) ) {
                    $TicketParam{Title} = $Param{GetParam}->{Subject};
                }
            }

            # create a new ticket
            $TicketID = $TicketObject->TicketCreate(%TicketParam);

            if ( !$TicketID ) {
                $LayoutObject->FatalError(
                    Message => $LayoutObject->{LanguageObject}->Translate(
                        'Couldn\'t create ticket for Process with ProcessEntityID "%s"!',
                        $Param{ProcessEntityID},
                    ),
                );
            }

            my $Success = $ProcessObject->ProcessTicketProcessSet(
                ProcessEntityID => $Param{ProcessEntityID},
                TicketID        => $TicketID,
                UserID          => $Self->{UserID},
            );
            if ( !$Success ) {
                $LayoutObject->FatalError(
                    Message => $LayoutObject->{LanguageObject}->Translate(
                        'Couldn\'t set ProcessEntityID "%s" on TicketID "%s"!',
                        $Param{ProcessEntityID},
                        $TicketID,
                    ),
                );
            }

            $Success = undef;

            $Success = $ProcessObject->ProcessTicketActivitySet(
                ProcessEntityID  => $Param{ProcessEntityID},
                ActivityEntityID => $ProcessStartpoint->{Activity},
                TicketID         => $TicketID,
                UserID           => $Self->{UserID},
            );

            if ( !$Success ) {
                $LayoutObject->FatalError(
                    Message => $LayoutObject->{LanguageObject}->Translate(
                        'Couldn\'t set ActivityEntityID "%s" on TicketID "%s"!',
                        $Param{ProcessEntityID},
                        $TicketID,
                    ),
                    Comment => Translatable('Please contact the administrator.'),
                );
            }

            %Ticket = $TicketObject->TicketGet(
                TicketID      => $TicketID,
                UserID        => $Self->{UserID},
                DynamicFields => 1,
            );

            if ( !IsHashRefWithData( \%Ticket ) ) {
                $LayoutObject->FatalError(
                    Message => $LayoutObject->{LanguageObject}->Translate(
                        'Could not store ActivityDialog, invalid TicketID: %s!',
                        $TicketID,
                    ),
                    Comment => Translatable('Please contact the administrator.'),
                );
            }

            for my $FieldName ( @{ $ActivityDialog->{FieldOrder} } ) {
                if ( $FieldName =~ m/^DynamicField_(.*)/xms ) {
                    my $Field = $1;
                    DFCONFIG:
                    for my $DynamicFieldConfig ( @{ $Self->{DynamicField} } ) {
                        if ( $Field eq $DynamicFieldConfig->{Name} ) {
                            # and now it's easy, just store the dynamic Field Values ;)
                            $DynamicFieldBackendObject->ValueSet(
                                DynamicFieldConfig => $DynamicFieldConfig,
                                ObjectID           => $TicketID,
                                Value              => $TicketParam{ 'DynamicField_' . $DynamicFieldConfig->{Name} },
                                UserID             => $Self->{UserID},
                            );
                            last DFCONFIG;
                        }
                    }
                }
            }
        }
    }

    elsif ( $TicketID && $Self->{IsProcessEnroll} ) {

        # use Error instead of FatalError as we are in a Pop-up window
        # Get Ticket to check TicketID was valid
        %Ticket = $TicketObject->TicketGet(
            TicketID      => $TicketID,
            UserID        => $Self->{UserID},
            DynamicFields => 0,
        );

        if ( !IsHashRefWithData( \%Ticket ) ) {
            $LayoutObject->Error(
                Message => $LayoutObject->{LanguageObject}->Translate( 'Invalid TicketID: %s!', $TicketID ),
            );
        }

        my $Success = $ProcessObject->ProcessTicketProcessSet(
            ProcessEntityID => $Param{ProcessEntityID},
            TicketID        => $TicketID,
            UserID          => $Self->{UserID},
        );
        if ( !$Success ) {
            $LayoutObject->Error(
                Message => $LayoutObject->{LanguageObject}->Translate(
                    'Couldn\'t set ProcessEntityID "%s" on TicketID "%s"!',
                    $Param{ProcessEntityID},
                    $TicketID,
                ),
            );
        }

        $Success = undef;

        $ProcessStartpoint = $ProcessObject->ProcessStartpointGet(
            ProcessEntityID => $Param{ProcessEntityID},
        );

        if (
            !$ProcessStartpoint
            || !IsHashRefWithData($ProcessStartpoint)
            || !$ProcessStartpoint->{Activity} || !$ProcessStartpoint->{ActivityDialog}
        ) {
            $LayoutObject->Error(
                Message => $LayoutObject->{LanguageObject}->Translate(
                    'No StartActivityDialog or StartActivityDialog for Process "%s" configured!',
                    $Param{ProcessEntityID},
                ),
            );
        }

        $Success = $ProcessObject->ProcessTicketActivitySet(
            ProcessEntityID  => $Param{ProcessEntityID},
            ActivityEntityID => $ProcessStartpoint->{Activity},
            TicketID         => $TicketID,
            UserID           => $Self->{UserID},
        );

        if ( !$Success ) {
            $LayoutObject->Error(
                Message => $LayoutObject->{LanguageObject}->Translate(
                    'Couldn\'t set ActivityEntityID "%s" on TicketID "%s"!',
                    $Param{ProcessEntityID},
                    $TicketID,
                ),
                Comment => Translatable('Please contact the administrator.'),
            );
        }

        # use ProcessEntityID from the web request
        $ProcessEntityID = $Param{ProcessEntityID};

        # Check if we deal with a Ticket Update
        $UpdateTicketID = $TicketID;
    }

    # If we had a TicketID, get the Ticket
    else {

        # Get Ticket to check TicketID was valid
        %Ticket = $TicketObject->TicketGet(
            TicketID      => $TicketID,
            UserID        => $Self->{UserID},
            DynamicFields => 1,
        );

        if ( !IsHashRefWithData( \%Ticket ) ) {
            $LayoutObject->FatalError(
                Message => $LayoutObject->{LanguageObject}->Translate(
                    'Could not store ActivityDialog, invalid TicketID: %s!',
                    $TicketID,
                ),
            );
        }

        $ActivityEntityID = $Ticket{
            'DynamicField_'
                . $ConfigObject->Get('Process::DynamicFieldProcessManagementActivityID')
        };
        if ( !$ActivityEntityID ) {

            return $Self->_ShowDialogError(
                Message => $LayoutObject->{LanguageObject}->Translate(
                    'Missing ActivityEntityID in Ticket %s!',
                    $Ticket{TicketID},
                ),
                Comment => Translatable('Please contact the administrator.'),
            );
        }

        # Make sure the activity dialog to save is still the correct activity
        my $Activity = $Kernel::OM->Get('Kernel::System::ProcessManagement::Activity')->ActivityGet(
            ActivityEntityID => $ActivityEntityID,
            Interface        => ['AgentInterface'],
        );
        my %ActivityDialogs = reverse %{ $Activity->{ActivityDialog} // {} };
        if ( !$ActivityDialogs{$ActivityDialogEntityID} ) {
            my $TicketHook        = $ConfigObject->Get('Ticket::Hook');
            my $TicketHookDivider = $ConfigObject->Get('Ticket::HookDivider');

            $Error{WrongActivity} = 1;
            push @Notify, {
                Priority => 'Error',
                Data     => $LayoutObject->{LanguageObject}->Translate(
                    'This step does not belong anymore to the current activity in process for ticket \'%s%s%s\'! Another user changed this ticket in the meantime. Please close this window and reload the ticket.',
                    $TicketHook,
                    $TicketHookDivider,
                    $Ticket{TicketNumber},
                ),
            };
        }

        $ProcessEntityID = $Ticket{
            'DynamicField_'
                . $ConfigObject->Get('Process::DynamicFieldProcessManagementProcessID')
        };

        if ( !$ProcessEntityID ) {
            return $Self->_ShowDialogError(
                Message => $LayoutObject->{LanguageObject}->Translate(
                    'Missing ProcessEntityID in Ticket %s!',
                    $Ticket{TicketID},
                ),
                Comment => Translatable('Please contact the administrator.'),
            );
        }
    }

    # if we got errors go back to displaying the ActivityDialog
    if ( $IsUpload || IsHashRefWithData( \%Error ) ) {
        return $Self->_OutputActivityDialog(
            ProcessEntityID        => $ProcessEntityID,
            TicketID               => $TicketID || undef,
            ActivityDialogEntityID => $ActivityDialogEntityID,
            Error                  => \%Error,
            ErrorMessages          => \%ErrorMessages,
            GetParam               => $Param{GetParam},
            IsUpload               => $IsUpload,
            Notify                 => \@Notify,
        );
    }

    # We save only once, no matter if one or more configurations are set for the same param
    my %StoredFields;

    # Save loop for storing Ticket Values that were not required on the initial TicketCreate
    DIALOGFIELD:
    for my $CurrentField ( @{ $ActivityDialog->{FieldOrder} } ) {

        if ( !IsHashRefWithData( $ActivityDialog->{Fields}->{$CurrentField} ) ) {
            $LayoutObject->FatalError(
                Message => $LayoutObject->{LanguageObject}->Translate(
                    'Can\'t get data for Field "%s" of ActivityDialog "%s"!',
                    $CurrentField,
                    $ActivityDialogEntityID,
                ),
            );
        }

        next DIALOGFIELD if defined $Self->{NameToID}{$CurrentField} && $Self->{NameToID}{$CurrentField} eq 'horizontalline';

        if ( $CurrentField =~ m{^DynamicField_(.*)}xms ) {
            my $DynamicFieldName = $1;

            my $DynamicFieldConfig = ( grep { $_->{Name} eq $DynamicFieldName } @{ $Self->{DynamicField} } )[0];

            if ( !IsHashRefWithData($DynamicFieldConfig) ) {

                my $Message
                    = "DynamicFieldConfig missing for field: $Param{FieldName}, or is not a Ticket Dynamic Field!";

                # log error but does not stop the execution as it could be an old Article
                # DynamicField, see bug#11666
                $Kernel::OM->Get('Kernel::System::Log')->Log(
                    Priority => 'error',
                    Message  => $Message,
                );

                next DIALOGFIELD;
            }

            my $Success = $DynamicFieldBackendObject->ValueSet(
                DynamicFieldConfig => $DynamicFieldConfig,
                ObjectID           => $TicketID,
                Value              => $TicketParam{$CurrentField},
                UserID             => $Self->{UserID},
            );
            if ( !$Success ) {
                $LayoutObject->FatalError(
                    Message => $LayoutObject->{LanguageObject}->Translate(
                        'Could not set DynamicField value for %s of Ticket with ID "%s" in ActivityDialog "%s"!',
                        $CurrentField,
                        $TicketID,
                        $ActivityDialogEntityID,
                    ),
                );
            }
        }
        elsif ( $CurrentField eq 'PendingTime' ) {

            # This Value is just set if Status was on a Pending state
            # so it has to be possible to store the ticket if this one's empty
            if ( IsHashRefWithData( $TicketParam{'PendingTime'} ) ) {
                my $Success = $TicketObject->TicketPendingTimeSet(
                    UserID   => $Self->{UserID},
                    TicketID => $TicketID,
                    %{ $TicketParam{'PendingTime'} },
                );
                if ( !$Success ) {
                    $LayoutObject->FatalError(
                        Message => $LayoutObject->{LanguageObject}->Translate(
                            'Could not set PendingTime for Ticket with ID "%s" in ActivityDialog "%s"!',
                            $TicketID,
                            $ActivityDialogEntityID,
                        ),
                    );
                }
            }
        }

        elsif ( $CurrentField eq 'Article' ) {

            if ( $Param{GetParam}->{Subject} && $Param{GetParam}->{Body} ) {

                # add note
                my $ArticleID = '';
                my $MimeType  = 'text/plain';
                if ( $LayoutObject->{BrowserRichText} ) {
                    $MimeType = 'text/html';

                    # verify html document
                    $Param{GetParam}->{Body} = $LayoutObject->RichTextDocumentComplete(
                        String => $Param{GetParam}->{Body},
                    );
                }

                # Change history type and comment accordingly to the process article.
                my $ArticleType = $ActivityDialog->{Fields}->{Article}->{Config}->{ArticleType};
                my $HistoryType;
                my $HistoryComment = '';
                if ( $ArticleType eq 'phone' ) {
                    $HistoryType = 'PhoneCallAgent';
                }
                else {
                    $HistoryType    = 'AddNote';
                    $HistoryComment = 'Note';
                }

                my $From = "\"$Self->{UserFirstname} $Self->{UserLastname}\" <$Self->{UserEmail}>";
                $ArticleID = $TicketObject->ArticleCreate(
                    TicketID                  => $TicketID,
                    SenderType                => 'agent',
                    From                      => $From,
                    MimeType                  => $MimeType,
                    Charset                   => $LayoutObject->{UserCharset},
                    UserID                    => $Self->{UserID},
                    HistoryType               => $HistoryType,
                    HistoryComment            => '%%' . $HistoryComment,
                    Body                      => $Param{GetParam}->{Body},
                    Subject                   => $Param{GetParam}->{Subject},
                    ArticleType               => $ArticleType,
                    ForceNotificationToUserID => $ActivityDialog->{Fields}->{Article}->{Config}->{InformAgents}
                    ? $Param{GetParam}{InformUserID}
                    : [],
                );
                if ( !$ArticleID ) {
                    return $LayoutObject->ErrorScreen();
                }

                # get pre loaded attachment
                my @Attachments = $UploadCacheObject->FormIDGetAllFilesData(
                    FormID => $Self->{FormID},
                );

                # get submit attachment
                my %UploadStuff = $ParamObject->GetUploadAll(
                    Param => 'FileUpload',
                );
                if (%UploadStuff) {
                    push @Attachments, \%UploadStuff;
                }

                # write attachments
                ATTACHMENT:
                for my $Attachment (@Attachments) {

                    # skip, deleted not used inline images
                    my $ContentID = $Attachment->{ContentID};
                    if (
                        $ContentID
                        && ( $Attachment->{ContentType} =~ /image/i )
                        && ( $Attachment->{Disposition} eq 'inline' )
                    ) {
                        my $ContentIDHTMLQuote = $LayoutObject->Ascii2Html(
                            Text => $ContentID,
                        );

                        # workaround for link encode of rich text editor, see bug#5053
                        my $ContentIDLinkEncode = $LayoutObject->LinkEncode($ContentID);
                        $Param{GetParam}->{Body} =~ s/(ContentID=)$ContentIDLinkEncode/$1$ContentID/g;

                        # ignore attachment if not linked in body
                        if ( $Param{GetParam}->{Body} !~ /(?:\Q$ContentIDHTMLQuote\E|\Q$ContentID\E)/i ) {
                            next ATTACHMENT;
                        }
                    }

                    # write existing file to backend
                    $TicketObject->ArticleWriteAttachment(
                        %{$Attachment},
                        ArticleID => $ArticleID,
                        UserID    => $Self->{UserID},
                    );
                }

                # remove pre submitted attachments
                $UploadCacheObject->FormIDRemove( FormID => $Self->{FormID} );

                # time accounting
                if ( $Param{GetParam}->{TimeUnits} ) {
                    $TicketObject->TicketAccountTime(
                        TicketID  => $TicketID,
                        ArticleID => $ArticleID,
                        TimeUnit  => $Param{GetParam}{TimeUnits},
                        UserID    => $Self->{UserID},
                    );
                }
            }
        }

        # If we have to Update a ticket, update the transmitted values
        elsif ($UpdateTicketID) {

            my $Success;
            if ( $Self->{NameToID}->{$CurrentField} eq 'Title' ) {

                # if there is no title, nothing is needed to be done
                if (
                    !defined $TicketParam{'Title'}
                    || ( defined $TicketParam{'Title'} && $TicketParam{'Title'} eq '' )
                ) {
                    $Success = 1;
                }

                # otherwise set the ticket title
                else {
                    $Success = $TicketObject->TicketTitleUpdate(
                        Title    => $TicketParam{'Title'},
                        TicketID => $TicketID,
                        UserID   => $Self->{UserID},
                    );
                }
            }
            elsif (
                (
                    $Self->{NameToID}->{$CurrentField} eq 'CustomerID'
                    || $Self->{NameToID}->{$CurrentField} eq 'CustomerUserID'
                )
            ) {
                next DIALOGFIELD if $StoredFields{ $Self->{NameToID}->{$CurrentField} };

                if ( $ActivityDialog->{Fields}->{$CurrentField}->{Display} == 1 ) {
                    $LayoutObject->FatalError(
                        Message => $LayoutObject->{LanguageObject}->Translate(
                            'Wrong ActivityDialog Field config: %s can\'t be Display => 1 / Show field (Please change its configuration to be Display => 0 / Do not show field or Display => 2 / Show field as mandatory)!',
                            $CurrentField,
                        ),
                    );
                }

                # skip TicketCustomerSet() if there is no change in the customer
                if (
                    $Ticket{CustomerID} eq $TicketParam{CustomerID}
                    && $Ticket{CustomerUserID} eq $TicketParam{CustomerUser}
                ) {

                    # In this case we don't want to call any additional stores
                    # on Customer, CustomerNo, CustomerID or CustomerUserID
                    # so make sure both fields are set to "Stored" ;)
                    $StoredFields{ $Self->{NameToID}->{'CustomerID'} }     = 1;
                    $StoredFields{ $Self->{NameToID}->{'CustomerUserID'} } = 1;
                    next DIALOGFIELD;
                }

                $Success = $TicketObject->TicketCustomerSet(
                    No => $TicketParam{CustomerID},

                    # here too: unfortunately TicketCreate takes Param 'CustomerUser'
                    # instead of CustomerUserID, so our TicketParam hash
                    # has the CustomerUser Key instead of 'CustomerUserID'
                    User     => $TicketParam{CustomerUser},
                    TicketID => $TicketID,
                    UserID   => $Self->{UserID},
                );

                # In this case we don't want to call any additional stores
                # on Customer, CustomerNo, CustomerID or CustomerUserID
                # so make sure both fields are set to "Stored" ;)
                $StoredFields{ $Self->{NameToID}->{'CustomerID'} }     = 1;
                $StoredFields{ $Self->{NameToID}->{'CustomerUserID'} } = 1;
            }
            else {
                next DIALOGFIELD if $StoredFields{ $Self->{NameToID}->{$CurrentField} };

                my $TicketFieldSetSub = $CurrentField;
                $TicketFieldSetSub =~ s{ID$}{}xms;
                $TicketFieldSetSub = 'Ticket' . $TicketFieldSetSub . 'Set';

                if ( $TicketObject->can($TicketFieldSetSub) ) {
                    my $UpdateFieldName;

                    # sadly we need an exception for Owner(ID) and Responsible(ID), because the
                    # Ticket*Set subs need NewUserID as param
                    if (
                        scalar grep { $Self->{NameToID}->{$CurrentField} eq $_ }
                        qw( OwnerID ResponsibleID )
                    ) {
                        $UpdateFieldName = 'NewUserID';
                    }
                    else {
                        $UpdateFieldName = $Self->{NameToID}->{$CurrentField};
                    }

                    # to store if the field needs to be updated
                    my $FieldUpdate;

                    # only Service and SLA fields accepts empty values if the hash key is not
                    # defined set it to empty so the Ticket*Set function call will get the empty
                    # value
                    if (
                        ( $UpdateFieldName eq 'ServiceID' || $UpdateFieldName eq 'SLAID' )
                        && !defined $TicketParam{ $Self->{NameToID}->{$CurrentField} }
                    ) {
                        $TicketParam{ $Self->{NameToID}->{$CurrentField} } = '';
                        $FieldUpdate = 1;
                    }

                    # update Service an SLA fields if they have a defined value (even empty)
                    elsif ( $UpdateFieldName eq 'ServiceID' || $UpdateFieldName eq 'SLAID' ) {
                        $FieldUpdate = 1;
                    }

                    # update any other field that its value is defined and not empty
                    elsif (
                        $UpdateFieldName ne 'ServiceID'
                        && $UpdateFieldName ne 'SLAID'
                        && defined $TicketParam{ $Self->{NameToID}->{$CurrentField} }
                        && $TicketParam{ $Self->{NameToID}->{$CurrentField} } ne ''
                    ) {
                        $FieldUpdate = 1;
                    }

                    $Success = 1;

                    # check if field needs to be updated
                    if ($FieldUpdate) {
                        $Success = $TicketObject->$TicketFieldSetSub(
                            $UpdateFieldName => $TicketParam{ $Self->{NameToID}->{$CurrentField} },
                            TicketID         => $TicketID,
                            UserID           => $Self->{UserID},
                        );

                        # in case of a new service and no new SLA is to be set, check if current
                        # assigned SLA is still valid
                        if (
                            $UpdateFieldName eq 'ServiceID'
                            && !defined $TicketParam{SLAID}
                        ) {
                            # get ticket details
                            %Ticket = $TicketObject->TicketGet(
                                TicketID      => $TicketID,
                                DynamicFields => 0,
                                UserID        => $Self->{UserID},
                            );

                            # if ticket already have an SLA assigned get the list SLAs for the new
                            # service
                            if ( IsPositiveInteger( $Ticket{SLAID} ) ) {
                                my %SLAList = $Kernel::OM->Get('Kernel::System::SLA')->SLAList(
                                    ServiceID => $TicketParam{ $Self->{NameToID}->{$CurrentField} },
                                    UserID    => $Self->{UserID},
                                );

                                # if the current SLA is not in the list of SLA for new service
                                # remove SLA from ticket
                                if ( !$SLAList{ $Ticket{SLAID} } ) {
                                    $TicketObject->TicketSLASet(
                                        SLAID    => '',
                                        TicketID => $TicketID,
                                        UserID   => $Self->{UserID},
                                    );
                                }
                            }
                        }
                    }
                }
            }
            if ( !$Success ) {
                $LayoutObject->FatalError(
                    Message => $LayoutObject->{LanguageObject}->Translate(
                        'Could not set %s for Ticket with ID "%s" in ActivityDialog "%s"!',
                        $CurrentField,
                        $TicketID,
                        $ActivityDialogEntityID,
                    ),
                );
            }
        }
    }

    # Transitions will be handled by ticket event module (TicketProcessTransitions.pm).

    # if we were updating a ticket, close the popup and return to zoom
    # else (new ticket) just go to zoom to show the new ticket
    if ($UpdateTicketID) {

        # load new URL in parent window and close popup
        return $LayoutObject->PopupClose(
            URL => "Action=AgentTicketZoom;TicketID=$TicketID",
        );
    }

    return $LayoutObject->Redirect(
        OP => "Action=AgentTicketZoom;TicketID=$TicketID",
    );
}

sub _DisplayProcessList {
    my ( $Self, %Param ) = @_;

    # If we have a ProcessEntityID
    $Param{Errors}->{ProcessEntityIDInvalid} = ' ServerError'
        if ( $Param{ProcessEntityID} && !$Param{ProcessList}->{ $Param{ProcessEntityID} } );

    # get layout object
    my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout');

    $Param{ProcessList} = $LayoutObject->BuildSelection(
        Class        => 'Modernize Validate_Required' . ( $Param{Errors}->{ProcessEntityIDInvalid} || ' ' ),
        Data         => $Param{ProcessList},
        Name         => 'ProcessEntityID',
        SelectedID   => $Param{ProcessEntityID},
        PossibleNone => 1,
        Sort         => 'AlphanumericValue',
        Translation  => 1,
        AutoComplete => 'off',
    );

    # add rich text editor
    if ( $LayoutObject->{BrowserRichText} ) {

        # use height/width defined for this screen
        $Param{RichTextHeight} = $Self->{Config}->{RichTextHeight} || 0;
        $Param{RichTextWidth}  = $Self->{Config}->{RichTextWidth}  || 0;

        $LayoutObject->Block(
            Name => 'RichText',
            Data => \%Param,
        );
    }

    if ( $Param{PreSelectProcess} && $Param{ProcessID} ) {
        $LayoutObject->Block(
            Name => 'PreSelectProcess',
            Data => {
                ProcessID => $Param{ProcessID},
            },
        );
    }

    $LayoutObject->Block(
        Name => 'ProcessList',
        Data => {
            %Param,
            FormID => $Self->{FormID},
        },
    );

    # on initial screen from navbar there is no IsMainWinow but also no IsProcessEnroll,
    # then it must be a MainWindow
    if ( !$Self->{IsMainWindow} && !$Self->{IsProcessEnroll} ) {
        $Self->{IsMainWindow} = 1;
    }

    my $Type = $Self->{IsMainWindow} ? '' : 'Small';

    my $Output = $LayoutObject->Header(
        Type => $Type,
    );
    if ( $Self->{IsMainWindow} ) {
        $Output .= $LayoutObject->NavigationBar();
    }

    $Output .= $LayoutObject->Output(
        TemplateFile => 'AgentTicketProcess' . $Type,
        Data         => {
            %Param,
            FormID          => $Self->{FormID},
            IsProcessEnroll => $Self->{IsProcessEnroll},
        },
    );

    # workaround when activity dialog is loaded by AJAX as first activity dialog, if there is
    # a date field like Pending Time or Dynamic Fields Date/Time or Date, there is no way to set
    # this options in the footer again
    $LayoutObject->{HasDatepicker} = 1;

    $Output .= $LayoutObject->Footer( Type => $Type );

    return $Output;
}

# =item _CheckField()
#
# checks all the possible ticket fields and returns the ID (if possible) value of the field, if valid
# and checks are successful
#
# if Display param is set to 0 or not given, it uses ActivityDialog field default value for all fields
# or global default value as fall-back only for certain fields
#
# if Display param is set to 1 or 2 it uses the value from the web request
#
#     my $PriorityID = $AgentTicketProcessObject->_CheckField(
#         Field        => 'PriorityID',
#         Display      => 1,                   # optional, 0 or 1 or 2
#         DefaultValue => '3 normal',          # ActivityDialog field default value (it uses global
#                                              #    default value as fall back for mandatory fields
#                                              #    (Queue, Sate, Lock and Priority)
#     );
#
# Returns:
#     $PriorityID = 1;                         # if PriorityID is set to 1 in the web request
#
#     my $PriorityID = $AgentTicketProcessObject->_CheckField(
#         Field        => 'PriorityID',
#         Display      => 0,
#         DefaultValue => '3 normal',
#     );
#
# Returns:
#     $PriorityID = 3;                        # since ActivityDialog default value is '3 normal' and
#                                             #     field is hidden
#
# =cut

sub _CheckField {
    my ( $Self, %Param ) = @_;

    # check needed stuff
    for my $Needed (qw(Field)) {
        if ( !$Param{$Needed} ) {
            $Kernel::OM->Get('Kernel::System::Log')->Log(
                Priority => 'error',
                Message  => "Need $Needed!"
            );
            return;
        }
    }

    # remove the ID and check if the given field is required for creating a ticket
    my $FieldWithoutID = $Param{Field};
    $FieldWithoutID =~ s{ID$}{}xms;
    my $TicketRequiredField = scalar grep { $_ eq $FieldWithoutID } qw(Queue State Lock Priority);

    my $Value;

    # get needed objects
    my $ParamObject  = $Kernel::OM->Get('Kernel::System::Web::Request');
    my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout');

    # if no Display (or Display == 0) is committed
    if ( !$Param{Display} ) {

        # Check if a DefaultValue is given
        if ( $Param{DefaultValue} ) {

            # check if the given field param is valid
            $Value = $Self->_LookupValue(
                Field => $FieldWithoutID,
                Value => $Param{DefaultValue},
            );
        }

        # if we got a required ticket field, check if we got a valid DefaultValue in the SysConfig
        if ( !$Value && $TicketRequiredField ) {
            $Value = $Kernel::OM->Get('Kernel::Config')->Get("Process::Default$FieldWithoutID");

            if ( !$Value ) {
                $LayoutObject->FatalError(
                    Message => $LayoutObject->{LanguageObject}->Translate(
                        'Default Config for Process::Default%s missing!',
                        $FieldWithoutID,
                    ),
                );
            }
            else {

                # check if the given field param is valid
                $Value = $Self->_LookupValue(
                    Field => $FieldWithoutID,
                    Value => $Value,
                );
                if ( !$Value ) {
                    $LayoutObject->FatalError(
                        Message => $LayoutObject->{LanguageObject}->Translate(
                            'Default Config for Process::Default%s invalid!',
                            $FieldWithoutID,
                        ),
                    );
                }
            }
        }
    }
    elsif ( $Param{Display} == 1 ) {

        # Display == 1 is logicality not possible for a ticket required field
        if ($TicketRequiredField) {
            $LayoutObject->FatalError(
                Message => $LayoutObject->{LanguageObject}->Translate(
                    'Wrong ActivityDialog Field config: %s can\'t be Display => 1 / Show field (Please change its configuration to be Display => 0 / Do not show field or Display => 2 / Show field as mandatory)!',
                    $Param{Field},
                ),
            );
        }

        # check if the given field param is valid
        if ( $Param{Field} eq 'Article' ) {

            # in case of article fields we need to fake a value
            $Value = 1;

            my ( $Body, $Subject, $AttachmentDelete1, $TimeUnits ) = (
                $ParamObject->GetParam( Param => 'Body' ),
                $ParamObject->GetParam( Param => 'Subject' ),
                $ParamObject->GetParam( Param => 'AttachmentDelete1' ),
                $ParamObject->GetParam( Param => 'TimeUnits' )
            );

            # If attachment exists and body and subject not, it is error (see bug#13081).
            if ( defined $AttachmentDelete1 && ( !$Body && !$Subject ) ) {
                $Value = 0;
            }

            # If time units exists and body and subject not, it is error (see bug#13266).
            if ( $TimeUnits && ( !$Body && !$Subject ) ) {
                $Value = 0;
            }

        }
        else {

            $Value = $Self->_LookupValue(
                Field => $Param{Field},
                Value => $ParamObject->GetParam( Param => $Param{Field} ) || '',
            );
        }
    }
    elsif ( $Param{Display} == 2 ) {

        # check if the given field param is valid
        if ( $Param{Field} eq 'Article' ) {

            my ( $Body, $Subject ) = (
                $ParamObject->GetParam( Param => 'Body' ),
                $ParamObject->GetParam( Param => 'Subject' )
            );

            $Value = 0;
            if ( $Body && $Subject ) {
                $Value = 1;
            }
        }
        else {
            $Value = $Self->_LookupValue(
                Field => $Param{Field},
                Value => $ParamObject->GetParam( Param => $Param{Field} ) || '',
            );
        }
    }

    return $Value;
}

# =item _LookupValue()
#
# returns the ID (if possible) of nearly all ticket fields and/or checks if its valid.
# Can handle IDs or Strings.
# Currently working with: State, Queue, Lock, Priority (possible more).
#
#     my $PriorityID = $AgentTicketProcessObject->_LookupValue(
#         PriorityID => 1,
#     );
#     $PriorityID = 1;
#
#     my $StateID = $AgentTicketProcessObject->_LookupValue(
#         State => 'open',
#     );
#     $StateID = 3;
#
#     my $PriorityID = $AgentTicketProcessObject->_LookupValue(
#         Priority => 'unknownpriority1234',
#     );
#     $PriorityID = undef;
#
# =cut

sub _LookupValue {
    my ( $Self, %Param ) = @_;

    # get log object
    my $LogObject = $Kernel::OM->Get('Kernel::System::Log');

    # check needed stuff
    for my $Needed (qw(Field Value)) {
        if ( !defined $Param{$Needed} ) {
            $LogObject->Log(
                Priority => 'error',
                Message  => "Need $Needed!"
            );
            return;
        }
    }

    if ( !$Param{Field} ) {
        $LogObject->Log(
            Priority => 'error',
            Message  => "Field should not be empty!"
        );
        return;
    }

    # if there is no value, there is nothing to do
    return if !$Param{Value};

    # remove the ID for function name purpose
    my $FieldWithoutID = $Param{Field};
    $FieldWithoutID =~ s{ID$}{}xms;

    my $LookupFieldName;
    my $ObjectName;
    my $FunctionName;

    # owner(ID) and responsible(ID) lookup needs UserID as parameter
    if ( scalar grep { $Param{Field} eq $_ } qw( OwnerID ResponsibleID ) ) {
        $LookupFieldName = 'UserID';
        $ObjectName      = 'User';
        $FunctionName    = 'UserLookup';
    }

    # owner and responsible lookup needs UserLogin as parameter
    elsif ( scalar grep { $Param{Field} eq $_ } qw( Owner Responsible ) ) {
        $LookupFieldName = 'UserLogin';
        $ObjectName      = 'User';
        $FunctionName    = 'UserLookup';
    }

    # service and SLA lookup needs Name as parameter (While ServiceID an SLAID uses standard)
    elsif ( scalar grep { $Param{Field} eq $_ } qw( Service SLA ) ) {
        $LookupFieldName = 'Name';
        $ObjectName      = $FieldWithoutID;
        $FunctionName    = $FieldWithoutID . 'Lookup';
    }

    # other fields can use standard parameter names as Priority or PriorityID
    else {
        $LookupFieldName = $Param{Field};
        $ObjectName      = $FieldWithoutID;
        $FunctionName    = $FieldWithoutID . 'Lookup';
    }

    # get appropriate object of field
    my $FieldObject;
    if ( $Kernel::OM->Get('Kernel::System::Main')->Require( 'Kernel::System::' . $ObjectName, Silent => 1 ) ) {
        $FieldObject = $Kernel::OM->Get( 'Kernel::System::' . $ObjectName );
    }

    my $Value;

    # check if the backend module has the needed *Lookup sub
    if ( $FieldObject && $FieldObject->can($FunctionName) ) {

        # call the *Lookup sub and get the value
        $Value = $FieldObject->$FunctionName(
            $LookupFieldName => $Param{Value},
        );
    }

    # if we didn't have an object and the value has no ref a string e.g. Title and so on
    # return true
    elsif ( $Param{Field} eq $FieldWithoutID && !ref $Param{Value} ) {
        return $Param{Value};
    }
    else {
        $LogObject->Log(
            Priority => 'error',
            Message  => "Error while checking with " . $FieldWithoutID . "Object!"
        );
        return;
    }

    return if ( !$Value );

    # return the given ID value if the *Lookup result was a string
    if ( $Param{Field} ne $FieldWithoutID ) {
        return $Param{Value};
    }

    # return the *Lookup string return value
    return $Value;
}

sub _GetResponsibles {
    my ( $Self, %Param ) = @_;

    # get needed objects
    my $ConfigObject = $Kernel::OM->Get('Kernel::Config');
    my $GroupObject  = $Kernel::OM->Get('Kernel::System::Group');
    my $QueueObject  = $Kernel::OM->Get('Kernel::System::Queue');
    my $TicketObject = $Kernel::OM->Get('Kernel::System::Ticket');
    my $UserObject   = $Kernel::OM->Get('Kernel::System::User');

    # get available permissions and set permission group type accordingly.
    my $ConfigPermissions   = $ConfigObject->Get('System::Permission');
    my $PermissionGroupType = ( grep { $_ eq 'responsible' } @{$ConfigPermissions} ) ? 'responsible' : 'rw';

    # get login list of users
    my %UserLoginList = $UserObject->UserList(
        Type  => 'Short',
        Valid => 1,
    );

    # prepare acl data
    my %ACLUsers;

    # if we are updating a ticket show the full list of possible owners
    if ( $Param{TicketID} ) {
        if (
            $Param{QueueID}
            && !$Param{AllUsers}
        ) {
            my $GID = $QueueObject->GetQueueGroupID(
                QueueID => $Param{QueueID}
            );

            my %MemberList = $GroupObject->PermissionGroupGet(
                GroupID => $GID,
                Type    => $PermissionGroupType,
            );

            for my $MemberKey ( keys( %MemberList ) ) {
                if ( $UserLoginList{ $MemberKey } ) {
                    $ACLUsers{ $MemberKey } = $UserLoginList{ $MemberKey };
                }
            }
        }
    }
    else {

        # the StartActivityDialog does not provide a TicketID and it could be that also there
        # is no QueueID information. Get the default QueueID for this matters.
        if ( !$Param{QueueID} ) {
            my $Queue   = $ConfigObject->Get("Process::DefaultQueue");
            my $QueueID = $QueueObject->QueueLookup( Queue => $Queue );
            if ( $QueueID ) {
                $Param{QueueID} = $QueueID;
            }
        }

        # just show only users with selected custom queue
        if (
            $Param{QueueID}
            && !$Param{OwnerAll}
        ) {
            my @UserIDs = $TicketObject->GetSubscribedUserIDsByQueueID( %Param );
            for my $GroupMemberKey ( keys( %UserLoginList ) ) {
                my $Hit = 0;
                USERID:
                for my $UID (@UserIDs) {
                    if ( $UID eq $GroupMemberKey ) {
                        $Hit = 1;

                        last USERID;
                    }
                }
                if ( !$Hit ) {
                    delete( $UserLoginList{ $GroupMemberKey } );
                }
            }
        }

        # show all system users
        if ( $ConfigObject->Get('Ticket::ChangeOwnerToEveryone') ) {
            %ACLUsers = %UserLoginList;
        }

        # show all subscribed users who have the appropriate permission in the queue group
        elsif ( $Param{QueueID} ) {
            my $GID = $QueueObject->GetQueueGroupID(
                QueueID => $Param{QueueID}
            );

            my %MemberList = $GroupObject->PermissionGroupGet(
                GroupID => $GID,
                Type    => $PermissionGroupType,
            );

            for my $MemberKey ( keys( %MemberList ) ) {
                if ( $UserLoginList{ $MemberKey } ) {
                    $ACLUsers{ $MemberKey } = $UserLoginList{ $MemberKey };
                }
            }
        }
    }

    # apply acl
    my $ACL = $TicketObject->TicketAcl(
        %Param,
        Action        => $Self->{Action},
        ReturnType    => 'Ticket',
        ReturnSubType => 'Responsible',
        Data          => \%ACLUsers,
        UserID        => $Self->{UserID},
    );
    if ( $ACL ) {
        %ACLUsers = $TicketObject->TicketAclData();
    }

    # prepare display data
    my %UserNameList = $UserObject->UserList(
        Type  => 'Long',
        Valid => 1,
    );
    my %ShownUsers = map( { $_ => $UserNameList{$_} } keys( %ACLUsers ) );

    return \%ShownUsers;
}

sub _GetOwners {
    my ( $Self, %Param ) = @_;

    # get needed objects
    my $ConfigObject = $Kernel::OM->Get('Kernel::Config');
    my $GroupObject  = $Kernel::OM->Get('Kernel::System::Group');
    my $QueueObject  = $Kernel::OM->Get('Kernel::System::Queue');
    my $TicketObject = $Kernel::OM->Get('Kernel::System::Ticket');
    my $UserObject   = $Kernel::OM->Get('Kernel::System::User');

    # get available permissions and set permission group type accordingly.
    my $ConfigPermissions   = $ConfigObject->Get('System::Permission');
    my $PermissionGroupType = ( grep { $_ eq 'owner' } @{$ConfigPermissions} ) ? 'owner' : 'rw';

    # get login list of users
    my %UserLoginList = $UserObject->UserList(
        Type  => 'Short',
        Valid => 1,
    );

    # prepare acl data
    my %ACLUsers;

    # if we are updating a ticket show the full list of possible owners
    if ( $Param{TicketID} ) {
        if (
            $Param{QueueID}
            && !$Param{AllUsers}
        ) {
            my $GID = $QueueObject->GetQueueGroupID(
                QueueID => $Param{QueueID}
            );

            my %MemberList = $GroupObject->PermissionGroupGet(
                GroupID => $GID,
                Type    => $PermissionGroupType,
            );

            for my $MemberKey ( keys( %MemberList ) ) {
                if ( $UserLoginList{ $MemberKey } ) {
                    $ACLUsers{ $MemberKey } = $UserLoginList{ $MemberKey };
                }
            }
        }
    }
    else {

        # the StartActivityDialog does not provide a TicketID and it could be that also there
        # is no QueueID information. Get the default QueueID for this matters.
        if ( !$Param{QueueID} ) {
            my $Queue   = $ConfigObject->Get("Process::DefaultQueue");
            my $QueueID = $QueueObject->QueueLookup( Queue => $Queue );
            if ( $QueueID ) {
                $Param{QueueID} = $QueueID;
            }
        }

        # just show only users with selected custom queue
        if (
            $Param{QueueID}
            && !$Param{OwnerAll}
        ) {
            my @UserIDs = $TicketObject->GetSubscribedUserIDsByQueueID( %Param );
            for my $GroupMemberKey ( keys( %UserLoginList ) ) {
                my $Hit = 0;
                USERID:
                for my $UID (@UserIDs) {
                    if ( $UID eq $GroupMemberKey ) {
                        $Hit = 1;

                        last USERID;
                    }
                }
                if ( !$Hit ) {
                    delete( $UserLoginList{ $GroupMemberKey } );
                }
            }
        }

        # show all system users
        if ( $ConfigObject->Get('Ticket::ChangeOwnerToEveryone') ) {
            %ACLUsers = %UserLoginList;
        }

        # show all subscribed users who have the appropriate permission in the queue group
        elsif ( $Param{QueueID} ) {
            my $GID = $QueueObject->GetQueueGroupID(
                QueueID => $Param{QueueID}
            );

            my %MemberList = $GroupObject->PermissionGroupGet(
                GroupID => $GID,
                Type    => $PermissionGroupType,
            );

            for my $MemberKey ( keys( %MemberList ) ) {
                if ( $UserLoginList{ $MemberKey } ) {
                    $ACLUsers{ $MemberKey } = $UserLoginList{ $MemberKey };
                }
            }
        }
    }

    # apply acl
    my $ACL = $TicketObject->TicketAcl(
        %Param,
        Action        => $Self->{Action},
        ReturnType    => 'Ticket',
        ReturnSubType => 'Owner',
        Data          => \%ACLUsers,
        UserID        => $Self->{UserID},
    );
    if ( $ACL ) {
        %ACLUsers = $TicketObject->TicketAclData();
    }

    # prepare display data
    my %UserNameList = $UserObject->UserList(
        Type  => 'Long',
        Valid => 1,
    );
    my %ShownUsers = map( { $_ => $UserNameList{$_} } keys( %ACLUsers ) );

    return \%ShownUsers;
}

sub _GetSLAs {
    my ( $Self, %Param ) = @_;

    # get sla
    my %SLA;
    if ( $Param{ServiceID} && $Param{Services} && %{ $Param{Services} } ) {
        if ( $Param{Services}->{ $Param{ServiceID} } ) {
            %SLA = $Kernel::OM->Get('Kernel::System::Ticket')->TicketSLAList(
                %Param,
                Action => $Self->{Action},
                UserID => $Self->{UserID},
            );
        }
    }
    return \%SLA;
}

sub _GetServices {
    my ( $Self, %Param ) = @_;

    # get service
    my %Service;

    # get options for default services for unknown customers
    my $DefaultServiceUnknownCustomer = $Kernel::OM->Get('Kernel::Config')->Get('Ticket::Service::Default::UnknownCustomer');

    # check if no CustomerUserID is selected
    # if $DefaultServiceUnknownCustomer = 0 leave CustomerUserID empty, it will not get any services
    # if $DefaultServiceUnknownCustomer = 1 set CustomerUserID to get default services
    if (
        !$Param{CustomerUserID}
        && $DefaultServiceUnknownCustomer
    ) {
        $Param{CustomerUserID} = '<DEFAULT>';
    }

    # get service list
    if ( $Param{CustomerUserID} ) {
        %Service = $Kernel::OM->Get('Kernel::System::Ticket')->TicketServiceList(
            %Param,
            Action => $Self->{Action},
            UserID => $Self->{UserID},
        );
    }
    return \%Service;
}

sub _GetLocks {
    my ( $Self, %Param ) = @_;

    my %Locks = $Kernel::OM->Get('Kernel::System::Lock')->LockList(
        UserID => $Self->{UserID},
    );

    return \%Locks;
}

sub _GetPriorities {
    my ( $Self, %Param ) = @_;

    my %Priorities;

    # Initially we have just the default Queue Parameter
    # so make sure to get the ID in that case
    my $QueueID;
    if ( !$Param{QueueID} && $Param{Queue} ) {
        $QueueID = $Kernel::OM->Get('Kernel::System::Queue')->QueueLookup( Queue => $Param{Queue} );
    }
    if ( $Param{QueueID} || $QueueID || $Param{TicketID} ) {
        %Priorities = $Kernel::OM->Get('Kernel::System::Ticket')->TicketPriorityList(
            %Param,
            Action => $Self->{Action},
            UserID => $Self->{UserID},
        );

    }
    return \%Priorities;
}

sub _GetQueues {
    my ( $Self, %Param ) = @_;

    # check which type of permission is needed: if the process ticket
    # already exists (= TicketID is present), we need the 'move_into'
    # permission otherwise the 'create' permission
    my $PermissionType = 'create';
    if ( $Param{TicketID} ) {
        $PermissionType = 'move_into';
    }

    # get config object
    my $ConfigObject = $Kernel::OM->Get('Kernel::Config');

    # check own selection
    my %NewQueues;
    if ( $ConfigObject->Get('Ticket::Frontend::NewQueueOwnSelection') ) {
        %NewQueues = %{ $ConfigObject->Get('Ticket::Frontend::NewQueueOwnSelection') };
    }
    else {

        # SelectionType Queue or SystemAddress?
        my %Queues;
        if ( $ConfigObject->Get('Ticket::Frontend::NewQueueSelectionType') eq 'Queue' ) {
            %Queues = $Kernel::OM->Get('Kernel::System::Ticket')->TicketMoveList(
                %Param,
                Type    => $PermissionType,
                Action  => $Self->{Action},
                QueueID => $Self->{QueueID},
                UserID  => $Self->{UserID},
            );
        }
        else {
            %Queues = $Kernel::OM->Get('Kernel::System::DB')->GetTableData(
                Table => 'system_address',
                What  => 'queue_id, id',
                Valid => 1,
                Clamp => 1,
            );
        }

        # get permission queues
        my %UserGroups = $Kernel::OM->Get('Kernel::System::Group')->PermissionUserGet(
            UserID => $Self->{UserID},
            Type   => $PermissionType,
        );

        # build selection string
        QUEUEID:
        for my $QueueID ( sort keys %Queues ) {
            my %QueueData = $Kernel::OM->Get('Kernel::System::Queue')->QueueGet( ID => $QueueID );

            # permission check, can we create new tickets in queue
            next QUEUEID if !$UserGroups{ $QueueData{GroupID} };

            my $String = $ConfigObject->Get('Ticket::Frontend::NewQueueSelectionString')
                || '<Realname> <<Email>> - Queue: <Queue>';
            $String =~ s/<Queue>/$QueueData{Name}/g;
            $String =~ s/<QueueComment>/$QueueData{Comment}/g;

            # remove trailing spaces
            $String =~ s{\s+\z}{} if !$QueueData{Comment};

            if ( $ConfigObject->Get('Ticket::Frontend::NewQueueSelectionType') ne 'Queue' ) {
                my %SystemAddressData = $Self->{SystemAddress}->SystemAddressGet(
                    ID => $Queues{$QueueID},
                );
                $String =~ s/<Realname>/$SystemAddressData{Realname}/g;
                $String =~ s/<Email>/$SystemAddressData{Name}/g;
            }
            $NewQueues{$QueueID} = $String;
        }
    }

    return \%NewQueues;
}

sub _GetStates {
    my ( $Self, %Param ) = @_;

    my %States = $Kernel::OM->Get('Kernel::System::Ticket')->TicketStateList(
        %Param,

        # Set default values for new process ticket
        QueueID  => $Param{QueueID}  || 1,
        TicketID => $Param{TicketID} || '',

        # remove type, since if Ticket::Type is active in sysconfig, the Type parameter will
        # be sent and the TicketStateList will send the parameter as State Type
        Type => undef,

        Action => $Self->{Action},
        UserID => $Self->{UserID},
    );

    return \%States;
}

sub _GetTypes {
    my ( $Self, %Param ) = @_;

    # get type
    my %Type;
    if ( $Param{QueueID} || $Param{TicketID} ) {
        %Type = $Kernel::OM->Get('Kernel::System::Ticket')->TicketTypeList(
            %Param,
            Action => $Self->{Action},
            UserID => $Self->{UserID},
        );
    }
    return \%Type;
}

sub _GetAJAXUpdatableFields {
    my ( $Self, %Param ) = @_;

    my %DefaultUpdatableFields = (
        PriorityID    => 1,
        QueueID       => 1,
        ResponsibleID => 1,
        ServiceID     => 1,
        SLAID         => 1,
        StateID       => 1,
        OwnerID       => 1,
        LockID        => 1,
        TypeID        => 1,
    );

    # create a DynamicFieldLookupTable
    my %DynamicFieldLookup = map { 'DynamicField_' . $_->{Name} => $_ } @{ $Self->{DynamicField} };

    my @UpdatableFields;
    FIELD:
    for my $Field ( sort keys %{ $Param{ActivityDialogFields} } ) {

        my $FieldData = $Param{ActivityDialogFields}->{$Field};

        # skip hidden fields
        next FIELD if !$FieldData->{Display};

        # for Dynamic Fields check if is AJAXUpdatable
        if ( $Field =~ m{^DynamicField_(.*)}xms ) {
            my $DynamicFieldConfig = $DynamicFieldLookup{$Field};

            # skip any field with wrong config
            next FIELD if !IsHashRefWithData($DynamicFieldConfig);

            # skip field if is not IsACLReducible (updatable)
            my $IsACLReducible = $Kernel::OM->Get('Kernel::System::DynamicField::Backend')->HasBehavior(
                DynamicFieldConfig => $DynamicFieldConfig,
                Behavior           => 'IsACLReducible',
            );
            next FIELD if !$IsACLReducible;

            push @UpdatableFields, $Field;
        }

        # for all others use %DefaultUpdatableFields table
        else {

            # standarize the field name (e.g. use StateID for State field)
            my $FieldName = $Self->{NameToID}->{$Field};

            # skip if field name could not be converted (this means that field is unknown)
            next FIELD if !$FieldName;

            # skip if the field is not updatable via ajax
            next FIELD if !$DefaultUpdatableFields{$FieldName};

            push @UpdatableFields, $FieldName;
        }
    }

    return \@UpdatableFields;
}

sub _GetFieldsToUpdateStrg {
    my ( $Self, %Param ) = @_;

    my $FieldsToUpdate = '';
    if ( IsArrayRefWithData( $Param{AJAXUpdatableFields} ) ) {
        my $FirstItem = 1;
        FIELD:
        for my $Field ( @{ $Param{AJAXUpdatableFields} } ) {
            next FIELD if $Field eq $Param{TriggerField};
            if ($FirstItem) {
                $FirstItem = 0;
            }
            else {
                $FieldsToUpdate .= ', ';
            }
            $FieldsToUpdate .= "'" . $Field . "'";
        }
    }
    return $FieldsToUpdate;
}

sub _ShowDialogError {
    my ( $Self, %Param ) = @_;

    my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout');

    my $Output = $LayoutObject->Header( Type => 'Small' );
    $Output .= $LayoutObject->Error(%Param);
    $Output .= $LayoutObject->Footer( Type => 'Small' );
    return $Output;
}

sub _GetShownDynamicFields {
    my ( $Self, %Param ) = @_;

    # get ticket object
    my $TicketObject = $Kernel::OM->Get('Kernel::System::Ticket');

    # use only dynamic fields which passed the acl
    my %TicketAclFormData = $TicketObject->TicketAclFormData();

    # cycle through dynamic fields to get shown or hidden fields
    for my $DynamicField ( @{ $Self->{DynamicField} } ) {

        # if field was not configured initially set it as not visible
        if ( $Self->{NotShownDynamicFields}->{ $DynamicField->{Name} } ) {
            $DynamicField->{Shown} = 0;
        }
        else {

            # hide DynamicFields only if we have ACL's
            if (
                IsHashRefWithData( \%TicketAclFormData )
                && defined $TicketAclFormData{ $DynamicField->{Name} }
            ) {
                if ( $TicketAclFormData{ $DynamicField->{Name} } >= 1 ) {
                    $DynamicField->{Shown} = 1;
                }
                else {
                    $DynamicField->{Shown} = 0;
                }
            }

            # else show them by default
            else {
                $DynamicField->{Shown} = 1;
            }
        }
    }

    return 1;
}

1;

=back

=head1 TERMS AND CONDITIONS

This software is part of the KIX project
(L<https://www.kixdesk.com/>).

This software comes with ABSOLUTELY NO WARRANTY. For details, see the enclosed file
LICENSE for license information (AGPL). If you did not receive this file, see

<https://www.gnu.org/licenses/agpl.txt>.

=cut
