// MorgenGrauen MUDlib
//
// room/description.c -- room description handling
//
// $Id: description.c 9468 2016-02-19 21:07:04Z Gloinson $

#pragma strong_types
#pragma save_types
#pragma pedantic
#pragma range_check
#pragma no_clone

inherit "/std/container/description";

#define NEED_PROTOTYPES

#include <properties.h>
#include <defines.h>
#include <wizlevels.h>
#include <language.h>
#include <doorroom.h>

void create()
{
  ::create();
  SetProp(P_NAME, "Raum");
  SetProp(P_INT_SHORT,"<namenloser Raum>");
  SetProp(P_INT_LONG,0);
  SetProp(P_ROOM_MSG, ({}) );
  SetProp(P_FUNC_MSG, 0);
  SetProp(P_MSG_PROB, 30);
  AddId(({"raum", "hier"}));
}

void init()
{
  // Wenn P_ROOM_MSG gesetzt oder P_FUNC_MSG und kein Callout laeuft,
  // Callout starten.
  mixed roommsg = QueryProp(P_ROOM_MSG);
  if( ( (roommsg && sizeof(roommsg)) ||
        QueryProp(P_FUNC_MSG) ) &&
      (find_call_out("WriteRoomMessage")==-1))
    call_out("WriteRoomMessage", random(QueryProp(P_MSG_PROB)));
}

varargs void AddRoomMessage(string *mesg, int prob, mixed func)
{
  if (mesg && !pointerp(mesg))
    raise_error(sprintf(
      "AddRoomMessage(): wrong argument type, expected Array or 0, "
      "got %.20O",mesg));

   SetProp(P_ROOM_MSG, mesg);

  if (prob>0)
    SetProp(P_MSG_PROB, prob);

  if (func)
    SetProp(P_FUNC_MSG, func);
}

static void WriteRoomMessage()
{
  int tim, msgid;
  string *room_msg,func;
  mixed *func_msg;

  room_msg = (string *)QueryProp(P_ROOM_MSG);
  func_msg = QueryProp(P_FUNC_MSG);
  if ((!room_msg || !sizeof(room_msg)) && !func_msg)
    return;

  if (room_msg&&sizeof(room_msg))
  {
    msgid = random(sizeof(room_msg));
    // Defaultwerte sind fuer Altcode schwierig
    send_room(this_object(), room_msg[msgid],
              MT_LOOK|MT_LISTEN|MT_FEEL|MT_SMELL|
              MSG_DONT_STORE|MSG_DONT_BUFFER|MSG_DONT_WRAP);
  }

  if (func_msg)
  {
    if (stringp(func_msg))
      func=(string)func_msg;
    else
      func=func_msg[random(sizeof(func_msg))];
    if (func && function_exists(func))
      call_other (this_object(), func, msgid);
  }

  while (remove_call_out("WriteRoomMessage")!=-1);
  tim=QueryProp(P_MSG_PROB);
  if(this_object() && sizeof(filter(
       deep_inventory(this_object()), #'interactive))) //')))
    call_out("WriteRoomMessage", (tim<15 ? 15 : tim));
}

varargs string int_long(mixed viewer,mixed viewpoint,int flags)
{
  string descr, inv_descr;

  flags &= 3;
  if( IS_LEARNER(viewer) && viewer->QueryProp( P_WANTS_TO_LEARN ) )
    descr = "[" + object_name(ME) + "]\n";
  else
    descr = "";

  descr += process_string(QueryProp(P_INT_LONG)||"");
  
  // ggf. Tueren hinzufuegen.
  if (QueryProp(P_DOOR_INFOS)) {
    string tmp=((string)call_other(DOOR_MASTER,"look_doors"));
    if (stringp(tmp) && sizeof(tmp))
        descr += tmp;
  }
  
  // ggf. Ausgaenge hinzufuegen.
  if ( viewer->QueryProp(P_SHOW_EXITS) && (!QueryProp(P_HIDE_EXITS) 
	|| pointerp(QueryProp(P_HIDE_EXITS))) )
    descr += GetExits(viewer) || "";

  // Viewpoint (Objekt oder Objektarray) sind nicht sichtbar
  inv_descr = (string) make_invlist(viewer, all_inventory(ME) 
		  - (pointerp(viewpoint)?viewpoint:({viewpoint})) ,flags);

  if ( inv_descr != "" )
    descr += inv_descr;

  if(environment() && (inv_descr=QueryProp(P_TRANSPARENT)))
  {
    if(stringp(inv_descr)) descr += inv_descr;
    else                   descr += "Ausserhalb siehst Du:\n";
            
    descr += environment()->int_short(viewer,ME);
  }
                  
  return descr;
}

string int_short(mixed viewer,mixed viewpoint)
{
  string descr, inv_descr;

  descr = process_string( QueryProp(P_INT_SHORT)||"");

  // Ist das letzte Zeichen kein Satzzeichen einen Punkt anhaengen, sonst nur
  // den \n.
  int i=descr[<1];
  if(i!='.' && i!='!' && i!='?')
    descr+=".\n";
  else
    descr+="\n";

  // Aber ggf. den Pfad fuer Magier vor dem \n einfuegen.
  if(IS_LEARNING(viewer))
    descr[<1..<2]=" [" + object_name(ME) + "]";

  if ( ( viewer->QueryProp(P_SHOW_EXITS)
         || ( environment(viewer) == ME && !viewer->QueryProp(P_BRIEF) ) )
       && (!QueryProp(P_HIDE_EXITS) || pointerp(QueryProp(P_HIDE_EXITS))) )
    descr += GetExits(viewer) || "";

  // Viewpoint (Objekt oder Objektarray) sind nicht sichtbar
  inv_descr = (string) make_invlist( viewer, all_inventory(ME) 
		  - (pointerp(viewpoint)?viewpoint:({viewpoint})) );

  if ( inv_descr != "" )
    descr += inv_descr;

  return descr;
}

/** Roommessages abschalten, wenn keine Interactives mehr da sind.
  */
// TODO: Irgendwann das varargs loswerden, wenn in der restlichen Mudlib
// TODO::exit() 'richtig' ueberschrieben wird.
varargs void exit(object liv, object dest) {
  // fall erbende Objekte das liv nicht uebergeben. Pruefung nur auf
  // previous_object(). Wenn Magier da noch irgendwelche Spielchen mit
  // call_other() & Co treiben, haben wir Pech gehabt, macht aber nicht viel,
  // weil die Raummeldungen dann im naechsten callout abgeschaltet werden.
  if (!living(liv=previous_object())) return;

  object *interactives = filter(all_inventory(), #'interactive);
  // liv wurde noch nicht bewegt, ggf. beruecksichtigen.
  if ( !sizeof(interactives) ||
      (interactive(liv) && sizeof(interactives) < 2) )
    while (remove_call_out("WriteRoomMessage")!=-1);
}

static string _query_int_long() {return Query(P_INT_LONG, F_VALUE);}


// Querymethode fuer P_DOMAIN - gibt die Region an, in der Raum liegt, sofern
// er unter /d/ liegt...
static string _query_lib_p_domain()
{
  string fn = object_name();
  if (strstr(fn, "/d/") == 0)
  {
    return capitalize(explode(fn, "/")[2]);
  }

  return "unbekannt";
}

<string|string*>* _set_harbour_name( <string|string*>* desc) 
{
  if ( sizeof(desc)!=2 )
  {
    raise_error(sprintf("Unacceptable data in P_HARBOUR, sizeof() was %d, "
      "expected 2.", sizeof(desc)));
  }
  else if ( !stringp(desc[0]) )
  {
    raise_error("Wrong data type in P_HARBOUR[0]: expected 'string'.");
  }
  else if ( pointerp(desc[1]) && sizeof(desc[1])<1 )
  {
    raise_error("Insufficient data in P_HARBOUR[1]: expected 'string*', "
      "got '({})'.");
  }
  else if ( stringp(desc[1]) )
  {
    desc[1] = ({desc[1]});
  }
  return Set(P_HARBOUR, desc, F_VALUE);
}

