// --------------------------------------------------------------------------
// Citadel: NetMsgO.CPP
//
// How to write messages out to the network

#include "ctdl.h"
#pragma hdrstop

#include "room.h"
#include "auxtab.h"
#include "log.h"
#include "net.h"
#include "msg.h"
#include "filerdwr.h"
#include "events.h"


// --------------------------------------------------------------------------
// Contents
//
// getdupeMessage() 	reads a message off disk into RAM, lim fields
// netPutMessage()		Puts a message to a file
// NewRoom()			Puts all new messages in a room to a file
// saveMessage()		saves a message to file if it is netable
// ReadMsgFile()		Reads a message file into thisRoom


static Message *LoadAndTestIfShouldSaveMessage(ulong id);


// --------------------------------------------------------------------------
// NewRoom(): Puts all new messages in a room to a file.
//
// filename = "name" for old netting or NULL for 6.9
// file = msg.69 for 6.9 or NULL for old netting

int NewRoom(int room, const char *filename, FILE *file)
	{
	int read = TI()MS.Read;
	Bool first = TRUE;

	m_slot i, slot;

	int h;

	ulong lowLim = TI()CurrentUser->GetRoomNewPointer(room) + 1;
	const ulong highLim = cfg.newest;

	TI()CurrentUser->SetRoomNewPointer(room, cfg.newest);

	// stuff may have scrolled off system unseen, so...
	if (cfg.oldest > lowLim)
		{
		lowLim = cfg.oldest;
		}

	if (file == NULL)
		{
		char FileName[100];

		sprintf(FileName, sbs, cfg.temppath, filename);

		if ((file = fopen(FileName, FO_AB)) == NULL)
			{
			return (0);
			}
		}

	// In 66 (perhaps 67?) this can go away. (By that time, all non-local
	// from #NODENAME messages will have scrolled.)
	h = hash(cfg.nodeTitle);

	m_slot size_table = sizetable();

	for (i = 0; i != size_table; i++, slot = i)
		{
		ulong msgNo = (ulong) (cfg.mtoldest + slot);

		if (msgNo >= lowLim && highLim >= msgNo)
			{
#ifdef AUXMEM
			messagetable *lmt = getMsgTab(slot);
#endif
			// skip messages not in this room
			if (getRoomNumLMT(slot) != room)
				{
				continue;
				}

			// seek out original message table entry
			Bool scrolled = FALSE;

			while (getFlagsLMT(slot)->IsCopy())
				{
				// copy has scrolled?
				if (getCopyLMT(slot) > (m_slot) slot)
					{
					scrolled = TRUE;
					break;
					}
				else	// look at original message index
					{
					assert(getCopyLMT(slot) != 0);
					slot = slot - getCopyLMT(slot);
#ifdef AUXMEM
					lmt = getMsgTab(slot);
#endif
					}
				}

			if (scrolled)
				{
				continue;
				}

			// no open messages from the system
			// This goes away in 66: see note above.
			if (getAuthHashLMT(slot) == h)
				{
				continue;
				}

			// skip mail
			if (getFlagsLMT(slot)->IsMail())
				{
				continue;
				}

			// skip mass e-mail
			if (getFlagsLMT(slot)->IsMassemail())
				{
				continue;
				}

			// No problem user shit
			if (
					(
					getFlagsLMT(slot)->IsProblem() ||
					getFlagsLMT(slot)->IsModerated()
					)

				&&
					!getFlagsLMT(slot)->IsMadevis()
				)
				{
				continue;
				}

			// skip Local messages
			if (getFlagsLMT(i)->IsLocal())
				{
				continue;
				}

			Message *Msg = LoadAndTestIfShouldSaveMessage(msgNo);
			if (Msg)
				{
				PrepareMsgScriptInit(Msg);
				doEvent(EVT_STORENETMESSAGE, InitMsgScript);

				if (CheckMsgScript(Msg))
					{
					if (!filename) // Net 69 stuff
						{
						// Blank room name for net69 because we don't need it

						if (!Msg->GetToUser()[0] &&
								!(Msg->GetGroup()[0] && Msg->GetToUser()[0]))
							{
							if (TI()node->GetNetworkType() != NET_C86)
								{
								Msg->SetCreationRoom(ns);
								}
							}

						if (first && (TI()node->GetNetworkType() != NET_C86))
							{
							PutStr(file, GetRoomNetID(room));
							first = FALSE;
							}
						}

					TI()MS.Read++;

					if (TI()node->GetNetworkType() == NET_C86)
						{
						Msg->MakeCit86Packet(file);
						}
					else
						{
						Msg->Store(SMC_NETWORK, file);
						}
					}

				delete Msg;
				}
			}
		}

	if (filename)
		{
		fclose(file);
		}
	else
		{
		if (!first)
			{
			fputc(0, file);
			}
		}

	return (TI()MS.Read - read);
	}


static Message *LoadAndTestIfShouldSaveMessage(ulong id)
	{
	m_slot slot, origSlot;
	Bool referenceFlag;
	ulong referenceID;
	r_slot referenceRoom;
	uchar referenceAttr;

	Bool iter = FALSE;
	do
		{
		slot = indexslot(id);

		if (slot == M_SLOT_ERROR)
			{
			DebugOut(getdbmsg(39), ltoac(id));

			return (NULL);
			}

		if (!getFlags(slot)->IsInuse())
			{
			return (NULL);
			}

		if (!iter)
			{
			origSlot = slot;
			referenceID = id;
			referenceFlag = getFlags(slot)->IsCopy();
			referenceRoom = getRoomNum(slot);
			referenceAttr = 0;
			referenceAttr |= getFlags(slot)->IsReceived()	? ATTR_RECEIVED : 0;
			referenceAttr |= getFlags(slot)->IsReply()		? ATTR_REPLY	: 0;
			referenceAttr |= getFlags(slot)->IsMadevis()	? ATTR_MADEVIS	: 0;
			referenceAttr |= getFlags(slot)->IsCensored()	? ATTR_CENSORED : 0;
			}

		if (getFlags(slot)->IsCopy())
			{
			if (getCopy(slot) <= slot)
				{
				id -= getCopy(slot);
				}
			else
				{
				// Copied message has scrolled
				return (FALSE);
				}
			}

		iter = TRUE;
		} while (getFlags(slot)->IsCopy());

	if (MaySeeIndexMsg(origSlot) != MSM_GOOD && !getFlags(origSlot)->IsNet())
		{
		return (NULL);
		}

	ulong LocationInFile = getLocation(slot);

	if (LocationInFile != ULONG_ERROR)
		{
		Message *Msg = new Message;

		if (Msg)
			{
			ReadMessageStatus Status;

			bufferedWinReOpen(msgfl);
			bufferedSeek(msgfl, LocationInFile);
			Status = Msg->ReadAll(RMC_NORMAL, NULL);
			bufferedWinCloseTmp(msgfl);

			if (Status != RMS_OK)
				{
				delete Msg;
				return (NULL);
				}

			if (atol(Msg->GetLocalID()) != id)
				{
				label Byte;
				strcpy(Byte, ltoac(LocationInFile));

				cPrintf(getmsg(1007), cfg.Lmsg_nym, ltoac(id),
						Byte);
				doccr();
				delete Msg;
				return (NULL);
				}

			if (BeenThere(Msg->GetFromPath(), TI()node->GetName(),
					TI()node->GetAlias(), TI()node->GetLocID(), NULL))
				{
				delete Msg;
				return (NULL);
				}

			#ifndef WINCIT
				Msg->Decompress();
			#endif

			Msg->SetViewDuplicate(referenceFlag);
			Msg->SetOriginalID(referenceID);
			Msg->SetOriginalAttribute(referenceAttr);
			Msg->SetOriginalRoom(referenceRoom);

			if (Msg->GetFileLink()[0])
				{
				FILE *LinkedFile;

				if ((LinkedFile = fopen(Msg->GetFileLink(), FO_R)) == NULL)
					{
					return (NULL);
					}

				GetFileMessage(LinkedFile, Msg->GetTextPointer(), MAXTEXT);

				fclose(LinkedFile);
				}

			return (Msg);
			}
		else
			{
			cPrintf(getmsg(188), getnetmsg(118));
			return (NULL);
			}
		}
	else
		{
		return (NULL);
		}
	}
