// --------------------------------------------------------------------------
// Citadel: GrpEdit.CPP
//
// Code to edit groups.

#include "ctdl.h"
#pragma hdrstop

#include "room.h"
#include "log.h"
#include "group.h"
#include "hall.h"
#include "miscovl.h"


// --------------------------------------------------------------------------
// Contents
//
// killgroup()		sysop special to kill a group
// listgroup()		sysop/aide fn to list groups
// newgroup()		sysop special to add a new group
// renamegroup()	sysop special to rename a group


// --------------------------------------------------------------------------
// killgroup(): Sysop special to kill a group.

int killgroup(const char *gname)
	{
	char trapstr[256];
	label groupname;
	int groupslot, i;

	if (!gname)
		{
		doCR();

		do
			{
			getString(cfg.Lgroup_nym, groupname, LABELSIZE, TRUE, ECHO, ns);

			if (*groupname == '?')
				{
				ListGroups(FALSE);
				}
			} while (*groupname == '?');
		}
	else
		{
		CopyStringToBuffer(groupname, gname, LABELSIZE);
		}

	groupslot = FindGroupByPartialName(groupname, FALSE);

	if (groupslot == 0 || groupslot == 1)
		{
		if (!gname)
			{
			CRmPrintfCR(getmsg(957), GroupData->GetEntry(0)->GetName(),
					GroupData->GetEntry(1)->GetName(), 
					cfg.Lgroups_nym);
			}

		return (FALSE);
		}

	if (groupslot == CERROR || !(*groupname))
		{
		if (!gname)
			{
			CRmPrintfCR(getmsg(947), cfg.Lgroup_nym);
			}

		return (FALSE);
		}

	for (i = 0; i < cfg.maxrooms; i++)
		{
		if (IsRoomInuse(i) && (IsRoomGroupOnly(i) || IsRoomPrivGroup(i)))
			{
			Bool IsInuse = FALSE;

			if (IsRoomGroupOnly(i))
				{
				if (IsRoomMultiGroup(i))
					{
					IsInuse = IsInBooleanExpression(GetRoomGroupExpression(i),
							groupslot);
					}
				else
					{
					IsInuse = (GetRoomGroupNumber(i) == groupslot);
					}
				}

			if (!IsInuse && IsRoomPrivGroup(i))
				{
				IsInuse = (GetRoomPrivNumber(i) == groupslot);
				}

			if (IsInuse)
				{
				if (!gname)
					{
					CRmPrintfCR(getmsg(958), cfg.Ugroup_nym, cfg.Lroom_nym);
					}

				return (FALSE);
				}
			}
		}

	for (i = 0; i < cfg.maxhalls; i++)
		{
		if (HallData->GetEntry(i)->IsInuse() && HallData->GetEntry(i)->IsOwned())
			{
			Bool IsInuse = FALSE;

			if (HallData->GetEntry(i)->IsBoolGroup())
				{
				IsInuse = IsInBooleanExpression(HallData->GetEntry(i)->
						GetGroupExpression(), groupslot);
				}
			else
				{
				IsInuse =
						(HallData->GetEntry(i)->GetGroupNumber() == groupslot);
				}

			if (IsInuse)
				{
				if (!gname)
					{
					CRmPrintfCR(getmsg(960), cfg.Lhalls_nym);
					}

				return (FALSE);
				}
			}
		}

	sprintf(trapstr, getsysmsg(84), cfg.Lgroup_nym,
			GroupData->GetEntry(groupslot)->GetName());

	if (!gname && !getYesNo(trapstr, 0))
		{
		return (FALSE);
		}

	GroupData->GetEntry(groupslot)->SetInuse(FALSE);

	GroupData->Save();

	sprintf(trapstr, getmsg(961), groupname);
	trap(trapstr, T_SYSOP);

	return (TRUE);
	}


// --------------------------------------------------------------------------
// listgroup(): Sysop/aide fn to list groups.

void listgroup(void)
	{
	label groupname;

	SetDoWhat(AIDELIST);

	doCR();

	do
		{
		if (!getString(cfg.Lgroup_nym, groupname, LABELSIZE, TRUE, ECHO, ns))
			{
			return;
			}

		if (*groupname == '?')
			{
			ListGroups(FALSE);
			}
		} while (*groupname == '?');

	TI()UserControl.SetOutFlag(OUTOK);

	if (!(*groupname))
		{
		g_slot GroupSlot;

		doCR();

		for (GroupSlot = 0; GroupSlot < cfg.maxgroups; GroupSlot++)
			{
			// can they see the group
			if (GroupData->GetEntry(GroupSlot)->IsInuse() &&
					(!GroupData->GetEntry(GroupSlot)->IsLocked() || TI()CurrentUser->IsSysop()) &&
					(!GroupData->GetEntry(GroupSlot)->IsHidden() || onConsole || TI()CurrentUser->IsInGroup(GroupSlot)))
				{
				mPrintf(getmsg(232),
						(TI()CurrentUser->IsInGroup(GroupSlot)) ? '*' : ' ',
						GroupData->GetEntry(GroupSlot)->GetName(),
						GroupData->GetEntry(GroupSlot)->IsLocked() ? 'L' : ' ',
						GroupData->GetEntry(GroupSlot)->IsHidden() ? 'H' : ' ',
						(GroupData->GetEntry(GroupSlot)->IsAutoAdd() || !GroupSlot) ? 'A' : ' ');

				mPrintfCR(pcts, GroupData->GetEntry(GroupSlot)->GetDescription());
				}
			}
		}
	else
		{
		g_slot GroupSlot;
		int i;	// this is a l_slot and r_slot and h_slot...

		GroupSlot = FindGroupByPartialName(groupname, FALSE);

		if (GroupSlot == CERROR ||
				(GroupData->GetEntry(GroupSlot)->IsHidden() &&
				!TI()CurrentUser->IsInGroup(GroupSlot)))
			{
			CRmPrintfCR(getmsg(947), cfg.Lgroup_nym);
			return;
			}

		if (GroupData->GetEntry(GroupSlot)->IsLocked() && (!(TI()CurrentUser->IsSysop() || onConsole)))
			{
			CRmPrintf(getmsg(954), cfg.Ugroup_nym);
			return;
			}

		doCR();

		TI()UserControl.SetOutFlag(OUTOK);

		mPrintfCR(getmsg(962), cfg.Uusers_nym);

		prtList(LIST_START);

		for (i = 0; ((i < cfg.MAXLOGTAB) && (TI()UserControl.GetOutFlag() != OUTSKIP) &&
				(TI()UserControl.GetOutFlag() != OUTNEXT)); i++)
			{
			if (LogTab->GetEntry(i)->IsInuse())
				{
				LogEntry2 Log2(cfg.maxgroups);

				if (Log2.Load(LogTab->GetEntry(i)->GetLogIndex()))
					{
					if (Log2.IsInGroup(GroupSlot) ||
							(
								(
								cfg.showSysop || (TI()loggedIn &&
								TI()CurrentUser->IsMainSysop())
								)

							&&

							LogTab->GetEntry(i)->IsMainSysop()
							)
						)
						{
						prtList(LogTab->GetEntry(i)->GetName());
						}
					else
						{
						TI()UserControl.CheckInput(FALSE);
						}
					}
				}

			if (TI()UserControl.GetOutFlag() == OUTSKIP)
				{
				return;
				}
			}

		prtList(LIST_END);

		if (TI()UserControl.GetOutFlag() == OUTSKIP)
			{
			return;
			}

		TI()UserControl.SetOutFlag(OUTOK);

		CRmPrintfCR(getmsg(962), cfg.Urooms_nym);

		prtList(LIST_START);

		for (i = 0;
				(
					(i < cfg.maxrooms) &&
					(TI()UserControl.GetOutFlag() != OUTSKIP) &&
					(TI()UserControl.GetOutFlag() != OUTNEXT)
				);
				i++)
			{
			if (IsRoomInuse(i) && (IsRoomGroupOnly(i) || IsRoomPrivGroup(i)))
				{
				Bool ShowIt = FALSE;

				if (IsRoomGroupOnly(i))
					{
					if (IsRoomMultiGroup(i))
						{
						ShowIt = IsInBooleanExpression(
								GetRoomGroupExpression(i), GroupSlot);
						}
					else
						{
						ShowIt = (GetRoomGroupNumber(i) == GroupSlot);
						}
					}

				if (!ShowIt && IsRoomPrivGroup(i))
					{
					ShowIt = (GetRoomPrivNumber(i) == GroupSlot);
					}

				if (ShowIt)
					{
					prtList(GetRoomName(i));
					}
				}
			}

		prtList(LIST_END);

		if (TI()UserControl.GetOutFlag() == OUTSKIP)
			{
			return;
			}

		TI()UserControl.SetOutFlag(OUTOK);

		CRmPrintfCR(getmsg(962), cfg.Uhalls_nym);

		prtList(LIST_START);

		for (i = 0;
				(
					(i < cfg.maxhalls) &&
					(TI()UserControl.GetOutFlag() != OUTSKIP) &&
					(TI()UserControl.GetOutFlag() != OUTNEXT)
				);
				i++)
			{
			if (HallData->GetEntry(i)->IsInuse() &&
					HallData->GetEntry(i)->IsOwned())
				{
				Bool ShowIt = FALSE;

				if (HallData->GetEntry(i)->IsBoolGroup())
					{
					ShowIt = IsInBooleanExpression(HallData->GetEntry(i)->
							GetGroupExpression(), GroupSlot);
					}
				else
					{
					ShowIt =
							(HallData->GetEntry(i)->GetGroupNumber() ==
							GroupSlot);
					}

				if (ShowIt)
					{
					prtList(HallData->GetEntry(i)->GetName());
					}
				}
			}

		prtList(LIST_END);
		}
	}


// --------------------------------------------------------------------------
// newgroup(): Sysop special to add a new group.

Bool newgroup(const char *name, const char *desc, Bool lock, Bool hide,
		Bool autoadd)
	{
	label groupname;
	int slot, i, test;

	// search for a free group slot
	for (i = 0, slot = 0; i < cfg.maxgroups && !slot; i++)
		{
		if (!GroupData->GetEntry(i)->IsInuse())
			{
			slot = i;
			}
		}

	if (!slot)
		{
		if (!name)
			{
			CRmPrintf(getsysmsg(264));
			}

		return (FALSE);
		}

	if (name)
		{
		if ((!*name) || (FindGroupByName(name) != CERROR))
			{
			return (FALSE);
			}

		GroupData->GetEntry(slot)->SetName(name);
		GroupData->GetEntry(slot)->SetDescription(desc);
		GroupData->GetEntry(slot)->SetLocked(lock);
		GroupData->GetEntry(slot)->SetHidden(hide);
		GroupData->GetEntry(slot)->SetAutoAdd(autoadd);
		}
	else
		{
		char Desc[80];

		test = FALSE;
		do
			{
			doCR();
			getString(cfg.Lgroup_nym, groupname, LABELSIZE, TRUE, ECHO, ns);

			if (!*groupname)
				{
				return (FALSE);
				}

			if (*groupname == '?')
				{
				ListGroups(FALSE);
				}
			else if (FindGroupByName(groupname) != CERROR)
				{
				CRmPrintf(getsysmsg(257), groupname, cfg.Lgroup_nym);
				}
			else
				{
				test = TRUE;
				}
			} while (!test);

		getString(getsysmsg(258), Desc, 79, FALSE, ECHO, ns);

		GroupData->GetEntry(slot)->SetDescription(Desc);
		GroupData->GetEntry(slot)->SetLocked(getYesNo(getsysmsg(259), 0));
		GroupData->GetEntry(slot)->SetHidden(getYesNo(getsysmsg(260), 0));
		GroupData->GetEntry(slot)->SetAutoAdd(getYesNo(getsysmsg(261), 0));
		GroupData->GetEntry(slot)->SetName(groupname);
		}

	GroupData->GetEntry(slot)->SetInuse(TRUE);

	if (name || getYesNo(getmsg(57), 0))
		{
		char trapstr[256];

		cyclegroup(slot);

		GroupData->Save();

		sprintf(trapstr, getsysmsg(262), GroupData->GetEntry(slot)->GetName());

		trap(trapstr, T_SYSOP);

		TI()CurrentUser->SetInGroup(slot, TRUE);

		storeLog();

		if (!name)
			{
			globalgroup(GroupData->GetEntry(slot)->GetName(), getYesNo(getsysmsg(263), 0));
			}

		return (TRUE);
		}
	else
		{
		if (!GroupData->Load())
			{
			mPrintfCR(getmsg(656));
			}

		return (FALSE);
		}
	}


// --------------------------------------------------------------------------
// renamegroup(): Sysop special to rename a group.

Bool renamegroup(void)
	{
	label groupname, newname;
	char desc[80];
	g_slot GroupSlot;
	Bool prtMess = !TI()CurrentUser->IsExpert();
	Bool quit = FALSE;
	char trapstr[256];

	doCR();

	do
		{
		getString(cfg.Lgroup_nym, groupname, LABELSIZE, TRUE, ECHO, ns);

		if (!*groupname)
			{
			return (FALSE);
			}

		if (*groupname == '?')
			{
			ListGroups(FALSE);
			}
		} while (*groupname == '?');

	GroupSlot = FindGroupByPartialName(groupname, FALSE);

	if (GroupSlot != CERROR && (GroupData->GetEntry(GroupSlot)->IsHidden() &&
			!TI()CurrentUser->IsInGroup(GroupSlot) && !onConsole))
		{
		GroupSlot = CERROR;
		}

	if (GroupSlot == CERROR)
		{
		CRmPrintfCR(getmsg(947), cfg.Lgroup_nym);
		return (FALSE);
		}

	do
		{
		if (prtMess)
			{
			doCR();
			TI()UserControl.SetOutFlag(OUTOK);

			mPrintfCR(getsysmsg(177),
					GroupData->GetEntry(GroupSlot)->GetName());

			mPrintfCR(getsysmsg(178),
					GroupData->GetEntry(GroupSlot)->GetDescription()[0] ?
					GroupData->GetEntry(GroupSlot)->GetDescription() :
					getsysmsg(179));

			displayYesNo(getsysmsg(180),
					GroupData->GetEntry(GroupSlot)->IsLocked());
			doCR();

			displayYesNo(getsysmsg(181),
					GroupData->GetEntry(GroupSlot)->IsHidden());
			doCR();

			if (!GroupSlot)
				{
				GroupData->GetEntry(GroupSlot)->SetAutoAdd(TRUE);
				}

			displayYesNo(getsysmsg(182),
					GroupData->GetEntry(GroupSlot)->IsAutoAdd());

			CRCRmPrintfCR(getmsg(868));

			prtMess = !TI()CurrentUser->IsExpert();
			}

		const int c = DoMenuPrompt(getmsg(616), NULL);

		if (!(HaveConnectionToUser()))
			{
			GroupData->Load();
			return (FALSE);
			}

		switch (toupper(c))
			{
			case ESC:
			case 'A':
				{
				mPrintfCR(getmsg(653));

				if (getYesNo(getmsg(654), TRUE))
					{
					if (!GroupData->Load())
						{
						mPrintfCR(getmsg(656));
						}

					return (FALSE);
					}

				break;
				}

			case 'D':
				{
				char Prompt[128];

				mPrintfCR(getsysmsg(186));

				sprintf(Prompt, getsysmsg(187), cfg.Lgroup_nym);

				getString(Prompt, desc, 79, FALSE, ECHO,
						GroupData->GetEntry(GroupSlot)->GetDescription());

				if (*desc)
					{
					normalizeString(desc);
					GroupData->GetEntry(GroupSlot)->SetDescription(desc);
					}

				break;
				}

			case 'H':
				{
				char Prompt[128];

				mPrintfCR(getsysmsg(190));

				sprintf(Prompt, getsysmsg(191), cfg.Lgroup_nym);

				GroupData->GetEntry(GroupSlot)->SetHidden(
						getYesNo(Prompt, GroupData->GetEntry(
						GroupSlot)->IsHidden()));
				break;
				}

			case 'L':
				{
				char Prompt[128];

				mPrintfCR(getsysmsg(188));

				sprintf(Prompt, getsysmsg(189), cfg.Lgroup_nym);

				GroupData->GetEntry(GroupSlot)->SetLocked(getYesNo(
						Prompt, GroupData->GetEntry(GroupSlot)->
						IsLocked()));
				break;
				}

			case 'N':
				{
				char Prompt[128];

				mPrintfCR(getmsg(248));

				sprintf(Prompt, getsysmsg(184), cfg.Lgroup_nym);

				do
					{
					getString(Prompt, newname, LABELSIZE, TRUE, ECHO,
							GroupData->GetEntry(GroupSlot)->GetName());

					if (*newname == '?')
						{
						ListGroups(FALSE);
						}
					} while (*newname == '?');
				normalizeString(newname);

				if (*newname && (FindGroupByName(newname) != CERROR) &&
						!SameString(newname, GroupData->GetEntry(
						GroupSlot)->GetName()))
					{
					CRmPrintfCR(getsysmsg(185), newname, cfg.Lgroup_nym);
					}
				else
					{
					if (*newname)
						{
						GroupData->GetEntry(GroupSlot)->SetName(newname);
						}
					}

				break;
				}

			case 'S':
				{
				mPrintfCR(getmsg(60));

				if (getYesNo(getmsg(652), FALSE))
					{
					quit = TRUE;
					}

				break;
				}

			case 'U':
				{
				char Prompt[128];

				mPrintfCR(getsysmsg(192));

				sprintf(Prompt, getsysmsg(193), cfg.Lgroup_nym);

				if (GroupSlot)
					{
					GroupData->GetEntry(GroupSlot)->SetAutoAdd(getYesNo(
							Prompt, GroupData->GetEntry(GroupSlot)->
							IsAutoAdd()));
					}
				else
					{
					GroupData->GetEntry(GroupSlot)->SetAutoAdd(TRUE);
					CRmPrintfCR(getsysmsg(194), cfg.Lgroup_nym,
							GroupData->GetEntry(0)->GetName());
					}

				break;
				}

			case '\r':
			case '\n':
			case '?':
				{
				mPrintfCR(getmsg(351));

				prtMess = TRUE;
				break;
				}

			default:
				{
				BadMenuSelection(c);
				break;
				}
			}
		} while (!quit);

	sprintf(trapstr, getsysmsg(195), groupname,
			GroupData->GetEntry(GroupSlot)->GetName());

	trap(trapstr, T_SYSOP);
	GroupData->Save();

	return (TRUE);
	}
