/* Do not remove the headers from this file! see /USAGE for more info. */

/*
** mailbox.c -- a mailbox to hold message references
**
** 950701, Deathblade: Created.
*/

#include <mudlib.h>
#include <security.h>
#include <classes.h>
#include <flags.h>

inherit M_ACCESS;

inherit CLASS_MAILMSG;

/*
** mailbox: maps message keys to flags
*/
private mapping mailbox = ([ ]);

/*
** Flags for the mail
*/
#define F_UNREAD	1
//### code assumes zero/non-zero; fix if more flags are added

/*
** Who is this mailbox for?
*/
private nosave string owner;

/*
** What is the current message index.  This value is 0-based and represents
** a message index for messages from the user's perspective.  The value 1
** corresponds to the first key in the (ordered) set of message keys in the
** mailbox.
*/
private nosave int message_index = 0;


private nomask string get_fname()
{
    return sprintf("/data/mail/mbox/%c/%s", owner[0], owner);
}

nomask void create(string the_owner)
{
    if ( !clonep() )
	return;

    if ( file_name(previous_object()) != MAILBOX_D )
	error("*Security violation: invalid creation");

    owner = the_owner;
    unguarded(1, (: restore_object, get_fname(), 1 :));
}
private nomask void save_me()
{
    unguarded(1, (: save_object, get_fname() :));
}
nomask void remove()
{
    destruct();
}

nomask string query_owner()
{
    return owner;
}

nomask class mail_msg get_one_message(int message_key)
{
    class mail_msg msg;

//### need some work on ensuring the call stack is correct
//    if ( !check_privilege(owner) )
    if ( this_user()->query_userid() != owner )
	error("security violation: you are not allowed to use this mailbox\n");

    if ( undefinedp(mailbox[message_key]) )
	return 0;

    msg = MAIL_D->get_one_message(message_key);
    if ( !msg )
    {
	/* damn. bad message. remove it from the mailbox. */
	map_delete(mailbox, message_key);
	save_me();
    }

    return msg;
}

nomask int query_message_index()
{
    return message_index;
}
nomask void set_message_index(int new_message_index)
{
    message_index = new_message_index;
}

nomask int * query_message_keys()
{
    return sort_array(keys(mailbox), 1);
}
nomask int query_message_count()
{
    return sizeof(mailbox);
}

nomask int query_message_read(int message_key)
{
    return mailbox[message_key];
}
nomask void set_message_read(int message_key)
{
    if ( mailbox[message_key] )
    {
	mailbox[message_key] = 0;
	save_me();
    }
}
nomask int query_unread_count()
{
    return implode(values(mailbox), (: $1 + $2 :));
}
nomask int first_unread_message()
{
    int * message_keys = query_message_keys();
    int message_key;
    int message_index;

    foreach ( message_key in message_keys )
    {
	if ( mailbox[message_key] )
	    return message_index;

	++message_index;
    }

    return -1;
}

nomask void delete_message(int message_key)
{
//### need some work on ensuring the call stack is correct
//    if ( !check_privilege(owner) )
    if ( this_user()->query_userid() != owner )
	error("security violation: you are not allowed to read this mail\n");

    if ( undefinedp(mailbox[message_key]) )
	error("non-existent message\n");

    MAIL_D->delete_mail(message_key, owner);
    if( query_unread_count() <= message_index ) message_index--;
    map_delete(mailbox, message_key);

    save_me();
}

nomask void nuke_mailbox()
{
    if ( !check_previous_privilege(1) )
	error("security violation: illegal nuke of mailbox\n");

    foreach ( int message_key in keys(mailbox) )
	MAIL_D->delete_mail(message_key, owner);

    mailbox = ([ ]);
    unguarded(1, (: rm, get_fname() + __SAVE_EXTENSION__ :));
}

//### temp functions?  wait and see

nomask void receive_new_message(int message_key)
{
    object user;

//    if( previous_object() != find_object( MAIL_D ) )
//	return;

    mailbox[message_key] = F_UNREAD;
    save_me();

    if ( (user = find_user(owner)) &&
	 user->query_body()->test_flag(F_BIFF) )
	tell(user, ">>You have new mail<<\n");
}
