#include "boot.clh"

object PROGRAMMER
    parents	BUILDER;

    name = "Generic Programmer";

    obj		prog_obj;		/* object being programmed */
    str		prog_method;		/* method being programmed */

    verb	"eval" = eval_cmd;
    verb	"@prog*ram" = program_cmd;
    verb	"@prog*ram" : "on" = program_cmd;
    verb	"@ps" = ps_cmd;
    verb	"@kill" = kill_cmd;
    verb	"@verb" = verb_cmd;
    verb	"@verb" : "on" = verb_cmd;
    verb	"@rmv*erb" = rmverb_cmd;
    verb	"@rmv*erb" : "on" = rmverb_cmd;
    verb	"@rmm*ethod" = rmmethod_cmd;
    verb	"@rmm*ethod" : "on" = rmmethod_cmd;
    verb	"@rmva*r" = rmvar_cmd;
    verb	"@rmva*r" : "on" = rmvar_cmd;

    method init
	if (this == PROGRAMMER)
	    this.add_owner(WIZARD);
	else
	    pass();
	endif
    endmethod /* init */

    method eval_cmd
	if (caller != this)
	    return 1;
	endif
	if (!compile(this, "eval_tmp", args[2]))
	    echo("--> " + tostr(this.eval_tmp()));
	    rm_method("eval_tmp");
	endif
    endmethod

    method program_cmd
	var		what;
	ignore		E_METHODNF;

	if (caller != this)
	    return 1;
	elseif (!args[2] && !args[3])
	    echo("Entering programming mode.  Use \".\" to end");
	    prog_obj = NOTHING;
	    this.input_to("done_programming");
	elseif (!args[2] || !args[3])
	    echo("Usage:  @program <method> on <object>");
	    echo("        @program");
	else
	    what = this.match_env(args[4]);
	    if (!what)
		echo("I don't see that here.");
	    else
		prog_obj = what;  prog_method = args[2];
		echo("Programming " + args[2] + " on " + what.id);
		echo("Entering programming mode.  Use \".\" to end");
		this.input_to("done_programming");
	    endif
	endif
    endmethod /* program_cmd */

    method done_programming
	if (prog_obj == NOTHING)
	    compile(args[1]);
	else
	    if (!compile(prog_obj, prog_method, args[1]))
		echo("Method programmed.");
	    endif
	endif
    endmethod /* done_programming */

    method verb_cmd
	var	r, newargs, what, prep;

	if (caller != this)
	    return 1;
	endif
	newargs = explode(args[2]);
	if (!args[2] || !args[3] || !args[4]
	|| (lengthof(newargs)) < 2 || (lengthof(newargs) > 3))
	    echo("Usage:  @verb <verb> <method-to-call> on <obj>");
	    echo("        @verb <verb> <preposition> <method-to-call> on <obj>");
	    return 0;
	endif
	what = this.match_env(args[4]);
	if (!what)
	    echo("I don't see that here.");
	    return 0;
	elseif (lengthof(newargs) == 2)
	    r = what.add_verb(newargs[1], "", newargs[2]);
	else
	    r = what.add_verb(newargs[1], newargs[2], newargs[3]);
	endif
	if (r == E_PERM)
	    echo("Permission denied.");
	else
	    echo("Verb added.");
	endif
	return 0;
    endmethod /* verb_cmd */

    method rmverb_cmd
	var	what;

	if (caller != this)
	    return 1;
	endif
	if (!args[2] || !args[3] || !args[4])
	    echo("Usage:  @rmverb <verb> on <obj>");
	    return 0;
	endif
	what = this.match_env(args[4]);
	if (!what)
	    echo("I don't see that here.");
	elseif (what.rm_verb(args[2]) == E_PERM)
	    echo("Permission denied.");
	else
	    echo("Verb removed.");
	endif
	return 0;
    endmethod /* rmverb_cmd */
	
    method rmmethod_cmd
	var	r, what;
	ignore	E_PERM, E_METHODNF;

	if (caller != this)
	    return 1;
	endif
	if (!args[2] || !args[3] || !args[4])
	    echo("Usage:  @rmmethod <method> on <obj>");
	    return;
	endif
	what = this.match_env(args[4]);
	if (!what)
	    echo("I don't see that here.");
	else
	    r = what.rm_method(args[2]);
	    if (typeof(r) == ERR)
		echo(tostr(r));
	    else
		echo("Method removed.");
	    endif
	endif
	return 0;
    endmethod /* rmmethod_cmd */

    method rmvar_cmd
	var	r, what;
	ignore	E_PERM, E_VARNF;

	if (caller != this)
	    return 1;
	endif
	if (!args[2] || !args[3] || !args[4])
	    echo("Usage:  @rmvar <var> on <obj>");
	    return;
	endif
	what = this.match_env(args[4]);
	if (!what)
	    echo("I don't see that here.");
	else
	    r = what.rm_var(args[2]);
	    if (typeof(r) == ERR)
		echo(tostr(r));
	    else
		echo("Variable removed.");
	    endif
	endif
	return 0;
    endmethod

    method ps_cmd
	var	i, line, task;

	echo("PID     PLAYER          METHOD          STATUS");
	for task in (ps())
	    if (task[4] != this && !("a" in args[2]))
		continue;
	    endif
	    line = pad(tostr(task[1]),7) + " " + pad(task[4].id, 15) + " "
			+ pad(tostr(task[6]) + "." + task[9], 15) + " ";
	    if (task[10] == 0)
		line = line + "MSG    ";
	    elseif (task[10] == 1)
		line = line + "LOCK   ";
	    elseif (task[10] == 2)
		line = line + "TIMER  ";
	    elseif (task[10] == 3)
		line = line + "SYS_MSG";
	    endif
	    echo(line);
	endfor
    endmethod /* ps_cmd */

    method kill_cmd
	var	r, pid;
	ignore	E_PERM;

	pid = tonum(args[2]);
	r = kill(pid);
	if (r == E_PERM);
	    echo("Permission denied.");
	elseif (r != 0)
	    echo("No such process.");
	else
	    echo("Killed.");
	endif
    endmethod /* kill_cmd */
	    
endobject /* PROGRAMMER */