/*
Cellular-U phone

the U-phone is a funky object, since they all share a common pool of
strings and functions, as well as a subscriber list. Thus, each phone
only has a few local variables, and a couple references to other
functions.
*/

#define	PHONENUM	#6

/* shared strings */
PHONENUM.nam = "Cell-U-lar One cellular phone";
PHONENUM.dsc = "a small black portable telephone with the Cell-U-lar One corporation logo on it. a little label on the side has instructions for use";
PHONENUM.txt = "instructions: list, dial '#', answer, hangup, say, on, off";
PHONENUM.hmsg = "perhaps you should hang up first.\n";

/* put the first phone in its subscriber list */
PHONENUM.plist = listnew(PHONENUM);

/* null these to be safe */
PHONENUM.ohook = NULL;
PHONENUM.cfrom = NULL;
PHONENUM.dest = NULL;
PHONENUM.user = NULL;



/* list current phones / locations */
func PHONENUM.list
{
	foreach $phone in (#self.plist) {
		if($phone.user.nam != NULL) {
			echo($phone," - ",$phone.user.nam);
			if($phone.ohook != NULL)
				echo(" (in use)\n");
			else
				echo("\n");
		}
	}
}



/* talk into the phone */
func PHONENUM.say
{
	if(#self.ohook == NULL) {
		echo("the phone is hung up\n");
		foreach $guy in (#actor._loc._ply) {
			if($guy != #actor) {
				echoto($guy,#actor.nam," says, \"");
				foreacharg $tmp
					echoto($guy,$tmp," ");
				echoto($guy,"\"\n");
			} else {
				echo("You say, \"");
				foreacharg $tmp
					echo($tmp," ");
				echo("\"\n");
			}
		}
		return;
	}

	echoto(#self.ohook.user,#actor.nam," says, \"");
	foreacharg $tmp
		echoto(#self.ohook.user,$tmp," ");
	echoto(#self.ohook.user,"\" into the phone\n");

	echo("You say, \"");
	foreacharg $tmp
		echo($tmp," ");
	echo("\" into the phone\n");
}



/* dial a phone */
func PHONENUM.dial
{
	if(#self.ohook) {
		echo(PHONENUM.hmsg);
		return;
	}

	if($# != 1) {
		echo("dial what number ? (give the #, not the user)\n");
		return;
	}
	$num = atoobj($1);
	if($num == NULL) {
		echo($1," cannot be completed as dialed. please check the number and try again.\n");
		return;
	}

	if(listsearch(#self.plist,$num) == NULL) {
		echo($num," is not in service.\n");
		return;
	}

	if($num.ohook != NULL) {
		echo($num," is busy.\n");
		return;
	}

	if($num.user == NULL) {
		echo($num," is turned off.\n");
		return;
	}

	/* mark the other phone as being rung by us. */
	$num.cfrom = #self;

	/* mark us as trying to talk to them */
	$tmp = #self.ohook = $num;
	if($tmp == NULL)
		echo("cannot unhook phone: ",$tmp,"\n");

	echoto($num.user,$num.nam," rings softly\n");
	echo("...ring...\n");
}
chmod(&PHONENUM.dial,"W:rs");



/* answer a phone */
func PHONENUM.answer
{
	if(#self.ohook) {
		echo(PHONENUM.hmsg);
		return;
	}

	if(#self.cfrom == NULL) {
		echo("the other party has hung up\n");
		return;
	}

	$tmp = #self.ohook = #self.cfrom;
	if($tmp == NULL)
		echo("cannot unhook phone: ",$tmp,"\n");

	#self.user = #actor;
	#self.cfrom = NULL;

	echoto(#self.ohook.user,#actor.nam," answers the phone\n");
	echo("you are connected to ",#self.ohook.user.nam,"\n");
}
chmod(&PHONENUM.answer,"W:rs");



/* hang up a phone */
func PHONENUM.hangup
{
	if(#self.ohook == NULL) {
		echo("it is already hung up\n");
		return;
	}

	echoto(#self.ohook.user,"<click>\n",#actor.nam," hangs up the phone\n");
	#self.ohook.ohook = NULL;
	#self.ohook = NULL;
	echo("<click>\n");
}
chmod(&PHONENUM.hangup,"W:rs");




/* turn on a phone */
func PHONENUM.on
{
	if(#self.user) {
		echo("it is already on.\n");
		return;
	}
	#self.user = #actor;
	#self.ohook = NULL;
	echo("you turn the phone on.\n");
}
chmod(&PHONENUM.on,"W:rs");




/* turn off a phone */
func PHONENUM.off
{
	if(#self.user == NULL) {
		echo("it is already off.\n");
		return;
	}
	
	if(#self.ohook.user) {
		echoto(#self.ohook.user,"<click>\n",#actor.nam," turns off the phone\n");
		#self.ohook.ohook = NULL;
	}

	#self.ohook = NULL;
	#self.user = NULL;
	echo("<click>\n");
}
chmod(&PHONENUM.off,"W:rs");




/* make a new phone - clone a phone of my own! */
func PHONENUM.clone
{
	$phone = @.create(PHONENUM.nam);
	if($phone == NULL) {
		echo("create failed: ",error($phone),"!!\n");
		return;
	}

	/* share descs */
	$phone.nam = &PHONENUM.nam;
	$phone.dsc = &PHONENUM.dsc;
	$phone.txt = &PHONENUM.txt;

	/* share subscriber list */
	$phone.plist = &PHONENUM.plist;

	/* add to subscriber list */
	*$phone.plist = listadd($phone.plist,$phone);
	echo("added new phone ",$phone," to subscriber list\n");

	/* share functions */
	$phone.clone = &PHONENUM.clone;
	$phone.update = &PHONENUM.update;
	$phone.dial = &PHONENUM.dial;
	$phone.answer = &PHONENUM.answer;
	$phone.hangup = &PHONENUM.hangup;
	$phone.say = &PHONENUM.say;
	$phone.list = &PHONENUM.list;
	$phone.on = &PHONENUM.on;
	$phone.off = &PHONENUM.off;

	/* unshared vars */
	$phone.ohook = NULL;
	$phone.dest = NULL;
	$phone.cfrom = NULL;
	$phone.user = NULL;
}
/* make it so that only the telephone company can see/use this */
chmod(&PHONENUM.clone,"O:r");




/* update a phone's software - reload it from the master phone */
func PHONENUM.update
{
	if($1 == NULL) {
		echo("which phone?\n");
		return;
	}
	$num = atoobj($1);
	if(!isobj($num)) {
		echo("invalid number\n");
		return;
	}

	/* share descs */
	$num.nam = &PHONENUM.nam;
	$num.dsc = &PHONENUM.dsc;
	$num.txt = &PHONENUM.txt;

	/* share subscriber list */
	$num.plist = &PHONENUM.plist;

	/* share functions */
	$num.clone = &PHONENUM.clone;
	$num.update = &PHONENUM.update;
	$num.dial = &PHONENUM.dial;
	$num.answer = &PHONENUM.answer;
	$num.hangup = &PHONENUM.hangup;
	$num.say = &PHONENUM.say;
	$num.list = &PHONENUM.list;
	$num.on = &PHONENUM.on;
	$num.off = &PHONENUM.off;

	/* unshared vars */
	$num.ohook = NULL;
	$num.dest = NULL;
	$num.cfrom = NULL;
	$num.user = NULL;
	echo("updated service for ",$num,"\n");
}
/* make it so that only the telephone company can see/use this */
chmod(&PHONENUM.update,"O:r");



/* add a phone to the service list. */
func PHONENUM.addphone
{
	if($1 == NULL) {
		echo("which phone?\n");
		return;
	}
	$num = atoobj($1);
	if(isobj($num)) {
		*PHONENUM.plist = listadd(PHONENUM.plist,$num);
		echo("added\n");
	} else {
		echo("invalid number\n");
	}
}