key0-96/
key0-96/doc/key/
key0-96/doc/key/credits/
key0-96/doc/key/developers/
key0-96/doc/key/developers/resources/
key0-96/setup/caves/
key0-96/setup/help/
key0-96/setup/ruins/
key0-96/src/
key0-96/src/commands/
key0-96/src/events/
key0-96/src/hack/
key0-96/src/sql/
key0-96/src/swing/
key0-96/src/talker/forest/
key0-96/src/talker/objects/
key0-96/src/terminals/
/*
**               j###t  ########## ####   ####
**              j###t   ########## ####   ####
**             j###T               "###L J###"
**          ######P'    ##########  #########
**          ######k,    ##########   T######T
**          ####~###L   ####
**          #### q###L  ##########   .#####
**          ####  \###L ##########   #####"
**
**  $Id$
**
**  Class History
**
**  Date        Name         Description
**  ---------|------------|-----------------------------------------------
**  24Aug98     subtle       start of recorded history
**
*/

package key.commands;

import key.*;
import java.io.*;
import java.util.StringTokenizer;
import java.util.Hashtable;

/**
  *  Used to indicate a command has many names.  This class will
  *  simply forward it's "run" method to the specified command.
  *
  *  The context changing capabilities of this class make it easy
  *  to emulate some EW behaviour, such as "mail block", but using
  *  a context-switch to change the players context to their mailbox,
  *  and executing the 'block' command.  (or something)
 */
public class Also extends Command
{
	private static final long serialVersionUID = 2282992396833160677L;
	public static final AtomicElement[] ELEMENTS =
	{
		AtomicElement.construct( Also.class, Command.class, "command",
			AtomicElement.PUBLIC_ACCESSORS | AtomicElement.REFERENCE,
			"the command to be executed by the proxy" ),
		AtomicElement.construct( Also.class, Atom.class, "context",
			AtomicElement.PUBLIC_FIELD,
			"the context to execute the new command under, or null to leave it be" ),
		AtomicElement.construct( Also.class, Boolean.TYPE, "passArgs",
			AtomicElement.PUBLIC_FIELD,
			"true if user entered arguments are passed to the command" ),
	};
	
	public static final AtomicStructure STRUCTURE = new AtomicStructure( Command.STRUCTURE, ELEMENTS );
	
	private Reference command = Reference.EMPTY;
	public boolean passArgs = true;
	public Reference context = Reference.EMPTY;
	
	public Also()
	{
		setKey( "also" );
		usage = "";
	}
	
	public AtomicStructure getDeclaredStructure()
	{
		return( STRUCTURE );
	}
	
	public void setCommand( Command r )
	{
		command = Reference.to( r, false );
		usage = r.getUsage();
	}
	
	public void setCommand( String s, Atom r )
	{
		if( s.equals( Key.nullString ) )
			command = Reference.EMPTY;
		
		Search se = new Search( s, r );
		
		if( se.result instanceof Command )
			setCommand( ((Command)se.result) );
		else if( se != null )
			throw new InvalidSearchException( "invalid result trying to set field of type Command to " + se.result.toString() );
		else
			throw new InvalidSearchException( "could not find '" + s + "'" );
	}
	
	public Command getCommand()
	{
		try
		{
			return( (Command) command.get() );
		}
		catch( OutOfDateReferenceException e )
		{
			command = Reference.EMPTY;
			usage = "";
			return( null );
		}
		catch( ClassCastException e )
		{
			Log.error( "somebody set " + getId() + ".command wrong (reset)", e );
			command = Reference.EMPTY;
			usage = "";
			return( null );
		}
	}
	
	public String getWhichId()
	{
		Command c = getCommand();
		if( c != null )
			return( getId() + " (also link to '" + c.getWhichId() + "')" );
		else
			return( getId() + " (blank also link)" );
	}
	
	
	public void run( Player p, StringTokenizer args, String fullLine, CategoryCommand caller, InteractiveConnection ic, Flags flags ) throws IOException
	{
		Command c = getCommand();
		
		if( c == null )
		{
			ic.sendError( "This alias is incorrectly set up." );
			return;
		}
		
		if( !passArgs )
		{
			fullLine = c.getName();
			args = new StringTokenizer( "" );
		}
		
		Atom cxt = null;
		
		try
		{
			cxt = (Atom) context.get();
		}
		catch( OutOfDateReferenceException e )
		{
			context = Reference.EMPTY;
		}
		
		if( cxt != null )
		{
			Atom old = p.getContext();
			p.setContext( cxt );
			c.run( p, args, fullLine, caller, ic, flags );
			p.setContext( old );
		}
		else
			c.run( p, args, fullLine, caller, ic, flags );
	}
}