context: using System;
  using System.Collections;
  using System.Collections.Generic;
  using System.Text;
  using Server;
  
  namespace Server.Commands.Generic
  {
  	[Flags]
  	public enum CommandSupport
  	{
  		Single		= 0x0001,
  		Global		= 0x0002,
  		Online		= 0x0004,
  		Multi		= 0x0008,
  		Area		= 0x0010,
  		Self		= 0x0020,
  		Region		= 0x0040,
  		Contained	= 0x0080,
  
  		All			= Single | Global | Online | Multi | Area | Self | Region | Contained,
  		AllMobiles	= All & ~Contained,
  		AllNPCs		= All & ~(Online | Self | Contained),
  		AllItems	= All & ~(Online | Self | Region),
  
  		Simple		= Single | Multi,
  		Complex		= Global | Online | Area | Region | Contained
  	}
  
  	public abstract class BaseCommandImplementor
  	{
  		public static void RegisterImplementors()
  		{
  			Register( new RegionCommandImplementor() );
  			Register( new GlobalCommandImplementor() );
  			Register( new OnlineCommandImplementor() );
  			Register( new SingleCommandImplementor() );
  			Register( new SerialCommandImplementor() );
  			Register( new MultiCommandImplementor() );
  			Register( new AreaCommandImplementor() );
  			Register( new SelfCommandImplementor() );
  			Register( new ContainedCommandImplementor() );
  		}
  
  		private string[] m_Accessors;
  		private AccessLevel m_AccessLevel;
  		private CommandSupport m_SupportRequirement;
  		private Dictionary<string, BaseCommand> m_Commands;
  		private string m_Usage;
  		private string m_Description;
  		private bool m_SupportsConditionals;
  
  		public bool SupportsConditionals
  		{
  			get{ return m_SupportsConditionals; }
  			set{ m_SupportsConditionals = value; }
  		}
  
  		public string[] Accessors
  		{
  			get{ return m_Accessors; }
  			set{ m_Accessors = value; }
  		}
  
  		public string Usage
  		{
  			get{ return m_Usage; }
  			set{ m_Usage = value; }
  		}
  
  		public string Description
  		{
  			get{ return m_Description; }
  			set{ m_Description = value; }
  		}
  
  		public AccessLevel AccessLevel
  		{
  			get{ return m_AccessLevel; }
  			set{ m_AccessLevel = value; }
  		}
  
  		public CommandSupport SupportRequirement
  		{
  			get{ return m_SupportRequirement; }
  			set{ m_SupportRequirement = value; }
  		}
  
  		public Dictionary<string, BaseCommand> Commands
  		{
  			get{ return m_Commands; }
  		}
  
  		public BaseCommandImplementor()
  		{
  			m_Commands = new Dictionary<string, BaseCommand>( StringComparer.OrdinalIgnoreCase );
  		}
  
  		public virtual void Compile( Mobile from, BaseCommand command, ref string[] args, ref object obj )
  		{
  			obj = null;
  		}
  
  		public virtual void Register( BaseCommand command )
  		{
  			for ( int i = 0; i < command.Commands.Length; ++i )
  				m_Commands[command.Commands[i]] = command;
  		}
  
  		public bool CheckObjectTypes( BaseCommand command, Extensions ext, out bool items, out bool mobiles )
  		{
  			items = mobiles = false;
  
  			ObjectConditional cond = ObjectConditional.Empty;
  
  			foreach ( BaseExtension check in ext )
  			{
  				if ( check is WhereExtension )
  				{
  					cond = ( check as WhereExtension ).Conditional;
  
  					break;
  				}
  			}
  
  			bool condIsItem = cond.IsItem;
  			bool condIsMobile = cond.IsMobile;
  
  			switch ( command.ObjectTypes )
  			{
  				case ObjectTypes.All:
  				case ObjectTypes.Both:
  				{
  					if ( condIsItem )
  						items = true;
  
  					if ( condIsMobile )
  						mobiles = true;
  
  					break;
  				}
  				case ObjectTypes.Items:
  				{
  					if ( condIsItem )
  					{
  						items = true;
  					}
  					else if ( condIsMobile )
  					{
  						command.LogFailure( "You may not use a mobile type condition for this command." );
  						return false;
  					}
  
  					break;
  				}
  				case ObjectTypes.Mobiles:
  				{
  					if ( condIsMobile )
  					{
  						mobiles = true;
  					}
  					else if ( condIsItem )
  					{
  						command.LogFailure( "You may not use an item type condition for this command." );
  						return false;
  					}
  
  					break;
  				}
  			}
  
  			return true;
  		}
  
  		public void RunCommand( Mobile from, BaseCommand command, string[] args )
  		{
  			try
  			{
  				object obj = null;
  
  				Compile( from, command, ref args, ref obj );
  
  				RunCommand( from, obj, command, args );
  			}
  			catch ( Exception ex )
  			{
  				from.SendMessage( ex.Message );
  			}
  		}
  
  		public string GenerateArgString( string[] args )
  		{
  			if ( args.Length == 0 )
  				return "";
  
  			// NOTE: this does not preserve the case where quotation marks are used on a single word
  
  			StringBuilder sb = new StringBuilder();
  
  			for ( int i = 0; i < args.Length; ++i )
  			{
  				if ( i > 0 )
  					sb.Append( ' ' );
  
  				if ( args[i].IndexOf( ' ' ) >= 0 )
  				{
  					sb.Append( '"' );
  
gt: 					sb.Append( args[i] );