/*

 BabbleMud - A MUD server

 Author:  Nick Gammon 
          http://www.gammon.com.au/ 

(C) Copyright Nick Gammon 2004. Permission to copy, use, modify, sell and
distribute this software is granted provided this copyright notice appears
in all copies. This software is provided "as is" without express or implied
warranty, and with no claim as to its suitability for any purpose.
 
*/

#include "commands.h"

struct fShowEffect
{
  Character & player_;
   // ctor
  fShowEffect (Character & player) : player_ (player){}
  void operator() (const Object & o) 
    {
    player_.send (MAKE_STRING (" " << o.gets ("effect") << " by " << o.geti ("by")));
    } // end of operator()
  
};  // end of fShowEffect

struct fShowSpell
{
  Character & player_;
  // ctor
  fShowSpell (Character & player) : player_ (player){}
  void operator() (const Object & o) 
    {
    CACHE_COLOURS string OneSpellColour = control ().gets ("colour_one_spell");
    
    // only show active spells
    if (!o.getb ("active"))
      return;
    
    player_.send (MAKE_STRING (OneSpellColour << setw (15) << firstLetterCaps (o.gets ("name")) 
            << RESET << " - " << o.gets ("summary")));
    } // end of operator()
  
};  // end of fShowSpell

void DoSpells (CommandInfo & info)
{
CACHE_COLOURS string SpellListColour = control ().gets ("colour_spell_list");

Character & p (info.player ());
ObjectList & spells = control ().items_ ["spells"];

  p.send (SpellListColour + makeHeading ("Spells") + RESET);
  for_each (ISEQ (spells), fShowSpell (p));

} // end of DoSpells

struct fApplyEffect
{
  Character & player_;
  CommandInfo & info_;
   // ctor
  fApplyEffect (Character & player, CommandInfo & info) 
    : player_ (player), info_ (info) {}
  void operator() (const Object & o) 
    {
    string effect = o.gets ("effect");  // what to effect
    int by = o.geti ("by");             // by how much
    string type = o.gets ("type");      // type of effect
    
    // now = do it now
    if (type == "now")
      {
      int value = player_.geti (effect);  // current value
      value += by;  // amend it
      if (value < 0)
        value = 0;  // not negative
      player_.seti (effect, value);   // set new value
      }
    else if (type == "every") // every = do it later
      {
      int interval = o.geti ("interval", 5);  // default every 5 seconds
      if (interval < 1)
        interval = 1;
      int count = o.geti ("count", 3);  // default 3 times
      if (count < 1)
        count = 1;
      Event e ("EventEffect", interval * 1000, count, 0, o);
      e.sets ("id", player_.gets ("id")); // which player
      // TODO: fix this
      // do substitutions in messages (if any)
      //~ e.sets ("msg_target", FixMessage (e.gets ("msg_target"), info_, false));
      //~ e.sets ("msg_room",   FixMessage (e.gets ("msg_room"), info_, false));
      eventQueue ().push (e); // queue it
      }
    } // end of operator()
  
};  // end of fApplyEffect

void DoCast (CommandInfo & info)
{
Character & p (info.player ());
Character & target (info.target ());
Object & spell = info.spell ();

string name = spell.gets ("name");

  // now see if we have learnt it
  set<string> knownSpells;
  stringToContainer (p.gets ("spells"), knownSpells);
  
  if (knownSpells.find (name) == knownSpells.end ())
    throw msg ("have_not_learnt_spell");

  // TODO: check other things, like do we have enough mana or whatever
  
  // lala lala
  
  // OK, we are going to do it - apply each effect
  for_each (ISEQ (spell.contents_), fApplyEffect (target, info));

  // set up messages to be sent - fix them to replace things like <target>
  //   however without adding a newline, that will be done later
      
  // success messages are actually in the spell - copy back to our copy
  // of the command object
  for (StringMap::const_iterator msg_iter = spell.get_sdata ().begin ();
      msg_iter != spell.get_sdata ().end ();
      ++msg_iter)
    if (msg_iter->first.find ("success_") != string::npos)
      info.command_.sets (msg_iter->first, msg_iter->second);
  
  //~ // special case - casting on yourself
  if (&p == &target)
    info.sub_ ["target"].sets ("short", "yourself");    // and 'himself' when others look??????
  
} // end of DoCast


static int LoadCommandsMap ()
  {
static CommandHandlerMap & commandmap = getCommandHandlerMap ();

  cout << "Loading command handlers in " __FILE__ << endl;
    
  COMMAND (DoSpells);  // show spells
  COMMAND (DoCast);    // cast a spell

  return 0;
  } // end of LoadCommands

static int loadThemUp = LoadCommandsMap ();
