// 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}));
}

