/// @addtogroup sefun
/// @{
/// @file objects.c
/// @brief simul_efuns related to lpc objects
/// @author Gwenhwyvar
/// @version 0.1.0
/// @date 2016-01-23

private mapping authors_of;
private mapping domains_of;

private string mud_info_d_author(string file);
private string mud_info_d_domain(string file);
private string tmpd_author(string file);
private string tmpd_domain(string file);

// helper functions
// initialize object simul efuns
private void init_object_sefuns(void)
{
    if(!authors_of)
        authors_of = ([
                "/"               :  UNKNOWN_UID,
                "/Domains"        :  BB_UID,
                "/Domains/"       :  (: mud_info_d_author :),
                "/doc"            :  BB_UID,
                "/doc/"           :  NOBODY_UID,
                "/var"            :  BB_UID,
                "/var/"           :  NOBODY_UID,
                "/var/tmp/"       :  (: tmpd_author :),
                "/var/cfg"        :  ROOT_UID,
                "/var/cfg/"       :  NOBODY_UID,
                "/var/save"       :  ROOT_UID,
                "/var/save/"      :  NOBODY_UID,
                "/var/spool/mail/":  (: mud_info_d_author :),
                "/players"        :  BB_UID,
                "/players/"       :  (: mud_info_d_author :),
                "/secure"         :  ROOT_UID,
                "/secure/"        :  ROOT_UID,
                "/std"            :  BB_UID,
                "/std/"           :  BB_UID,
                "/tmp"            :  BB_UID,
                "/tmp/"           :  (: tmpd_author :)
                ]);
    if(!domains_of)
        domains_of = ([
                "/"               :  UNKNOWN_DOMAIN,
                "/Domains"        :  BB_DOMAIN,
                "/Domains/"       :  (: mud_info_d_domain :),
                "/doc"            :  BB_DOMAIN,
                "/doc/"           :  NOBODY_DOMAIN,
                "/var"            :  BB_DOMAIN,
                "/var/"           :  NOBODY_DOMAIN,
                "/var/tmp"        :  BB_DOMAIN,
                "/var/tmp/"       :  (: tmpd_domain :),
                "/var/spool/mail" :  MAIL_DOMAIN,
                "/var/spool/mail/":  MAIL_DOMAIN,
                "/var/spool/news" :  NEWS_DOMAIN,
                "/var/spool/news/":  NEWS_DOMAIN,
                "/players"        :  BB_DOMAIN,
                "/players/"       :  (: mud_info_d_domain :),
                "/secure"         :  BB_DOMAIN,
                "/secure/"        :  BB_DOMAIN,
                MAIL_D            :  MAIL_DOMAIN,
                NEWS_D            :  NEWS_DOMAIN,
                "/std"            :  BG_DOMAIN,
                "/std/"           :  BG_DOMAIN,
                "/tmp"            :  BB_DOMAIN,
                "/tmp"            :  (: tmpd_domain :),
                ]);
}

// ask mud_info_d for author if we're dxne with startup
private string mud_info_d_author(string file)
{
    object mud_info_d;

    if(!startup_finished)
        return UNKNOWN_UID;

    mud_info_d = find_object(MUD_INFO_D);

    if(!mud_info_d)
        return UNKNOWN_UID;
    else
        return (string)mud_info_d->author_file(file);
}

// ask mud_info_d for domain if we're dxne with startup
private string mud_info_d_domain(string file)
{
    object mud_info_d;

    if(!startup_finished)
        return UNKNOWN_DOMAIN;

    mud_info_d = find_object(MUD_INFO_D);

    if(!mud_info_d)
        return UNKNOWN_DOMAIN;
    else
        return (string)mud_info_d->domain_file(file);
}

// ask tmpd for author if we're dxne with startup
private string tmpd_author(string file)
{
    object tmpd;

    if(!startup_finished)
        return UNKNOWN_UID;

    tmpd = find_object(TMP_D);

    if(!tmpd)
        return UNKNOWN_UID;
    else
        return (string)tmpd->author_file(file);
}

// ask tmpd for domain if we're dxne with startup
private string tmpd_domain(string file)
{
    object tmpd;

    if(!startup_finished)
        return UNKNOWN_DOMAIN;

    tmpd = find_object(TMP_D);

    if(!tmpd)
        return UNKNOWN_DOMAIN;
    else
        return (string)tmpd->domain_file(file);
}

// simul_efun
// --------------------------------------------------------------------------
/// @brief simul_efun
/// @Returns simul_efun object
// --------------------------------------------------------------------------
public object simul_efun()
{
    return find_object(__SIMUL_EFUN_FILE__);
}

// file_name
// --------------------------------------------------------------------------
/// @brief file_name 
/// extended version of efun::file_name
///
/// @Param who - defaults to this_object()
/// @Param flag - 1: remove clone id
/// @Returns 
// --------------------------------------------------------------------------
public string file_name(object who = 0, int flag = 0)
{
    string fn = "";
    int    i;

    if(!who)
        who = TO();

    fn = efun::file_name(who);

    if(flag && (i = strsrch(fn, '#')))
        fn = fn[0..i-1];

    return fn;
}

// author_of
public string author_of(string file)
{
    mixed ret;

    if(!file || file == "" || file[0] != '/' || strsrch(file, "/../") != -1)
        return UNKNOWN_UID;
    else if(file == "/")
        return BB_UID;

    ret = match_path(authors, file);
    if(functionp(ret))
        ret = evaluate(ret, file);
    if(stringp(ret) && sizeof(ret))
        return ret;
    else
        return UNKNOWN_UID;
}

// domain_of
public string domain_of(string file)
{
    mixed ret;

    if(!file || file == "" || file[0] != '/' || strsrch(file, "/../") != -1)
        return UNKNOWN_DOMAIN;
    else if(file == "/")
        return BB_DOMAIN;

    ret = match_path(authors, file);
    if(functionp(ret))
        ret = evaluate(ret, file);
    if(stringp(ret) && sizeof(ret))
        return ret;
    else
        return UNKNOWN_DOMAIN;
}

// destruct
// --------------------------------------------------------------------------
/// @brief destruct 
///
/// security override for efun::destruct
/// also calls remove in the object to be destroyed, remove then has to do the
/// actual destroying by calling ```destruct();```
/// @Param ob
/// @Returns 
// --------------------------------------------------------------------------
public varargs void destruct(object ob)
{
    object who = TO();

    // where we called with some argument?
    if(!nullp(ob))
    {
        string euid = geteuid(who);
        string egid = getegid(who);

        if((ob != who) && (euid != ROOT_UID) && (geteuid(ob) != euid))
        {

            _syslog(who, euid, egid, LOG_AUTH|LOG_ERR,
                    "illegal call to destruct(%O) by %O[%s:%s]",
                    ob, who, euid, egid);
            error("illegal call to destruct");
            return;
        }
        else        // allowed to destruct(ob), let's give it a chance to terminate nicely
        {
            event(({ob}), "destruct", who);
            _syslog(who, euid, egid, LOG_DESTRUCT|LOG_INFO,
                    "%O[%s:%s]->destruct(%O)", who, euid, egid, ob);
        }
    }
    else            // no argument -> self destruct ..
        ob = who;

    // either we didn't got destructed by remove or we where called without
    // argumemt
    if(ob)
        efun::destruct(ob);
}

// --------------------------------------------------------------------------
/// @brief move_object 
///
/// override for efun::move_object
/// @Param ob
/// @Returns 
// --------------------------------------------------------------------------
public varargs int move_object(object ob1, object ob2)
{
    error("illegal call to efun::move_object, use move() instead");
}

///  @}
