use strict;
no warnings 'redefine';

sub DelegateToGroups {
    my ($self, %args) = @_;

    my $Groups = RT::Groups->new($RT::SystemUser);
    $Groups->LimitToPersonalGroupsFor($self->PrincipalId);
    $Groups->LimitToActive unless $args{INACTIVE};
    $Groups->LimitToEnabled unless $args{DISABLED};

    if (my $Queue = $args{Queue}) {
	$Groups->LimitToDelegateOnQueue($Queue);
	return $Groups if $Groups->Count;

	# Okay, we start again...
	$Groups = RT::Groups->new($RT::SystemUser);
	$Groups->LimitToPersonalGroupsFor($self->PrincipalId);
	$Groups->LimitToActive unless $args{INACTIVE};
	$Groups->LimitToEnabled unless $args{DISABLED};
    }

    # Find out global delegates
    $Groups->LimitToDelegateOnGlobal;

    return $Groups;
}

sub DelegateFromGroups {
    my ($self, %args) = @_;

    my $Groups = RT::Groups->new($RT::SystemUser);
    $Groups->LimitToActive unless $args{INACTIVE};
    $Groups->LimitToEnabled unless $args{DISABLED};
    $Groups->LimitToPersonalGroups;
    $Groups->LimitToDelegateTo($self->Id);
    $Groups->LimitToDelegateOnGlobal;

    my $Queue = $args{Queue} or return $Groups;

    my $alias = $Groups->Join(
	TYPE	=> 'left',
	ALIAS1	=> 'main',
	FIELD1	=> 'Instance',
	TABLE2	=> 'Groups',
	FIELD2	=> 'Instance',
    );
    $Groups->LimitToPersonalGroups( LEFTJOIN => $alias );
    $Groups->LimitToDelegateOnQueue( $Queue, LEFTJOIN => $alias );

    my $clause = 'main.Name';
    $Groups->_OpenParen($clause);
    $Groups->Limit(
	SUBCLAUSE	=> $clause,
	ALIAS		=> $alias,
	FIELD		=> 'id',
	OPERATOR	=> 'IS',
	VALUE		=> 'NULL',
	ENTRYAGGREGATOR => 'AND',
    );
    $Groups->LimitToInactive(
	SUBCLAUSE	=> $clause,
	ALIAS		=> $alias,
    );
    $Groups->LimitToDisabled(
	SUBCLAUSE	=> $clause,
	ALIAS		=> $alias,
    );
    $Groups->_CloseParen($clause);

    $Groups->LimitToDelegateOnQueue(
	$Queue,
	ENTRYAGGREGATOR => 'OR',
    );

    return $Groups;
}

sub DelegateAddresses {
    my ($self, %args) = @_;

    my $Queue = $args{Queue} or return;
    my $Group = $self->DelegateToGroups( Queue => $Queue )->First or return;

    return $Group->MemberEmailAddresses;
}

# Queue, Delegate, Starts, Due, Disabled
sub SetDelegate {
    my ($self, %args) = @_;

    my $Queue = $args{Queue} or return;
    my $QueueId = -1;

    if ($Queue and $Queue ne '-1') {
        my $QueueObj = RT::Queue->new($self->CurrentUser);
        $QueueObj->Load($Queue);
        $QueueId = $Queue->Id or return;
    }

    my $Groups = RT::Groups->new($self->CurrentUser);
    $Groups->LimitToPersonalGroupsFor($self->PrincipalId);
    $Groups->{find_disabled_rows}++;

    my $Delegates = {};
    while ( my $Group = $Groups->Next) {
        $Group->UpdateCompany($self->Attribute('Company'))
            if $Group->can('UpdateCompany');
        $Delegates->{$Group->Name} = $Group;
    }

    my $Group = $Delegates->{$QueueId};

    if (my $Delegate = $args{Delegate}) {
        if (!$Group) {
            $Group = RT::Group->new($self->CurrentUser);
            $Group->UpdateCompany if $Group->can('UpdateCompany');
            $Group->CreatePersonalGroup(
                Name        => $QueueId,
                PrincipalId => $self->PrincipalId,
            );
            $Delegates->{$QueueId} = $Group;
        }

        my $DelegateObj = RT::User->new($self->CurrentUser);
        $DelegateObj->Load($Delegate);

        my $DelegateId = $DelegateObj->Id or return;
	$Group->SetDescription($DelegateId);
	foreach my $User (@{$Group->UserMembersObj->ItemsArrayRef}) {
	    $Group->DeleteMember($User->PrincipalId);
	}
	$Group->AddMember($DelegateId);
	$Group->SetDisabled($args{Disabled}) if exists $args{Disabled};
        $Group->SetStarts($args{Starts}) if exists $args{Starts};
        $Group->SetDue($args{Due}) if exists $args{Due};
    }
    else {
        $Group->Delete if $Group;
    }
}

# Compatibility measure till 104UI was cleaned-up to not using these API.

sub dbh { $RT::Nothing }
sub get_hash { {} }
sub call_sp { '' }
sub val { '' }
sub vals { () }
sub get { '' }
sub describe { '' }
sub meta { {} }
sub normalize { '' }
sub table { {} }
sub ext_table { {} }
sub tables { {} }
sub src { [] }
sub load_meta { {} }
sub fields { {} }
sub procedures_cname { {} }
sub fields_cname { {} }
sub fields_values { {} }
sub field_cname { '' }
sub no_to_id { 0 }
sub column_hash { {} }
sub field_values { () }
sub code { '' }

1;
