// MorgenGrauen MUDlib
//
// container/items.c -- creating extra items in room
//
// $Id: items.c 8811 2014-05-09 17:30:37Z Zesstra $

// extra items handling
//
//	AddItem(string filename, int refresh)
//	  Clones an item and puts it into the room. <refresh> may be
//	  on of the following:
//	  REFRESH_NONE: No refresh done until reboot.
//	  REFRESH_DESTRUCT: Refresh on reset if item was destructed.
//	  REFRESH_REMOVE: Refresh on reset if item was removed from room.
//	  REFRESH_ALWAYS: Create a new clone on every reset.
//
// The commands are implemented as properties P_ITEMS as mapping. They are 
// stored locally (_set_xx) as mapping to speed up the routines 
// in this module.
// 
// Format of key and data in the P_ITEMS mapping:
//
// ([ key1 : refresh1; obp1; arr1, ..., keyn : refreshn; obpn; arrn ])

#include <sys_debug.h>
#pragma strict_types
#pragma save_types
#pragma range_check
#pragma no_clone

#define NEED_PROTOTYPES
#include <thing/properties.h>
#include <rooms.h>
#include <container.h>
#undef NEED_PROTOTYPES
#include <defines.h>
#include <config.h>
#include <properties.h>
#include <moving.h>
#include <daemon.h>

protected void create()
{ 
  Set(P_ITEMS,({}));
  Set(P_ITEMS,SECURED,F_MODE_AS);
  
  OBJECTD->QueryObject();  // querying general objects
}

protected void create_super()
{
  set_next_reset(-1);
}

/* Kram zum Aufraeumen von multiplen gleichen Items im Container. */
private object removeable_ob(object ob)
{
  if(!query_once_interactive(ob) && !living(ob))
  {
    return ob;
  }

  return 0;
}

protected varargs void remove_multiple(int limit, mixed fun)
{
  object *inh = all_inventory(ME)-({0});

  inh=filter(inh,#'removeable_ob);
  foreach(mixed item : QueryProp(P_ITEMS))
  {
    inh-=({item[0]});
  }

  if(!stringp(fun) && !closurep(fun))
  {
    fun="description_id";
  }
  object **sorted_inh=unique_array(inh,fun,0);
  foreach(object *arr : sorted_inh)
  {
    if(sizeof(arr)<=limit)
    {
      continue;
    }
    catch(call_other(arr[limit ..], "remove"); publish);
  }
}


/* Item handling */
public varargs object AddItem(mixed filename, int refresh, mixed props) 
{
  string file;
  object ob;
  int i;

  if(pointerp(filename))
  {
    for(i=sizeof(filename);i--;)
    {
      filename[i] = (string)master()->make_path_absolute( filename[i] );
    }
      
    file=filename[random(sizeof(filename))];
  }
  else 
  {
    file=filename=(string)master()->make_path_absolute(filename);
  }
  
  if(props==1)
  {
    catch(ob=load_object(file); publish);
  }
  else
  {
    catch(ob=clone_object(file); publish);
  }
  
  if(objectp(ob))
  {
    ob->move(ME,M_NOCHECK|M_NO_ATTACK);
    // mit Absicht keine Pruefung aufs Move, wenns nicht geht, solls 2s
    // spaeter auf der Ebene buggen, weil praktisch niemand im create() das
    // Ergebnis vom AddItem() prueft.
  }

  // In P_ITEMS vermerken, es sei denn, REFRESH_NONE ist gegeben, in dem
  // Fall ist die Speicherung voellig unnoetig.
  // TODO: Pruefen, ob das wirklich problemlos geht. Bis dahin werden auch
  // TODO::REFRESH_NONE-Items vermerkt. (s. clean_up() in /std/room.c)
  //if (!(refresh&REFRESH_NONE)) {
    SetProp(P_ITEMS,QueryProp(P_ITEMS)+
      ({ 
        ({
          ob,        // RITEM_OBJECT
          filename,  // RITEM_FILE
          refresh    // RITEM_REFRESH
        })+
        ((mappingp(props) || props==1) ? ({props}) : ({}))
      }));
  //}

  if(ob && mappingp(props)) 
    walk_mapping(props,symbol_function("SetProp",ob));
  
  return ob;
}


private void ri_rem_ob(object ob)
{
  object *inv;

  if(objectp(ob) && environment(ob)==this_object())
  {
    inv=deep_inventory(ob);

    foreach(object o : inv)
    {
      o->remove(1);
      if(objectp(o))
      {
        destruct(o);
      }
    }

    ob->remove(1);

    if(ob)
    {
      destruct(ob);
    }
  }
}

private int ri_filter(<int|<string|string*>|object|mapping>* ritem, 
  string|string* file)
{
  object ob;
  
  ob=ritem[RITEM_OBJECT];
  
  if(stringp(file) && ritem[RITEM_FILE]==file)
  {
    ri_rem_ob(ob);
    return 0;
  }
  else if(pointerp(ritem[RITEM_FILE]) && pointerp(file) &&
          sizeof(file & ritem[RITEM_FILE])==sizeof(ritem[RITEM_FILE]))
  {
    ri_rem_ob(ob);
    return 0;
  }

  return 1;
}


public void RemoveItem(string|string* filename)
{
  < <int|<string|string*>|object|mapping>* >* items=QueryProp(P_ITEMS);

  if(!pointerp(items) || !sizeof(items))
  {
    return;
  }

  if(pointerp(filename))
  {
    foreach(string fn: &filename)
    {
      fn=master()->make_path_absolute(fn);
    }
  }
  else
  {
    filename=master()->make_path_absolute( filename );
  }
  
  SetProp(P_ITEMS,filter(items, #'ri_filter/*'*/,filename));
}

private mixed _do_refresh(mixed item)
{
  string file;
  object ob;

  if(!pointerp(item) || item[RITEM_REFRESH]==REFRESH_NONE)
  {
    return item;
  }

  if(pointerp(item[RITEM_FILE])) 
  {
    file=item[RITEM_FILE][random(sizeof(item[RITEM_FILE]))];
  }
  else
  {
    file=item[RITEM_FILE];
  }

  switch(item[RITEM_REFRESH])
  {
    case REFRESH_MOVE_HOME:
      if(objectp(item[RITEM_OBJECT]) &&
        environment(item[RITEM_OBJECT])!=ME)
      {
        item[RITEM_OBJECT]->move(ME,M_GO|M_NO_ATTACK);
        break;
      }
      
    // fall through
    case REFRESH_DESTRUCT:
      if(objectp(item[RITEM_OBJECT])) 
        break; // else FALL THROUGH
      
    case REFRESH_REMOVE:
      if(objectp(item[RITEM_OBJECT]) &&
        environment(item[RITEM_OBJECT])==ME)
        break; // else FALL THROUGH
      
    default:
      if(sizeof(item)>RITEM_PROPS && item[RITEM_PROPS]==1)
      {
        ob=load_object(file);
      }
      else
      {
        ob=clone_object(file);
      }

      ob->move(ME,M_NOCHECK|M_NO_ATTACK);
      break;
  }
  
  if(ob)
  {
    item[RITEM_OBJECT]=ob;
      
    if(sizeof(item)>RITEM_PROPS && mappingp(item[RITEM_PROPS]))
      walk_mapping(item[RITEM_PROPS],symbol_function("SetProp",ob));
  }
  
  return item;
}


// reset handling: check how the items should be refreshed.
void reset() 
{
  mixed *items;

  if(!pointerp(items=QueryProp(P_ITEMS)))
  {
    SetProp(P_ITEMS,({}));
    return;
  }
  
  SetProp(P_ITEMS,map(items,#'_do_refresh)-({0}));
}

