/** (C) Game Page Network, Inc., Confidential, All Rights Reserved */
// Command.java -- GPN command processors
// --paul@gamepage.net, 21jul97

import java.io.*;
import java.util.*;

/** Command abstract class describes a GPN command.
 *
 * To implement a GPN command, subclass Command & provide your own constructor 
 * (with command name and help string) and process method.
 */
public abstract class Command {
  private static Hashtable table = new Hashtable(40);

  // Call this to install a new Command into the hashtable.
  private static void install(String name, Command command) {
    table.put(name, command);
  }
  /** Lookup a command for a client session manager.
   * @param command name
   * @param member name
   * @return Command for name else String error message.
   */
  public static Object lookup(String name, int argc, Client client) {
    Command command = (Command)table.get(name);

    if ( command==null ) {
      return(name+": No such command.");
    }

    if ( command.argc>=0 && argc!=command.argc) {
      return("usage: "+name+" "+
	     ((command.args==null) ? "" : command.args));
    }

    Member member = client.getMember();
    if (member==null &&
	!name.equalsIgnoreCase("login") &&
	!name.equalsIgnoreCase("quit") &&
	!Club.trustedIP(client.getAddress())) {
      // Not currently using the command.anonymous flag.
      return(name+" command requires you to login first.");
    }
    if ( command.coach && !Club.coach(member)) {
      return(name+" command can only be used by a Club Coach.");
    }
    return command;
  }

  public static Command find(String name) {
    return (Command)table.get(name);
  }

  // ---------------------------------------------------------------------
  
  // Command instance fields:
  protected String name;
  protected int argc;		// required argc, else -1 for any argc
  protected String args;	// name of required args
  protected String help;
  protected boolean anonymous;  // allow anonymous operation?
  protected boolean coach;	// allowed use only for club coaches?

  public String toString()      {  return name; }

  /** Command constructor (to be provided for each subclass command).
   * Provide your own constructor which simply calls this super constructor
   * with appropriate name and help string for your command.
   */
  protected Command(String name, int argc, String args, String help) {
    this.name = name;
    this.argc = argc;
    this.args = args;
    this.help = help;  
    this.anonymous = false;	// do not allow anonymous
    this.coach = false;		// do not require coach
    install(name,this);
  }
  
  /** Command process method (to be provided for each subclass command).
   * @param StringTokenizer ARGS can be used to access any command arguments.
   * @param Client indicates the client session issuing the command.
   * @return int STATUS return value.
   */

  /*
  public void process(String request, String arg, StringTokenizer rest,
		      Member member, Table table, Client c) {
  */
  public void process(StringTokenizer args, Client c) {
    // Be sure to implement for each subclass command with correct signature, 
    // else this catchall method will get invoked.
    c.send("! unknown command");
    Club.debug("Command.process catch: "+args);
  }

  // ---------------------------------------------------------------------
  // Initialize the command table (call this from Club.main).
  protected static void loadCommands() {
    new HelpCommand(); new LoginCommand(); 
    new WhoCommand(); new TablesCommand(); 
    new QuitCommand();

    new LogCommand(); new EjectCommand(); new BanCommand();
    new DebugCommand();

    new TalkCommand(); new WhisperCommand(); 
    new KibitzCommand(); new ShoutCommand(); new SoundCommand();
    new MuteCommand(); new UnmuteCommand();
    
    new ObserveCommand(); new OpenCommand(); new JoinCommand();
    new TimerCommand(); new PracticeCommand();
    new StartCommand(); new ResetCommand(); 
    
    new MoveCommand(); new DisplayCommand(); new ListCommand();
    new DrawCommand(); new ResignCommand(); new SaveCommand();

    new ShutdownCommand();
  }  
}  
