#pragma strong_types,rtt_checks

#include <moving.h>
#include <properties.h>
#include <container/vitems.h>

// Einschraenkungen: Alle _query_* Querymethoden und _set_* Setmethoden im
// Ziel werden nicht beschattet.


// Alle nicht explizit zum oeffentlichen Interface von /std/container
// gehoerenden (d.h. alle nicht explizit "public" definierten) Funktionen
// werden protected geerbt. Damit koennen sie von aussen nicht gerufen werden
// und der Effekt ist, dass sie nicht im Shadow gerufen werden, sondern im
// beschatteten Objekt.
protected functions nosave private variables inherit "/std/container";

// Mapping ohne Values. Keys zeigen an, welche Props dieses Objekt im
// Zielobjekt beschattet.
mapping props;

object cloner;

protected void create()
{
  cloner=previous_object();
  set_next_reset(7200);
}

// Einige spezielle Props (wie Details etc. und Props mit Arrays oder
// Mappings) werden gemerged mit dem Ziel, alle anderen ueberschrieben.
private void configure_object(object ziel, mapping newprops)
{
  props = ([:0]);
  foreach (string k, mixed v : newprops)
  {
    int reset_prop;
    if (k[0] == VI_RESET_PREFIX)
    {
      reset_prop=1;
      k=k[1..];
    }
    switch(k)
    {
      case P_READ_DETAILS:
        if (reset_prop)
          RemoveReadDetail(0);
        else
          SetProp(P_READ_DETAILS, ziel->QueryProp(P_READ_DETAILS));
        walk_mapping(v, #'AddReadDetail);
        break;
      case P_DETAILS:
        if (reset_prop)
          RemoveDetail(0);
        else
          SetProp(P_DETAILS, ziel->QueryProp(P_DETAILS));
        walk_mapping(v, #'AddDetail);
        break;
      case P_SMELLS:
        if (reset_prop)
          RemoveSmells(0);
        else
          SetProp(P_SMELLS, ziel->QueryProp(P_SMELLS));
        walk_mapping(v, #'AddSmells);
        break;
      case P_SOUNDS:
        if (reset_prop)
          RemoveSounds(0);
        else
          SetProp(P_SOUNDS, ziel->QueryProp(P_SOUNDS));
        walk_mapping(v, #'AddSounds);
        break;
      case P_TOUCH_DETAILS:
        if (reset_prop)
          RemoveTouchDetail(0);
        else
          SetProp(P_TOUCH_DETAILS, ziel->QueryProp(P_TOUCH_DETAILS));
        walk_mapping(v, #'AddTouchDetail);
        break;
      case P_IDS:
        if (reset_prop)
          SetProp(P_IDS, v);
        else
        {
          SetProp(P_IDS, ziel->QueryProp(P_IDS));
          AddId(v);
        }
      case P_CLASS:
        if (reset_prop)
          SetProp(P_CLASS, v);
        else
        {
          SetProp(P_CLASS, ziel->QueryProp(P_CLASS));
          AddClass(v);
        }
      case P_ADJECTIVES:
        if (reset_prop)
          SetProp(P_ADJECTIVES, v);
        else
        {
          SetProp(P_ADJECTIVES, ziel->QueryProp(P_ADJECTIVES));
          AddAdjective(v);
        }
        break;

      // Alle anderen Properties stumpf setzen.
      default:
        if (reset_prop)
          SetProp(k, v);
        else
        {
          mixed val = ziel->QueryProp(k);
          // Arrays und Mapping koennen addiert werden, alles andere wird
          // ueberschrieben.
          if (pointerp(val) || mappingp(val))
            SetProp(k, val + v);
          else
            SetProp(k, v);
        }
     } // switch
  } // foreach
}

/*
xcall 
/players/zesstra/vitem_shadow->set_shadow(find_object("/players/zesstra/seil#55513
2"),([P_MATERIAL:([MAT_ICE:100]),P_SHORT:"Eis-Seil"]))
*/
public void set_shadow(object target, mapping p)
{
  // wenn schon beschattend, ists nen Fehler
  if (query_shadowing(this_object()))
      raise_error(sprintf("set_shadow(): Ein Objekt wird schon beschattet: "
            "%O (Ziel jetzt: %O)\n",query_shadowing(this_object()), target));

  // der Aufrufer muss eine eUID gleich meiner UID haben, damit er das
  // Beschatten aktivieren kann. (Dieses Objekt hat immer die UID+eUID == eUID
  // vom Cloner des Shadows, d.h. vom Erzeuger des vItems.) D.h. das
  // Beschatten kann vom Erzeuger des vItems aktiviert werden.
  if (getuid(this_object()) == geteuid(previous_object()))
  {
    configure_object(target, p);
    if (shadow(target, 1) != target)
      raise_error(sprintf("Kann %O nicht beschatten.\n",target));
  }
  else
    raise_error(sprintf("Kann %O nicht beschatten, falsche eUID. "
                        "Meine: %s, Aufrufer: %s\n",
                        target, getuid(this_object()),
                        geteuid(previous_object()) ));
}


varargs int remove(int silent)
{
  // Sollten wir gerade etwas beschatten, ist der Aufruf von diesem remove()
  // evtl. auch der vom Ziel. Wir machen das ganz einfach: Aufruf von remove()
  // fuehrt zum Entsorgen von Ziel und diesem Objekt.
  object ziel=query_shadowing(this_object());
  // und ganz wichtig: nur wenn das Ziel noch ein virtuell anwesendes Items
  // (vitem) ist, d.h. *kein* Environment hat.
  if (ziel && !environment(ziel))
    ziel->remove(1);

  return ::remove(1);
}

// Dieses Objekt raeumt sich immer im ersten reset auf - es ist kurzlebig und
// transient und Aenderungen an seinen Daten bleiben nicht erhalten.
void reset()
{
  // BTW: Sollten wir gerade etwas beschatten, ist der Aufruf von diesem
  // reset() evtl. auch der vom Ziel. (remove kuemmer sich drum)
  remove(1);
}

// private ueberschreiben, damit es in diesem Objekt nicht gerufen werden kann
// und im Beschatteten gerufen wird.
private varargs void init(object origin)
{
}

public varargs int move( object|string dest, int method )
{
  object ziel=query_shadowing(this_object());
  int res;
  if (ziel)
  {
    // PreventMove() im Ziel fragt die Props P_NOGET, P_WEIGHT etc. nicht via
    // Callother ab, daher wird die Abfrage nicht durch diesen Shadow
    // geleitet. Daher muss hier selber geprueft werden. Das PreventMove() in
    // diesem Objekt beruecksichtigt die Properties des Schatten und des
    // Beschatteten.
    // Bemerkung: das bedeutet, dass PreventInsert() auch zweimal gerufen
    // wird, fuer den Shadow und das Ziel. Deswegen darf man auch *nicht* per
    // M_NOCHECK bewegen, weil die PreventInsert() fuer den Beschatteten ja
    // noch ablehnend sein koennen.
    dest = move_norm_dest(dest);
    res = PreventMove(dest, 0, method);
    if (res)
    {
      // auf gueltigen Fehler pruefen, wer weiss, was Magier da evtl.
      // versehentlich zurueckgeben.
      if (VALID_MOVE_ERROR(res))
        return res;
      else
        return ME_DONT_WANT_TO_BE_MOVED;
    }
    res = ziel->move(dest, method);
    if (res == MOVE_OK)
    {
      // virtuellem environment bescheidsagen, dass das Objekt bewegt wurde.
      cloner->VItemMoved(ziel);
      // und nach Bewegung des vitems ist das kein vitem mehr und der Schatten
      // muss weg.
      remove(1);
    }
  }
  // Bewegen vom Schatten ist nicht. Und ohne Ziel braucht es den Schatten eh
  // nicht.
  else
  {
    remove(1);
    res = ME_WAS_DESTRUCTED;
  }
  return res;
}

// Query und QueryProp liefern die abweichend hier definierten Properties,
// oder ansonsten die aus dem beschatteten Objekt.
public mixed QueryProp( string name )
{
  object ziel=query_shadowing(this_object());
  if (ziel && !member(props,name))
  {
    return ziel->QueryProp(name);
  }
  return ::QueryProp(name);
}

public varargs mixed Query( string name, int Type )
{
  object ziel=query_shadowing(this_object());
  if (ziel && !member(props,name))
  {
    return ziel->Query(name, Type);
  }
  return ::Query(name, Type);
}

public varargs mixed Set( string name, mixed Value, int Type, int extern )
{
  // Ab jetzt ist das unsere Prop, die aus dem Beschatteten ist egal.
  m_add(props,name);
  return ::Set(name, Value, Type, extern_call());
}

public mixed SetProp( string name, mixed Value )
{
  // Ab jetzt ist das unsere Prop, die aus dem Beschatteten ist egal.
  m_add(props,name);
  return ::SetProp(name, Value);
}

// Details hinzufuegen muss die passende Prop so markieren, dass sie aus
// diesem Objekt geliefert wird.
public void AddDetail(string|string* keys, string|string*|mapping|closure descr)
{
  // Ab jetzt ist das unsere Prop, die aus dem Beschatteten ist egal.
  m_add(props,P_DETAILS);
  m_add(props,P_SPECIAL_DETAILS);
  return ::AddDetail(keys, descr);
}

public void AddReadDetail(string|string* keys,
                   string|string*|mapping|closure descr )
{
  // Ab jetzt ist das unsere Prop, die aus dem Beschatteten ist egal.
  m_add(props,P_READ_DETAILS);
  return ::AddReadDetail(keys, descr);
}

public void AddSounds(string|string* keys,
               string|string*|mapping|closure descr )
{
  // Ab jetzt ist das unsere Prop, die aus dem Beschatteten ist egal.
  m_add(props,P_SOUNDS);
  return ::AddSounds(keys, descr);
}

public void AddSmells(string|string* keys,
               string|string*|mapping|closure descr )
{
  // Ab jetzt ist das unsere Prop, die aus dem Beschatteten ist egal.
  m_add(props,P_SMELLS);
  return ::AddSmells(keys, descr);
}

public void AddTouchDetail(string|string* keys,
                    string|string*|mapping|closure descr )
{
  // Ab jetzt ist das unsere Prop, die aus dem Beschatteten ist egal.
  m_add(props,P_TOUCH_DETAILS);
  return ::AddTouchDetail(keys, descr);
}

// Beides nicht unterstuetzt fuer vitems.
visible void AddSpecialDetail(string|string* keys, string functionname )
{
  raise_error("Nicht unterstuetzt fuer vitem-shadows.\n");
}
visible void RemoveSpecialDetail(string|string* keys )
{
  raise_error("Nicht unterstuetzt fuer vitem-shadows.\n");
}

// Wird ggf. auf GetDetail im echten Item umgeleitet, damit jenes FP an
// Details haben kann und man diese auch findet.
public varargs string GetDetail(string key, string race, int sense)
{
  object ziel=query_shadowing(this_object());
  if (!ziel)
    return ::GetDetail(key, race, sense);

  switch(sense)
  {
    case SENSE_SMELL: if (member(props, P_SMELLS))
                          return ::GetDetail(key, race, sense);
                      break;
    case SENSE_SOUND: if (member(props, P_SOUNDS))
                          return ::GetDetail(key, race, sense);
                      break;
    case SENSE_TOUCH: if (member(props, P_TOUCH_DETAILS))
                          return ::GetDetail(key, race, sense);
                      break;
    case SENSE_READ:  if (member(props, P_READ_DETAILS))
                          return ::GetDetail(key, race, sense);
                      break;

    default:          if (member(props, P_DETAILS))
                          return ::GetDetail(key, race, sense);
                      break;
  }
  // nix in diesem Objekt, GetDetail vom ziel darfs machen.
  return ziel->GetDetail(key, race, sense);
}

// Sollen aus dem Beschatteten kommen
public object *present_objects( string complex_desc )
{
  object ziel=query_shadowing(this_object());
  if (ziel)
    return ziel->present_objects(complex_desc);
  return ::present_objects(complex_desc);
}

// Sollen aus dem Beschatteten kommen
public object *locate_objects( string complex_desc, int info )
{
  object ziel=query_shadowing(this_object());
  if (ziel)
    return ziel->locate_objects(complex_desc, info);
  return ::locate_objects(complex_desc, info);
}

public object *AllVirtualEnvironments()
{
  if (cloner)
  {
    object *cloner_envs = all_environment(cloner)
                          || cloner->AllVirtualEnvironments();
    if (cloner_envs)
      return ({cloner}) + cloner_envs;
    return ({cloner});
  }
  return 0;
}

