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 ##########   #####"
**
**  Class History
**  
**  Date        Name         Description
**  ---------|------------|-----------------------------------------------
**  22Jun97     subtle       added primitive SuppressionList support, now
**                           also modifies directedAt scape if people are
**                           blocking.
**
*/

package key.effect;

import key.*;
import java.util.StringTokenizer;
import java.util.Enumeration;
import java.util.Vector;

/**
  *  A communication effect that goes to an entire
  *  medium, such as a room or channel.  (Technically,
  *  it goes to any scape)
 */
public class Directed extends Communication
{
	Splashable directedAt;
	String selfMessage;
	String otherMessage;
	char targetCode;
	
	/**
	  *  Creates a new communication
	  *
	  * @param from the player who sent it
	  * @param to the player who's meant to receive the tell, or, alternatively
	  *           a _temporary_ scape (one generated for the explicit purpose
	  *           of sending a group of players).  The reason for the temporary
	  *           'ness' of it is that the players which are blocking will be
	  *           removed from this scape.  Consider this fair warning.
	  * @param main the message to show to everyone in the location scape
	  * @param self the UNPARSED message to show to the player - thats
	  *             what the tCode is for, what to replace the recipients name
	  *             with.
	 */
	public Directed( Player from, Splashable to, String self, String other, char tCode )
	{
		super( from );
		
		directedAt = to;
		otherMessage = other;
		selfMessage = self;
		targetCode = tCode;
	}

	public String getMessage( Player receiver )
	{
		if( directedAt instanceof PlayerGroup )
			originator.putCode( targetCode, ((PlayerGroup)directedAt).allNames( receiver ) );
		else
		{
			if( directedAt == receiver )
				originator.putCode( targetCode, "you" );
			else
				originator.putCode( targetCode, ((Player)directedAt).getName() );
		}
		
		if( originator == receiver )
			return( Grammar.substitute( selfMessage, originator.getCodes() ) );
		else
			return( Grammar.substitute( otherMessage, originator.getCodes() ) );
	}
	
		//  problem with this routine as it stands - there is no 'double'
		//  scan - if you send a tell and someone's blocking, the originator
		//  gets the error, but the people who still receive it, it looks like
		//  the tell went through to that other person...
		//
		//  modifying the scape is a good thing - it means that multi-tells
		//  will skip blocking individuals in the future.
	public void cause()
	{
		SuppressionList sl = new SuppressionList();
		PlayerGroup plg = null;
		
		directedAt.splash( this, sl );
		
		if( sl.count() > 0 )
		{
			boolean remove = false;
			boolean noblocked = false;
			Vector blockedNames = null;
			
			if( directedAt instanceof PlayerGroup )
			{
				remove = true;
				plg = (PlayerGroup) directedAt;
			}
			
			for( Enumeration e = sl.elements(); e.hasMoreElements(); )
			{
				SuppressionList.Entry sle = (SuppressionList.Entry) e.nextElement();
				boolean isActuallyBlocked;
				
				originator.sendFailure( sle.getText() );
				
				isActuallyBlocked = sle.isActuallyBlocked();
				
				if( !isActuallyBlocked )
					noblocked = true;
				
				if( remove && isActuallyBlocked )
				{
					Player bp = (Player) sle.getFrom();
					
					if( blockedNames == null )
						blockedNames = new Vector( 10, 10 );
					
					blockedNames.addElement( bp.getName() );
					
					try
					{
						plg.unlinkPlayer( bp );
					}
					catch( NonUniqueKeyException ex )
					{
						Log.debug( this, ex.toString() + " during a blocked directed suppresion" );
					}
					catch( BadKeyException ex )
					{
						Log.debug( this, ex.toString() + " during a blocked directed suppresion" );
					}
				}
			}
			
			if( remove || noblocked )
			{
				if( remove && plg.numberPlayers() == 0 )
					;
				else
					originator.splash( this, null );
				
				if( blockedNames != null )
				{
						//  now we should notify other people who received this
						//  event of the people who were blocking
						//  build the list of names:
					String nameList = Grammar.enumerate( blockedNames.elements() );
					blockedNames = null;
					
						//  notify them all individually:
					Effect eff;
					
					if( plg.getNumberPlayers() == 1 )
						eff = new key.effect.BlockNotification( originator, plg, "(" + nameList + " was blocking " + originator.getName() + " and has been removed from the reply list)" );
					else
						eff = new key.effect.BlockNotification( originator, plg, "(" + nameList + " were blocking " + originator.getName() + " and have been removed from the reply list)" );
					
					eff.cause();
				}
				
					//  generate reply lists here?
			}
			else
			{
				//  its just an individual, we've already output
				//  a message, do nothing
			}
		}
		else
			originator.splash( this, null );
		
			//  this will log all tells
		//Log.log( "tells", getMessage( null ) );
	}
	
	public void sending( String message, Player p )
	{
		p.addHistoryLine( message );
	}
}