#ifndef BABBLEMUD_CHARACTER_H
#define BABBLEMUD_CHARACTER_H

// a game character
// could be a mob, or a connected player

class Character : public TopThing
{

private:
 
  Character (const Character &);  // do not allow copy construction!!!

public:

  bool closing_;     // true if they are about to leave us
  string prompt_;      // the current prompt

  // this is a mob
  virtual const bool mob () const { return true; }

  // ctor
  Character () : closing_ (false) {}
  virtual ~Character () 
    { }; // dtor
  
  // send a message which has been decoded
  virtual void send (const string & msg, const bool newline = true) {};
  // send a message code - lookup in whichmap
  virtual void send (const string & code, const StringMap & whichmap, const bool newline = true) {};
  // send a decoded message, substitute with subs
  virtual void send (const string & msg, const ThingMap & subs, const bool newline = true) {};
  // send a message code - lookup in whichmap, substitute with subs
  virtual void send (const string & code, const StringMap & whichmap, 
                     const ThingMap & subs, const bool newline = true, 
                     const bool notFoundIsOk = false) {};
       
  virtual bool IsPlaying () const { return !closing_; }

  void ClosePlayer () { closing_ = true; }    // get rid of this character
 
  virtual void Save () {}           // save player to disk

  bool HaveFlag   (const string & name);  // is flag set?
  void NeedFlag   (const string & name,   // flag must be set
                   const string & message = "",
                   const bool lookedUp = false);    // true if message, false if code
  void NeedNoFlag (const string & name,   // flag must not be set
                   const string & message = "",  
                   const bool lookedUp = false);    // true if message, false if code
  
  void DoCommand (const string & command, const bool forced = false);  // simulate player input (eg. look)

  //~ // get the total of all items carried (eg. total weight)
  //~ template <typename RT>
  //~ RT getTotal (const string & what) const 
    //~ {
    //~ ObjectListMap::const_iterator i = contents_.find (c);
    //~ if (i == contents_.end ())
      //~ throw runtime_error ("Container " + c + " does not exist.");
    //~ return for_each (ISEQ (i->second), Object::fGetTotal<RT> (c, what)).GetTotal ();
    //~ }
  
  int  getiTotal (const string & c, const string & what) const 
    { 
    ObjectListMap::const_iterator i = items_.find (c);
    if (i == items_.end ())
      return 0;
    return for_each (ISEQ (i->second), Object::fGetTotal<int> (what)).GetTotal ();
    }

  double getfTotal (const string & c, const string & what) const 
    { 
    ObjectListMap::const_iterator i = items_.find (c);
    if (i == items_.end ())
      return 0;
    return for_each (ISEQ (i->second), Object::fGetTotal<double> (what)).GetTotal ();
    }

  // return the appropriate message for this guy
  const string error (const string & code);
  
  // return the appropriate message for this guy
  const string message (const string & code);
  
  Character * GetPlayer (const string & name, 
                      const string & noNameMessage, 
                      const bool & notme = false,
                      const bool & inroom = false);

  ObjectList & inventory () { return items_ ["inventory"]; }

  // language prefix (eg. fr_, it_, en_ )
  const string prefix () const { return gets ("prefix"); }

  const string GetCoins (const int coins) const;

  const string GetName () const;
  const int GetRoom () const;

};  // end of class Character 

// character list type
typedef std::list <Character*> CharacterList;
typedef CharacterList::iterator CharacterListIterator;

// map of currently playing people (by ID) for fast lookup
class Character;
typedef std::map <string, Character*> PlayingMap;

class World;
  
// class to sending various things to command handlers
class CommandInfo
  {
  public:
    
  StringMap wildcards_;     // the wildcards from their command
  ThingMap  sub_;           // message substitution (eg. %<player> = his name)
  Object    command_;       // the command object
  string    line_;          // what they actually typed
  string    handlerName_;   // name of handler (eg. "DoLook")
  Character * player_;      // player who typed command
  Character * target_;      // target (eg. give sword to Nick : Nick is target)
  World     & room_;        // current room
  Object    * spell_;       // the spell name, if applicable
  
  Character &  player () { return *player_; }
  // target of this command
  Character &  target () 
    { 
    if (target_ == NULL)
      throw msg ("no_target");
    return *target_; 
    }
  // room they are in
  World & room () 
    { 
    return room_; 
    }
  // the spell name
  Object & spell () 
    { 
    if (spell_ == NULL)
      throw msg ("no_spell");
    return *spell_; 
    }
  
  // ctor
  CommandInfo (Character *  player, World & room) 
    : player_ (player), target_ (NULL), room_ (room), spell_ (NULL) {}
  
  };  // end of CommandInfo  
  
void PlayerToRoom (Character & p,    // which player
                   const int & vnum,  // which room
                   CommandInfo & info); // for messages

#endif  // BABBLEMUD_CHARACTER_H

