// 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
#pragma pedantic

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

