# --
# Copyright (C) 2001-2021 OTRS AG, https://otrs.com/
# Copyright (C) 2021 Znuny GmbH, https://znuny.org/
# --
# This software comes with ABSOLUTELY NO WARRANTY. For details, see
# the enclosed file COPYING for license information (GPL). If you
# did not receive this file, see https://www.gnu.org/licenses/gpl-3.0.txt.
# --

package Kernel::Output::HTML::Dashboard::TicketQueueOverview;

use strict;
use warnings;

our $ObjectManagerDisabled = 1;

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

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

    # get needed parameters
    for my $Needed (qw( Config Name UserID )) {
        die "Got no $Needed!" if ( !$Self->{$Needed} );
    }

    $Self->{PrefKey}  = 'UserDashboardPref' . $Self->{Name} . '-Shown';
    $Self->{CacheKey} = $Self->{Name} . '-' . $Self->{UserID};

    return $Self;
}

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

    return;
}

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

    return (
        %{ $Self->{Config} },

        # remember, do not allow to use page cache
        # (it's not working because of internal filter)
        CacheKey => undef,
        CacheTTL => undef,
    );
}

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

    my $LimitGroup = $Self->{Config}->{QueuePermissionGroup} || 0;
    my $CacheKey   = 'User' . '-' . $Self->{UserID} . '-' . $LimitGroup;

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

    # check for refresh time
    my $Refresh = '';
    if ( $Self->{UserRefreshTime} ) {
        $Refresh = 60 * $Self->{UserRefreshTime};
        my $NameHTML = $Self->{Name};
        $NameHTML =~ s{-}{_}xmsg;

        # send data to JS
        $LayoutObject->AddJSData(
            Key   => 'QueueOverview',
            Value => {
                Name        => $Self->{Name},
                NameHTML    => $NameHTML,
                RefreshTime => $Refresh,
            },
        );
    }

    # get cache object
    my $CacheObject = $Kernel::OM->Get('Kernel::System::Cache');

    my $Content = $CacheObject->Get(
        Type => 'DashboardQueueOverview',
        Key  => $CacheKey,
    );
    return $Content if defined $Content;

    # get configured states, get their state ID and test if they exist while we do it
    my %States;
    my $StateIDURL;
    my %ConfiguredStates = %{ $Self->{Config}->{States} };
    for my $StateOrder ( sort { $a <=> $b } keys %ConfiguredStates ) {
        my $State = $ConfiguredStates{$StateOrder};

        # check if state is found, to record StateID
        my $StateID = $Kernel::OM->Get('Kernel::System::State')->StateLookup(
            State => $State,
        ) || '';
        if ($StateID) {
            $States{$State} = $StateID;

            # append StateID to URL for search string
            $StateIDURL .= "StateIDs=$StateID;";
        }
        else {

            # state does not exist, skipping
            delete $ConfiguredStates{$StateOrder};
        }
    }

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

    # get all queues
    my %Queues = $QueueObject->GetAllQueues(
        UserID => $Self->{UserID},
        Type   => 'ro',
    );

    # limit them by QueuePermissionGroup if needed
    my $LimitGroupID;
    if ($LimitGroup) {
        $LimitGroupID = $Kernel::OM->Get('Kernel::System::Group')->GroupLookup(
            Group => $LimitGroup,
        );
    }

    my $Sort = $Self->{Config}->{Sort} || '';

    my %QueueToID;
    my $QueueIDURL;

    # lookup queues, add their QueueID to new hash (needed for Search)
    QUEUES:
    for my $QueueID ( sort keys %Queues ) {

        # see if we have to remove the queue based on LimitGroup
        if ($LimitGroup) {
            my $GroupID = $QueueObject->GetQueueGroupID(
                QueueID => $QueueID,
            );
            if ( $GroupID != $LimitGroupID ) {
                delete $Queues{$QueueID};
                next QUEUES;
            }
        }

        # add queue to reverse hash
        $QueueToID{ $Queues{$QueueID} } = $QueueID;

        # add queue to SearchURL
        $QueueIDURL .= "QueueIDs=$QueueID;";
    }

    # Prepare ticket count.
    my $TicketObject = $Kernel::OM->Get('Kernel::System::Ticket');
    my @QueueIDs     = sort keys %Queues;
    if ( !@QueueIDs ) {
        @QueueIDs = (999_999);
    }

    my %Results;
    for my $StateOrderID ( sort { $a <=> $b } keys %ConfiguredStates ) {

        # Run ticket search for all Queues and appropriate available State.
        my @StateOrderTicketIDs = $TicketObject->TicketSearch(
            UserID   => $Self->{UserID},
            Result   => 'ARRAY',
            QueueIDs => \@QueueIDs,
            States   => [ $ConfiguredStates{$StateOrderID} ],
            Limit    => 100_000,
        );

        # Count of tickets per QueueID.
        my $TicketCountByQueueID = $TicketObject->TicketCountByAttribute(
            Attribute => 'QueueID',
            TicketIDs => \@StateOrderTicketIDs,
        );

        # Gather ticket count for corresponding Queue <-> State.
        QUEUEID:
        for my $QueueID (@QueueIDs) {
            next QUEUEID if !%Queues || !$Queues{$QueueID};
            push @{ $Results{ $Queues{$QueueID} } },
                $TicketCountByQueueID->{$QueueID} ? $TicketCountByQueueID->{$QueueID} : 0;
        }
    }

    # build header
    my @Headers = ( 'Queue', );
    for my $StateOrder ( sort { $a <=> $b } keys %ConfiguredStates ) {
        push @Headers, $ConfiguredStates{$StateOrder};
    }

    for my $HeaderItem (@Headers) {
        $LayoutObject->Block(
            Name => 'ContentLargeTicketQueueOverviewHeaderStatus',
            Data => {
                Text => $HeaderItem,
            },
        );
    }

    my $HasContent;

    # iterate over all queues, print results;
    my @StatusTotal;
    QUEUE:
    for my $Queue ( sort values %Queues ) {

        # Hide empty queues
        if ( !grep { defined $_ && $_ > 0 } @{ $Results{$Queue} } ) {
            next QUEUE;
        }

        $HasContent++;

        $LayoutObject->Block(
            Name => 'ContentLargeTicketQueueOverviewQueueName',
            Data => {
                QueueID   => $QueueToID{$Queue},
                QueueName => $Queue,
            }
        );

        # iterate over states
        my $Counter = 0;
        my $RowTotal;
        for my $StateOrderID ( sort { $a <=> $b } keys %ConfiguredStates ) {
            $LayoutObject->Block(
                Name => 'ContentLargeTicketQueueOverviewQueueResults',
                Data => {
                    Number  => $Results{$Queue}->[$Counter],
                    QueueID => $QueueToID{$Queue},
                    StateID => $States{ $ConfiguredStates{$StateOrderID} },
                    State   => $ConfiguredStates{$StateOrderID},
                    Sort    => $Sort,
                },
            );
            $RowTotal                   += $Results{$Queue}->[$Counter] || 0;
            $StatusTotal[$StateOrderID] += $Results{$Queue}->[$Counter] || 0;
            $Counter++;
        }

        # print row (queue) total
        $LayoutObject->Block(
            Name => 'ContentLargeTicketQueueOverviewQueueTotal',
            Data => {
                Number   => $RowTotal,
                QueueID  => $QueueToID{$Queue},
                StateIDs => $StateIDURL,
                Sort     => $Sort,
            },
        );

    }

    if ($HasContent) {
        $LayoutObject->Block(
            Name => 'ContentLargeTicketQueueOverviewStatusTotalRow',
        );

        for my $StateOrderID ( sort { $a <=> $b } keys %ConfiguredStates ) {
            $LayoutObject->Block(
                Name => 'ContentLargeTicketQueueOverviewStatusTotal',
                Data => {
                    Number   => $StatusTotal[$StateOrderID],
                    QueueIDs => $QueueIDURL,
                    StateID  => $States{ $ConfiguredStates{$StateOrderID} },
                    Sort     => $Sort,
                },
            );
        }
    }
    else {
        $LayoutObject->Block(
            Name => 'ContentLargeTicketQueueOverviewNone',
            Data => {
                ColumnCount => ( scalar keys %ConfiguredStates ) + 2,
            }
        );
    }

    $Content = $LayoutObject->Output(
        TemplateFile => 'AgentDashboardTicketQueueOverview',
        Data         => {
            %{ $Self->{Config} },
            Name => $Self->{Name},
        },
        AJAX => $Param{AJAX},
    );

    # cache result
    if ( $Self->{Config}->{CacheTTLLocal} ) {
        $CacheObject->Set(
            Type  => 'DashboardQueueOverview',
            Key   => $CacheKey,
            Value => $Content || '',
            TTL   => $Self->{Config}->{CacheTTLLocal} * 60,
        );
    }

    return $Content;
}

1;
