package PMG::ModGroup;

use strict;
use warnings;

sub new {
    my ($type, $entity, $targets) = @_;

    my $self = {
	targets => $targets,
	ea => [$entity],
	groups => [$targets],
	entity => $entity,
    };

    bless $self, $type;

    return $self;
}

# compute subgroups
# set ro (read only) to 1 if you do not plan to modify the
# entity (in actions like 'accept' od 'bcc'). This
# just return the existing groups but does not create new groups.

sub subgroups {
    my ($self, $targets, $ro) = @_;

    my $groups;
    if ($ro) {
	my @copy = @{$self->{groups}};
	$groups =  \@copy;
    } else {
	$groups =  $self->{groups};
    }

    my $ea =  $self->{ea};

    my $res;

    for my $i (0..$#$groups) {
	my $g = @$groups[$i];

	my $tcount = -1;
	my ($ma, $ua);
	foreach my $member (@$g) {
	    my $found = 0;
	    foreach my $t (@$targets) {
		if ($member eq $t) {
		    $found = 1;
		    $tcount++;
		}
	    }
	    if ($found) {
		push @$ma, $member;
	    } else {
		push @$ua, $member;
	    }
	}

	next if $tcount == -1;

	if ($tcount < $#$g) {
	    @$groups[$i] = $ma;
	    push @$groups, $ua;
	    if ($ro) {
		push @$ea, @$ea[$i];
	    } else {
		my $e = @$ea[$i];
		my $copy = $e->dup;

		# also copy proxmox attribute
		foreach (keys %$e) {$copy->{$_} = $e->{$_} if $_ =~ m/^PMX_/};

		push @$ea, $copy;
	    }
	}
	push @$res, [$ma, @$ea[$i]];
    }

    return $res;
}

1;

__END__

=head1 PMG::RuleDB::ModGroup

The idea behind the modification group object (ModGroup) is that some
modification are target specific. For example a mail can be posted to
two receiver:

  TO: user1@domain1.com, user2@domain2.com

and we have different rules to add disclaimers for those domains:

  Rule1: .*@domain1.com --> add disclaimer one
  Rule2: .*@domain2.com --> add disclaimer two

Both Rules are matching, because there are two different receivers,
one in each domain. If we simply modify the original mail we end up
with a mail containing both disclaimers, which is not what we want.

Another example is when you have receiver specific content filters,
for example you don't want to get .exe files for a specific user, but
allow it for everyone else:

  Rule1: user1@domain1.com && .exe attachments --> remove attachments
  Rule1: .*@domain2.com && .exe attachments --> accept

So you don't want to remeove the .exe file for user2@domain.com

Instead we want to group modification by matching rule targets.

  $mod_group = PMG::RuleDB::ModGroup->new ($targets, $entity);

  $targets ... array of all receivers
  $entity  ... original mail

return a new ModGroup Object. Action Objects which do target specific
modification have to call:

  my $subgroups = $mod_group->subgroups ($rule_targets);

  foreach my $ta (@$subgroups) {
    my ($targets, $entity) = (@$ta[0], @$ta[1]);
    my_modify_entity ($entity, $targets);
  }

That way we seamlessly hide the fact that mails are delivered to more
than one recipient, without the requirement to make a copy for each
recipient (which would lead to many unnecessays notification
mail). Insead we only make a minimum number of copies for specific
target groups.
