/*

 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"


//~ attributes used:

//~ PLAYER (number):
  
const string ROOM = "room";     // current room
const string COINS = "coins";   // coins s/he is carrying

//~ OBJECT (number):
    
const string VALUE = "value";     // what it is worth
    
//~ ROOM (flag):
  
const string SHOP = "shop";      // is this a shop?
  
//~ ROOM (float):
   
// profit shop makes when *customer* buys (eg. 1.2 for 20% profit)
const string PROFIT_BUY = "profit_buy";      


struct fShowStock
{
  Character & player_;
  double profit_;

  // ctor
  fShowStock (Character & player, const double profit) 
    : player_ (player), profit_ (profit) {}
  void operator() (const string & s) 
    {
    ObjectList::iterator i = FindObject (objects (), "id", s);
    if (i == objects ().end ())
      return;   // object does not exist
    Object & o = *i;
    int price = o.getiTotal (VALUE) * profit_;
    player_.send (
      MAKE_STRING (setw (5) << price << "  " << firstLetterCaps (shortDesc (o, player_.prefix ()))));

    } // end of operator()
  
};  // end of fShowStock

void DoList (CommandInfo & info)
{
Character & p (info.player ());

  if (!info.room ().roomFlag (SHOP))
    throw msg ("not_a_shop");
  
   // show stock
  set<string> stock;
  stringToContainer (info.room ().roomString ("shop_stock"), stock);
 
  if (stock.empty ())
    throw msg ("shop_out_of_stock");

  p.send ("shop_stock_heading", messagemap ());

   // show stock
  for_each (ISEQ (stock), fShowStock (p, info.room ().roomFloat (PROFIT_BUY)));
  
} // end of DoList

void DoBuy (CommandInfo & info)
{
Character & p (info.player ());

  if (!info.room ().roomFlag (SHOP))
    throw msg ("not_a_shop");
       
   // get stock
  set<string> stock;
  stringToContainer (info.room ().roomString ("shop_stock"), stock);
  
  ObjectList stockObjects;
  for (set<string>::const_iterator stockIter = stock.begin ();
       stockIter != stock.end ();
       ++stockIter)
    {
    ObjectList::iterator i = FindObject (objects (), "id", *stockIter);
    if (i != objects ().end ())
      stockObjects.push_back (*i);
    }
  
  Object obj = * getAnObject (info.wildcards_ ["what"], stockObjects,
                              "buy_what", "not_in_stock" );
  
  info.sub_ ["what"] = obj;
  int price = obj.getiTotal (VALUE) * info.room ().roomFloat (PROFIT_BUY);
  info.sub_ ["price"].sets ("short", MAKE_STRING (price));
  info.sub_ ["coins"].sets ("short", MAKE_STRING (p.geti (COINS)));
  if (price > p.geti (COINS))
    throw msg ("cannot_afford_to_buy");

  info.sub_ ["who"].sets ("short", p.message ("you"));
  
  CanTakeItem (p, info,  obj);

  GiveUniqueID (obj); // give object and all its children unique IDs
  p.inventory ().push_back (obj);   // add to inventory
  p.seti (COINS, p.geti (COINS) - price);   // adjust down his coins count
    
} // end of DoBuy

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

  cout << "Loading command handlers in " __FILE__ << endl;
    
  COMMAND (DoList);       // list what is for sale in a shop
  COMMAND (DoBuy);        // buy something

  return 0;
  } // end of LoadCommands

static int loadThemUp = LoadCommandsMap ();

