#include <lsc.h>

#define INDEX 3
#define ID 8
#define MASTER 20
#define PARENT 20
#define STATUS 8
#define STACKS 4
#define INPUT 16


static object * lsc;

int non_z(mixed data, mixed extra) {
	if (!data) return 0;
	return 1;
}

void update_lsc_list() {
	object * tmp;
	tmp = filter_array(lsc,"non_z", this_object(), 0);
	lsc = tmp;
}

void create() {
	if (!lsc) lsc=({});
}

void reset(int n) {
	update_lsc_list();
}

void register_compiler(object ob) {
	update_lsc_list();
	lsc += ({ ob });
}

string repeat_str(string ch, int n) {
        return sprintf("%'"+ch+"':*s",n,"");
}

/* it'll return ...
"It's a string ....    "
"		123456 "
"/players...#XXXX      "
*/

string format_mixed(mixed data, int len) {
	int n;
	string tmp;

	if (!data || intp(data) ) {
		tmp = data+" ";
		n = strlen(tmp);
		if (n>len) return repeat_str("*",len);
		return (repeat_str(" ",len-n)+tmp);
	}

	if (stringp(data)) {
		n = strlen(data);
		if (n>len) return data[0..len-4]+" ..";
		return data[0..n-1]+repeat_str(" ",len-n);
	}

	if (objectp(data)) {
		tmp = file_name(data);
		n = strlen(tmp);
		if (n>len) return tmp[0..len-4]+" ..";
		return tmp[0..n-1]+repeat_str(" ",len-n);
	}

	/* error */
	return repeat_str("X",len);
}

void show_all() {
	int i, n , ob_num, stat, speed, wtime, stack_size;
	string space, id, input, foo;
	object master, parent;		

	write(format_mixed(" #", INDEX)+
		format_mixed("   Id", ID)+
		format_mixed("Master", MASTER)+
		format_mixed("Parent",PARENT)+
		format_mixed("Status",STATUS)+
		format_mixed("Stk", STACKS)+
		format_mixed("Input",INPUT)+"\n");

	n = sizeof(lsc);
	for ( i=0; i<n; i++) {
		if (!lsc[i]) continue;

		id = (string) lsc[i]->query_process_id();
		master = (object) lsc[i]->query_this_play();
		parent = (object) lsc[i]->query_parent();
		stat = (int) lsc[i]->query_status();
		stack_size = (int) lsc[i]->query_stack_ptr();
		input = (string) lsc[i]->query_input();
		if (!input) input = "<NONE>";
/* index */
		write(format_mixed(i,INDEX));

/* id */
		if (!id) foo=format_mixed("<ROOT>",ID);
		else foo=format_mixed(id,ID);
		write(foo);

/* master */
		write(format_mixed(master, MASTER));

/* parent */
		if (!id) foo=format_mixed("NA",PARENT);
		else if (!parent) foo=format_mixed("Orphaned!",PARENT);
		else {
			foo=format_mixed(parent,PARENT);
		}
		write(foo);

/* status */
		if (stat==IDLE) foo="Idle";
		else if (stat==RUNNING) foo="Running";
		else if (stat==INCOMPLETE_INPUT) foo="Incmplt";
		else if (stat==PAUSED) foo="Paused";
		else if (stat==ERROR) foo="Error";
		write(format_mixed(foo,STATUS));

/* stack size */
		write(format_mixed(stack_size,STACKS));

/* input */
		write(format_mixed(input,INPUT));

		write("\n");
	}
}

void show_process(int num) {
	string input;
	object ob;

	if (num<0 || num>= sizeof(lsc)) return;
        if (!lsc[num]) return;
	ob = lsc[num];
	write(file_name(ob)+"\n");
	write("Stack Size: "+ob->query_stack_ptr()+
		", Speed: "+ob->query__speed()+
		", Wait time: "+ob->query_wait_time() + "\n");
	input = ob->query_input();
	if (input) 
		write("Input: %-200s\n",input);
}

void show_stack_process(int num, int limit) {
	int i,n;
	mixed * stack;
	object ob;

        if (num<0 || num>= sizeof(lsc)) return;
        if (!lsc[num]) return;
        ob = lsc[num];
	write(file_name(ob));
	stack = ob->query_stack();
	if (!stack) return;
	if (!limit) limit = 20;
	n = sizeof(stack);
	write("Stack size: "+n+"\n");
	if (n>limit) n = limit;
	call_other("u/s/square/cyber","print_ret",stack[0..n],0);
}

void show_varlist_process(int num, int limit) {
	int i,n;
	mixed * k;
	mapping varlist;
	object ob;

        if (num<0 || num>= sizeof(lsc)) return;
        if (!lsc[num]) return;
        ob = lsc[num];
        write(file_name(ob)+"\n");
	varlist = ob->query_varlist();
	if (!varlist) return;
	if (!limit) limit = 20;
	k = keys(varlist);
	n = sizeof(k);
	if (n>limit) n = limit;
	for(i=0;i<n;i++) {
		write(k[i]+" : ");
		call_other("u/s/square/cyber","print_ret",varlist[k[i]],1);
	}
}


string kill_process(mixed num) {
	if (stringp(num)) sscanf(num,"%d", num);
	if (!intp(num)) return "non-int";
	if (num<0 || num>= sizeof(lsc)) return "out of range";
	if (!lsc[num]) return "no such obj";
	if (!lsc[num]->remove()) destruct(lsc[num]);
	return "done";
}

int remove() {
	int i,n;
	n = sizeof(lsc);
	for(i=0;i<n;i++) if (lsc[i]) lsc[i]->remove();
	destruct(this_object());
	return 1;
}