#!/usr/bin/perl
# This needs to be stackless, and its object must be a mooadmin.
#use Mooix::Thing;
use Mooix::CallStack;
use Mooix::Conf;
run sub {
	my $this=shift;
	%_=@_;
	my $object=$_{object} || $this->croak("object field required");
	my $delta=$_{delta} || return;

	# Every caller between the first and second stack boundries must be
	# either the object, the object's owner, or the moo admin, or this
	# fails.
	my $stack=Mooix::CallStack::get() || die "bad stack";
	my $bcount=0;
	my $objindex=$object->index;
	my $owner=$object->owner;
	my $ownerindex=$owner->index if $owner;
	my $admin=Mooix::Thing->get($Mooix::Conf::field{mooadminobj});
	my $adminindex=$admin->index if $admin;
	while ($stack) {
		if ($stack->boundry) {
			$bcount++;
			last if ($bcount == 2);
		}
		if ($bcount == 1 && length $stack->method) {
			# A caller we should check.
			if ($stack->index ne $objindex &&
			    $stack->index ne $ownerindex &&
			    $stack->index ne $adminindex) {
				return;
			}
		}
		$stack=$stack->next;
	}
	
	# Start at the object and work our way down. Note that no locking
	# is done, so objects may be moved around while this is in progress.
	while (ref $object) {
		# Notify object of change in mass.
		if ($object->implements('masschange')) {
			my $delta=$object->masschange($delta);
			last unless $delta;
		}
		# Access the field directly to avoid recursion through the
		# method.
		$object->_mass($object->_mass + $delta);
		$object=$object->location;
	}
	return 1;
}
