// jboard.c

#include <ansi.h>

inherit ITEM;
inherit F_SAVE;

void setup()
{
	string loc;

	if( stringp(loc = query("location")) )
		move(loc);
	set("no_get", 1);
	restore();
}

void init()
{
	add_action("do_project", "project");
	add_action("do_report", "report");
	add_action("do_read", "read");
	add_action("do_terminate", "terminate");
}

string query_save_file()
{
	string id;

	if( !stringp(id = query("board_id")) ) return 0;
	return DATA_DIR + "board/" + id;
}

string short()
{
	mapping *notes;
	int i, unread, last_read_time;

	notes = query("notes");
	if( !pointerp(notes) || !sizeof(notes) )
		return ::short() + " [ 没有任何工作计画 ]";

	if( this_player() ) {
		last_read_time = (int)this_player()->query("board_last_read/" + (string)query("board_id"));
		for(unread = 0, i=sizeof(notes)-1; i>=0; i--, unread ++)
			if( notes[i]["time"] <= last_read_time ) break;
	}
	if( unread )
		return sprintf("%s [ %d 个工作计画，%d 份新进度报告 ]", ::short(), sizeof(notes), unread);
	else
		return sprintf("%s [ %d 个工作计画 ]", ::short(), sizeof(notes));
}

string long()
{
	mapping *notes;
	int i, j, last_time_read, new_report;
	string msg, myid;

	notes = query("notes");
	if( !pointerp(notes) || !sizeof(notes) ) return query("long");

	msg = query("long");
	last_time_read = this_player()->query("board_last_read/" + (string)query("board_id"));
	for(i=0; i<sizeof(notes); i++) {
		new_report = 0;
		if( arrayp(notes[i]["report"]) ) {
			j = sizeof(notes[i]["report"]);
			while(j--)
				if( notes[i]["report"][j]["time"] <= last_time_read ) break;
			new_report = sizeof(notes[i]["report"]) - j - 1;
		}
		msg += sprintf("%s[%2d]" NOR "  %=30s %12s %+3d (%s)\n",
			( notes[i]["time"] > last_time_read ? HIY: ""),
			i+1, notes[i]["title"], notes[i]["author"], new_report,
			ctime(notes[i]["time"])[0..15] );
	}
	return msg;
}

// This is the callback function to process the string returned from the
// editor defined in F_EDIT of player object.
void done_describe_project(object me, mapping note, string text)
{
	mapping *notes;

	note["msg"] = text;
	notes = query("notes");
	if( !pointerp(notes) || !sizeof(notes) )
		notes = ({ note });
	else
		notes += ({ note });

	set("notes", notes);
	tell_object(me, "新工作计画提出。\n");

	save();
	return;
}

// This is the callback function to process the string returned from the
// editor defined in F_EDIT of player object.
void done_report(object me, mapping report, int project, string text)
{
	mapping *notes, *reports;

	report["msg"] = text;
	notes = query("notes");
	reports = notes[project]["report"];
	if( !arrayp(reports) )	reports = ({ report });
	else					reports += ({ report });

	notes[project]["report"] = reports;
	notes[project]["time"] = time();

	set("notes", notes);
	tell_object(me, "进度报告完毕。\n");

	save();
	return;
}

int do_project(string arg)
{
	mapping note;

	if(!arg) return notify_fail("工作计画请指定一个标题。\n");
	
	note = allocate_mapping(5);
	note["title"] = arg;
	note["owner"] = this_player()->query("id");
	note["author"] = this_player()->name(1);
	note["time"] = time();
	this_player()->edit( (: done_describe_project, this_player(), note :) );
	return 1;
}

int do_report(string arg)
{
	int num;
	string title;
	mapping note, *notes;

	if(!arg || sscanf(arg, "%d %s", num, title)!=2 )
		return notify_fail("指令格式：report <计画编号> <进度报告标题>\n");

	notes = query("notes");
	if( !arrayp(notes) || num < 1 || num > sizeof(notes) )
		return notify_fail("没有这个工作计画。\n");

	note = allocate_mapping(5);
	note["title"] = arg;
	note["owner"] = this_player()->query("id");
	note["author"] = this_player()->name(1);
	note["time"] = time();
	this_player()->edit( (: done_report, this_player(), note, num-1 :) );
	return 1;
}

int do_read(string arg)
{
	int num, rep, last_read_time;
	mapping *notes;
	string myid;

	last_read_time = this_player()->query("board_last_read/" + query("board_id"));
	myid	= query("board_id");
	notes	= query("notes");

	if( !pointerp(notes) || !sizeof(notes) )
		return notify_fail("进度表上目前没有任何计画。\n");

	if( !arg ) return notify_fail("指令格式：read <计画编号>[.<报告编号>]|new|next\n");
	if( arg=="new" || arg=="next" ) {
		for(num = 1; num<=sizeof(notes); num++)
			if( notes[num-1]["time"] > last_read_time ) break;
	} else if( sscanf(arg, "%d.%d", num, rep)==2 ) {
		if( num < 1 || num > sizeof(notes) ) return notify_fail("没有这个计画。\n");
		else num--;
		if( rep < 1 || rep > sizeof(notes[num]["report"]) )	return notify_fail("没有这个进度报告。\n");
		else rep --;
		this_player()->start_more( sprintf(
"[%d.%d] %s: %s\n-------------------------------------------------------------------\n"
"%s\n-------------------------------------------------------------------\n%s\t\t%s(%s)\n",
			num + 1, rep + 1,
			notes[num]["title"],
			notes[num]["report"][rep]["title"],
			notes[num]["report"][rep]["msg"],
			ctime(notes[num]["report"][rep]["time"]),
			notes[num]["report"][rep]["author"],
			notes[num]["report"][rep]["owner"] ) );

		if( notes[num]["time"] > last_read_time )
			this_player()->set("board_last_read/" + query("board_id"),
				notes[num]["time"]);

		return 1;
	} if( !sscanf(arg, "%d", num) )
		return notify_fail("你要读第几个计画的简报？\n");

	if( num < 1 || num > sizeof(notes) )
		return notify_fail("没有这个计画。\n");
	num--;
	this_player()->start_more( sprintf(
"[%2d]\t%s\n负责人：%s(%s) : %s\n----------------------------------------------------------------------\n%s"
"----------------------------------------------------------------------\n进度报告：%d 份。\n",
		num + 1,
		notes[num]["title"],
		notes[num]["author"], notes[num]["owner"],
		ctime(notes[num]["time"])[0..9],
		notes[num]["msg"],
		sizeof(notes[num]["report"]) ) );

	// Keep track which post we were reading last time.
	if( notes[num]["time"] > last_read_time )
		this_player()->set("board_last_read/" + query("board_id"),
			notes[num]["time"]);

	return 1;
}


int do_terminate(string arg)
{
	mapping *notes;
	int num;

	if( !arg || sscanf(arg, "%d", num)!=1 )
		return notify_fail("指令格式：discard <留言编号>\n");
	notes = query("notes");
	if( !arrayp(notes) || num < 1 || num > sizeof(notes) )
		return notify_fail("没有这张留言。\n");
	num--;
	if( notes[num]["owner"] != (string)this_player(1)->query("id")
	&&	(string)SECURITY_D->get_status(this_player(1)) != "(admin)" )
		return notify_fail("这个留言不是你写的。\n");

	notes = notes[0..num-1] + notes[num+1..sizeof(notes)-1];
	set("notes", notes);
	save();
	write("删除第 " + (num+1) + " 号留言....Ok。\n");
	return 1;
}
