#include "boot.clh"

object LOCATED_OBJ
    parents	ROOT_OBJ;

    name = "Generic Located Object";

    obj		location;
    list	contents;

    method init
	if (this == LOCATED_OBJ)
	    this.add_owner(WIZARD);
	else
	    location = #-1;
	    contents = {};
	    pass();
	endif
    endmethod /* init */

    method destroy
	var	thing, thome;
	ignore	E_SERVERDN, E_OBJNF, E_METHODNF;

	if (PERMS_OK)
	    if (location)
		location.remove(this);
	    endif
	    for thing in (contents)
		thome = thing.home;
		if (thome)
		    thing.moveto(thome);
		else
		    thing.moveto(NOTHING);
		endif
	    endfor
	    pass();
	else
	    raise(E_PERM);
	endif
    endmethod /* destroy */

    blocked method location
	return location;
    endmethod /* location */

    method contained_by
	if (location == args[1])
	    return 1;
	elseif (!location)
	    return 0;
	else
	    return location.contained_by(args[1]);
	endif
    endmethod /* contained_by */

    method contents
	return contents;
    endmethod /* contents */

    method match_contents
	var	thing;

	for thing in (contents)
	    if (thing.match(args[1]))
		return thing;
	    endif
	endfor
	return NOTHING;
    endmethod /* match_contents */

    method moveto
	var	dest;
	ignore	E_SERVERDN, E_OBJNF, E_METHODNF;
					/* two sensitive spots, both handled */

	dest = args[1];			/* 1st arg is destination */
	if (dest == location)		/* we're already there! */
	    return 1;			/* (that was easy) */
	elseif (dest == this)		/* can't put something inside itself */
	    return 0;
	elseif (dest.contained_by(this)) /* or inside its location, etc */
	    return 0;
	endif
	lock ("moveto");
/*
 * If there's a destination, and it doesn't accept this, return 0
 * (note that E_SERVERDN here evaluates to FALSE)
 */
	if (dest && !dest.accept(this))
	    return 0;
	endif
/*
 * Remove this from old location, if any.
 * E_SERVERDN here is ignored (will be handled by remote server in
 * SYS_OBJ.boot_server()
 */
	if (location)		
	    location.remove(this);
	endif
/*
 * Update location.
 */
	location = dest;

	return 1;
    endmethod /* moveto */

/*
 * accept - add object to contents list
 */
    method accept
	var	what;				/* what object to add */

	what = args[1];
	contents = contents + what;
	if (serverof(what))			/* if object is visitor, */
	    SYS_OBJ.add_visitor(what, this);	/* add it to visitorlist */
	endif
	return 1;
    endmethod /* accept */

/*
 * remove - remove object from contents list
 */
    method remove
	var	what;

	what = args[1];
	contents = contents - what;
	if (serverof(what))			/* if object is visitor, */
	    SYS_OBJ.rm_visitor(what, this);	/* remove it from visitorlist */
	endif
    endmethod /* remove */

endobject /* LOCATED_OBJ */