#include "boot.clh"

object ROOT_OBJ
    list	owners;
    num		public = 1;
    str		name = "Root Object";

    verb	"@rename" : "to" = rename_verb;

    method init
	if (this == ROOT_OBJ)
	    this.add_owner(WIZARD);
	elseif (PERMS_OK)
	    owners = {};
	else
	    raise E_PERM;
	endif
    endmethod

    method clone
	var	new;

	if (!PERMS_OK && !public)
	    raise(E_PERM);
	else
	    new = clone();
	    new.init();
	    new.add_owner(player);
	    if (args)
		new.set_name(args[1]);
	    endif
	    return new;
	endif
    endmethod /* clone */

    method destroy
	var	owner;

	if (PERMS_OK)
	    for owner in (owners)
		owner.rm_creation(this);
	    endfor
	    destroy();
	else
	    raise(E_PERM);
	endif
    endmethod /* destroy */

    method name
	return name;
    endmethod /* name */

    method id
	return (name + "(" + tostr(this) + ")");
    endmethod /* id */

    method sdesc
	return ("You see " + name + " here.");
    endmethod /* sdesc */

    method set_name
	if (PERMS_OK) 
	    name = args[1];
	else
	    raise(E_PERM);
	endif
    endmethod /* set_name */

    method rename_verb
	var	r;
	ignore	E_RANGE;

	if (!this.match(args[2]))
	    return 1;
	elseif (!PERMS_OK)
	    player.tell("You can't rename that.");
	    return 0;
	endif
	r = this.set_name(args[4]);
	if (r == E_RANGE)
	    player.tell("You can't use that new name.");
	else
	    player.tell("Name set.");
	endif
    endmethod /* rename_verb */

    method publish
	if (!PERMS_OK)
	    raise(E_PERM);
	else
	    public = 1;
	endif
    endmethod

    method unpublish
	if (!PERMS_OK)
	    raise(E_PERM);
	else
	    public = 0;
	endif
    endmethod

    method add_parent
	if (!PERMS_OK)
	    raise(E_PERM);
	else
	    chparents(parents + args[1]);
	endif
    endmethod

    method rm_parent
	if (!PERMS_OK)
	    raise(E_PERM);
	else
	    chparents(parents - args[1]);
	endif
    endmethod

    method chparents
	if (!PERMS_OK)
	    raise(E_PERM);
	else
	    chparents(args[1]);
	endif
    endmethod

    method add_verb
	if (!PERMS_OK)
	    raise(E_PERM);
	else
	    return add_verb(args[1], args[2], args[3]);
	endif
    endmethod /* add_verb */

    method rm_verb
	if (!PERMS_OK)
	    raise(E_PERM);
	else
	    return rm_verb(args[1]);
	endif
    endmethod

    method rm_method
	if (!PERMS_OK)
	    raise(E_PERM);
	else
	    return rm_method(args[1]);
	endif
    endmethod

    method rm_var
	if (!PERMS_OK)
	    raise(E_PERM);
	else
	    return rm_var(args[1]);
	endif
    endmethod

    method owners
	return owners;
    endmethod /* owners */

    method add_owner
	if (PERMS_OK)
	    owners = owners + args[1];
	    args[1].add_creation(this);
	else
	    raise(E_PERM);
	endif
    endmethod /* add_owner */

    method rm_owner
	if (PERMS_OK)
	    owners = owners - args[1];
	    args[1].rm_creation(this);
	else
	    raise E_PERM;
	endif
    endmethod /* rm_owner */

    method show
	var	vars;
	var	item;

	player.tell(this.id + "   Size:  " + tostr(objsize()) + " bytes");
	if (parents)
	    player.tell("Parents:  " + tostr(parents));
	else
	    player.tell("No parents.");
	endif
	if (!public && !PERMS_OK)
	    player.tell("The rest of the object is not public.");
	    return;
	endif

	vars = vars();
	if (vars)
	    for item in (vars)
		player.tell("  " + item + ":  " + tostr(getvar(item)));
	    endfor
	else
	    player.tell("No vars.");
	endif

    endmethod /* show */

    method verbs
	if (PERMS_OK || public)
	    return verbs();
	endif
    endmethod /* verbs */

    method methods
	if (PERMS_OK || public)
	    return methods();
	endif
    endmethod /* methods */
	
    method spew_method
	var	code;
	ignore	E_METHODNF;

	if (!PERMS_OK && !public)
	    raise E_PERM;
	endif
	code = spew_method(args[1]);
	if (code == E_METHODNF);
	    return "That object does not define that method.";
	else
	    return code;
	endif
    endmethod /* spew_method */

    method list_method
	var	code, parent;
	ignore	E_METHODNF;

	if (!PERMS_OK && !public)
	    raise E_PERM;
	endif
	code = list_method(args[1], 0, 0);
	if (code)
	    return code;
	endif
	/* didn't find it; look on parents */
	parent = find_method(args[1]);
	if (parent)
	    code = parent.list_method(args[1]);
	    if (code)
		return "That object does not define that method, but its ancestor " + parent.id + " does:\n" + code;
	    endif
	endif
	return "That object does not define that method.";
    endmethod /* list_method */
endobject /* ROOT_OBJ */