/*
 * PtokaX - hub server for Direct Connect peer to peer network.

 * Copyright (C) 2004-2022  Petr Kozelka, PPK at PtokaX dot org

 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3
 * as published by the Free Software Foundation.

 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.

 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

//---------------------------------------------------------------------------
#include "stdinc.h"
#include <cstring>
//---------------------------------------------------------------------------
#include "LuaInc.h"
//---------------------------------------------------------------------------
#include "LuaSetManLib.h"
//---------------------------------------------------------------------------
#include "eventqueue.h"
#include "hashRegManager.h"
#include "hashUsrManager.h"
#include "LuaScriptManager.h"
#include "SettingManager.h"
#include "GlobalDataQueue.h"
//---------------------------------------------------------------------------
#ifdef _WIN32
#pragma hdrstop
#endif
//---------------------------------------------------------------------------

static int Save(lua_State * pLua)
{
    GlobalDataQueue::m_Ptr->PrometheusLuaInc(__func__);
	if (lua_gettop(pLua) != 0)
	{
		luaL_error(pLua, "bad argument count to 'Save' (0 expected, got %d)", lua_gettop(pLua));
		lua_settop(pLua, 0);
		return 0;
	}

	ScriptManager::m_Ptr->SaveScripts();

	SettingManager::m_Ptr->Save();

	return 0;
}
//------------------------------------------------------------------------------

static int GetMOTD(lua_State * pLua)
{
    GlobalDataQueue::m_Ptr->PrometheusLuaInc(__func__);
	if (lua_gettop(pLua) != 0)
	{
		luaL_error(pLua, "bad argument count to 'GetMOTD' (0 expected, got %d)", lua_gettop(pLua));
		lua_settop(pLua, 0);
		lua_pushnil(pLua);
		return 0;
	}

	if (SettingManager::m_Ptr->m_sMOTD != NULL)
	{
		lua_pushlstring(pLua, SettingManager::m_Ptr->m_sMOTD, (size_t)SettingManager::m_Ptr->m_ui16MOTDLen);
	}
	else
	{
		lua_pushnil(pLua);
	}

	return 1;
}
//------------------------------------------------------------------------------

static int SetMOTD(lua_State * pLua)
{
    GlobalDataQueue::m_Ptr->PrometheusLuaInc(__func__);
	if (lua_gettop(pLua) != 1)
	{
		luaL_error(pLua, "bad argument count to 'SetMOTD' (1 expected, got %d)", lua_gettop(pLua));
		lua_settop(pLua, 0);
		return 0;
	}

	if (lua_type(pLua, 1) != LUA_TSTRING)
	{
		luaL_checktype(pLua, 1, LUA_TSTRING);
		lua_settop(pLua, 0);
		return 0;
	}

	size_t szLen = 0;
	const char * sTxt = lua_tolstring(pLua, 1, &szLen);

	SettingManager::m_Ptr->SetMOTD(sTxt, szLen);

	SettingManager::m_Ptr->UpdateMOTD();

	lua_settop(pLua, 0);
	return 0;
}
//------------------------------------------------------------------------------

static int GetBool(lua_State * pLua)
{
    GlobalDataQueue::m_Ptr->PrometheusLuaInc(__func__);
	if (lua_gettop(pLua) != 1)
	{
		luaL_error(pLua, "bad argument count to 'GetBool' (1 expected, got %d)", lua_gettop(pLua));
		lua_settop(pLua, 0);
		lua_pushnil(pLua);
		return 1;
	}

	if (lua_type(pLua, 1) != LUA_TNUMBER)
	{
		luaL_checktype(pLua, 1, LUA_TNUMBER);
		lua_settop(pLua, 0);
		lua_pushnil(pLua);
		return 1;
	}

#if LUA_VERSION_NUM < 503
	size_t szId = (size_t)lua_tonumber(pLua, 1);
#else
	size_t szId = (size_t)lua_tointeger(pLua, 1);
#endif

	lua_settop(pLua, 0);

	if (szId >= SETBOOL_IDS_END)
	{
		luaL_error(pLua, "bad argument #1 to 'GetBool' (it's not valid id)");
		lua_pushnil(pLua);
		return 1;
	}

	SettingManager::m_Ptr->m_bBools[szId] == true ? lua_pushboolean(pLua, 1) : lua_pushnil(pLua);

	return 1;
}
//------------------------------------------------------------------------------

static int SetBool(lua_State * pLua)
{
    GlobalDataQueue::m_Ptr->PrometheusLuaInc(__func__);
	if (lua_gettop(pLua) != 2)
	{
		luaL_error(pLua, "bad argument count to 'SetBool' (2 expected, got %d)", lua_gettop(pLua));
		lua_settop(pLua, 0);
		return 0;
	}

	if (lua_type(pLua, 1) != LUA_TNUMBER || lua_type(pLua, 2) != LUA_TBOOLEAN)
	{
		luaL_checktype(pLua, 1, LUA_TNUMBER);
		luaL_checktype(pLua, 2, LUA_TBOOLEAN);
		lua_settop(pLua, 0);
		return 0;
	}

#if LUA_VERSION_NUM < 503
	size_t szId = (size_t)lua_tonumber(pLua, 1);
#else
	size_t szId = (size_t)lua_tointeger(pLua, 1);
#endif

	bool bValue = (lua_toboolean(pLua, 2) == 0 ? false : true);

	lua_settop(pLua, 0);

	if (szId >= SETBOOL_IDS_END)
	{
		luaL_error(pLua, "bad argument #1 to 'SetBool' (it's not valid id)");
		return 0;
	}

	if (szId == SETBOOL_ENABLE_SCRIPTING && bValue == false)
	{
		EventQueue::m_Ptr->AddNormal(EventQueue::EVENT_STOP_SCRIPTING, NULL);
		return 0;
	}

	if (szId == SETBOOL_HASH_PASSWORDS && bValue == true)
	{
		RegManager::m_Ptr->HashPasswords();
	}

	SettingManager::m_Ptr->SetBool(szId, bValue);

	return 0;
}
//------------------------------------------------------------------------------

static int GetNumber(lua_State * pLua)
{
    GlobalDataQueue::m_Ptr->PrometheusLuaInc(__func__);
	if (lua_gettop(pLua) != 1)
	{
		luaL_error(pLua, "bad argument count to 'GetNumber' (1 expected, got %d)", lua_gettop(pLua));
		lua_settop(pLua, 0);
		lua_pushnil(pLua);
		return 1;
	}

	if (lua_type(pLua, 1) != LUA_TNUMBER)
	{
		luaL_checktype(pLua, 1, LUA_TNUMBER);
		lua_settop(pLua, 0);
		lua_pushnil(pLua);
		return 1;
	}

#if LUA_VERSION_NUM < 503
	size_t szId = (size_t)lua_tonumber(pLua, 1);
#else
	size_t szId = (size_t)lua_tointeger(pLua, 1);
#endif

	lua_settop(pLua, 0);

	if (szId >= (SETSHORT_IDS_END - 1))
	{
		luaL_error(pLua, "bad argument #1 to 'GetNumber' (it's not valid id)");
		lua_pushnil(pLua);
		return 1;
	}

	lua_pushinteger(pLua, SettingManager::m_Ptr->m_i16Shorts[szId]);

	return 1;
}
//------------------------------------------------------------------------------

static int SetNumber(lua_State * pLua)
{
    GlobalDataQueue::m_Ptr->PrometheusLuaInc(__func__);
	if (lua_gettop(pLua) != 2)
	{
		luaL_error(pLua, "bad argument count to 'SetNumber' (2 expected, got %d)", lua_gettop(pLua));
		lua_settop(pLua, 0);
		return 0;
	}

	if (lua_type(pLua, 1) != LUA_TNUMBER || lua_type(pLua, 2) != LUA_TNUMBER)
	{
		luaL_checktype(pLua, 1, LUA_TNUMBER);
		luaL_checktype(pLua, 2, LUA_TNUMBER);
		lua_settop(pLua, 0);
		return 0;
	}

#if LUA_VERSION_NUM < 503
	size_t szId = (size_t)lua_tonumber(pLua, 1);
#else
	size_t szId = (size_t)lua_tointeger(pLua, 1);
#endif

	int16_t iValue = (int16_t)lua_tointeger(pLua, 2);

	lua_settop(pLua, 0);

	if (szId >= (SETSHORT_IDS_END - 1))
	{
		luaL_error(pLua, "bad argument #1 to 'SetNumber' (it's not valid id)");
		return 0;
	}

	SettingManager::m_Ptr->SetShort(szId, iValue);

	return 0;
}
//------------------------------------------------------------------------------

static int GetString(lua_State * pLua)
{
    GlobalDataQueue::m_Ptr->PrometheusLuaInc(__func__);
	if (lua_gettop(pLua) != 1)
	{
		luaL_error(pLua, "bad argument count to 'GetString' (1 expected, got %d)", lua_gettop(pLua));
		lua_settop(pLua, 0);
		lua_pushnil(pLua);
		return 1;
	}

	if (lua_type(pLua, 1) != LUA_TNUMBER)
	{
		luaL_checktype(pLua, 1, LUA_TNUMBER);
		lua_settop(pLua, 0);
		lua_pushnil(pLua);
		return 1;
	}

#if LUA_VERSION_NUM < 503
	size_t szId = (size_t)lua_tonumber(pLua, 1);
#else
	size_t szId = (size_t)lua_tointeger(pLua, 1);
#endif

	lua_settop(pLua, 0);

	if (szId >= SETTXT_IDS_END)
	{
		luaL_error(pLua, "bad argument #1 to 'GetString' (it's not valid id)");
		lua_pushnil(pLua);
		return 1;
	}

	if (SettingManager::m_Ptr->m_sTexts[szId] != NULL)
	{
		lua_pushlstring(pLua, SettingManager::m_Ptr->m_sTexts[szId], (size_t)SettingManager::m_Ptr->m_ui16TextsLens[szId]);
	}
	else
	{
		lua_pushnil(pLua);
	}

	return 1;
}
//------------------------------------------------------------------------------

static int SetString(lua_State * pLua)
{
    GlobalDataQueue::m_Ptr->PrometheusLuaInc(__func__);
	if (lua_gettop(pLua) != 2)
	{
		luaL_error(pLua, "bad argument count to 'SetString' (2 expected, got %d)", lua_gettop(pLua));
		lua_settop(pLua, 0);
		return 0;
	}

	if (lua_type(pLua, 1) != LUA_TNUMBER || lua_type(pLua, 2) != LUA_TSTRING)
	{
		luaL_checktype(pLua, 1, LUA_TNUMBER);
		luaL_checktype(pLua, 2, LUA_TSTRING);
		lua_settop(pLua, 0);
		return 0;
	}

#if LUA_VERSION_NUM < 503
	size_t szId = (size_t)lua_tonumber(pLua, 1);
#else
	size_t szId = (size_t)lua_tointeger(pLua, 1);
#endif

	if (szId >= SETTXT_IDS_END)
	{
		luaL_error(pLua, "bad argument #1 to 'SetString' (it's not valid id)");
		return 0;
	}

	size_t szLen;
	const char * sValue = lua_tolstring(pLua, 2, &szLen);

	SettingManager::m_Ptr->SetText(szId, sValue, szLen);

	return 0;
}
//------------------------------------------------------------------------------

static int GetMinShare(lua_State * pLua)
{
    GlobalDataQueue::m_Ptr->PrometheusLuaInc(__func__);
	if (lua_gettop(pLua) != 0)
	{
		luaL_error(pLua, "bad argument count to 'GetMinShare' (0 expected, got %d)", lua_gettop(pLua));
		lua_settop(pLua, 0);
		lua_pushnil(pLua);
		return 0;
	}

#if LUA_VERSION_NUM < 503
	lua_pushnumber(pLua, (double)SettingManager::m_Ptr->m_ui64MinShare);
#else
	lua_pushinteger(pLua, SettingManager::m_Ptr->m_ui64MinShare);
#endif

	return 1;
}
//------------------------------------------------------------------------------

static int SetMinShare(lua_State * pLua)
{
    GlobalDataQueue::m_Ptr->PrometheusLuaInc(__func__);
	const int n = lua_gettop(pLua);

	if (n == 2)
	{
		if (lua_type(pLua, 1) != LUA_TNUMBER || lua_type(pLua, 2) != LUA_TNUMBER)
		{
			luaL_checktype(pLua, 1, LUA_TNUMBER);
			luaL_checktype(pLua, 2, LUA_TNUMBER);
			lua_settop(pLua, 0);
			return 0;
		}

		SettingManager::m_Ptr->m_bUpdateLocked = true;

#if LUA_VERSION_NUM < 503
		SettingManager::m_Ptr->SetShort(SETSHORT_MIN_SHARE_LIMIT, (int16_t)lua_tonumber(pLua, 1));
		SettingManager::m_Ptr->SetShort(SETSHORT_MIN_SHARE_UNITS, (int16_t)lua_tonumber(pLua, 2));
#else
		SettingManager::m_Ptr->SetShort(SETSHORT_MIN_SHARE_LIMIT, (int16_t)lua_tointeger(pLua, 1));
		SettingManager::m_Ptr->SetShort(SETSHORT_MIN_SHARE_UNITS, (int16_t)lua_tointeger(pLua, 2));
#endif

		SettingManager::m_Ptr->m_bUpdateLocked = false;
	}
	else if (n == 1)
	{
		if (lua_type(pLua, 1) != LUA_TNUMBER)
		{
			luaL_checktype(pLua, 1, LUA_TNUMBER);
			lua_settop(pLua, 0);
			return 0;
		}

		double dBytes = lua_tonumber(pLua, 1);
		uint16_t iter = 0;
		for (; dBytes > 1024; iter++)
		{
			dBytes /= 1024;
		}

		SettingManager::m_Ptr->m_bUpdateLocked = true;

		SettingManager::m_Ptr->SetShort(SETSHORT_MIN_SHARE_LIMIT, (int16_t)dBytes);
		SettingManager::m_Ptr->SetShort(SETSHORT_MIN_SHARE_UNITS, iter);

		SettingManager::m_Ptr->m_bUpdateLocked = false;
	}
	else
	{
		luaL_error(pLua, "bad argument count to 'SetMinShare' (1 or 2 expected, got %d)", lua_gettop(pLua));
		lua_settop(pLua, 0);
		return 0;
	}

	SettingManager::m_Ptr->UpdateMinShare();
	SettingManager::m_Ptr->UpdateShareLimitMessage();

	lua_settop(pLua, 0);
	return 0;
}
//------------------------------------------------------------------------------

static int GetMaxShare(lua_State * pLua)
{
    GlobalDataQueue::m_Ptr->PrometheusLuaInc(__func__);
	if (lua_gettop(pLua) != 0)
	{
		luaL_error(pLua, "bad argument count to 'GetMaxShare' (0 expected, got %d)", lua_gettop(pLua));
		lua_settop(pLua, 0);
		lua_pushnil(pLua);
		return 0;
	}

#if LUA_VERSION_NUM < 503
	lua_pushnumber(pLua, (double)SettingManager::m_Ptr->m_ui64MaxShare);
#else
	lua_pushinteger(pLua, SettingManager::m_Ptr->m_ui64MaxShare);
#endif

	return 1;
}
//------------------------------------------------------------------------------

static int SetMaxShare(lua_State * pLua)
{
    GlobalDataQueue::m_Ptr->PrometheusLuaInc(__func__);
	const int n = lua_gettop(pLua);

	if (n == 2)
	{
		if (lua_type(pLua, 1) != LUA_TNUMBER || lua_type(pLua, 2) != LUA_TNUMBER)
		{
			luaL_checktype(pLua, 1, LUA_TNUMBER);
			luaL_checktype(pLua, 2, LUA_TNUMBER);
			lua_settop(pLua, 0);
			return 0;
		}

		SettingManager::m_Ptr->m_bUpdateLocked = true;

#if LUA_VERSION_NUM < 503
		SettingManager::m_Ptr->SetShort(SETSHORT_MAX_SHARE_LIMIT, (int16_t)lua_tonumber(pLua, 1));
		SettingManager::m_Ptr->SetShort(SETSHORT_MAX_SHARE_UNITS, (int16_t)lua_tonumber(pLua, 2));
#else
		SettingManager::m_Ptr->SetShort(SETSHORT_MAX_SHARE_LIMIT, (int16_t)lua_tointeger(pLua, 1));
		SettingManager::m_Ptr->SetShort(SETSHORT_MAX_SHARE_UNITS, (int16_t)lua_tointeger(pLua, 2));
#endif

		SettingManager::m_Ptr->m_bUpdateLocked = false;
	}
	else if (n == 1)
	{
		if (lua_type(pLua, 1) != LUA_TNUMBER)
		{
			luaL_checktype(pLua, 1, LUA_TNUMBER);
			lua_settop(pLua, 0);
			return 0;
		}

		double dBytes = (double)lua_tonumber(pLua, 1);
		uint16_t iter = 0;
		for (; dBytes > 1024; iter++)
		{
			dBytes /= 1024;
		}

		SettingManager::m_Ptr->m_bUpdateLocked = true;

		SettingManager::m_Ptr->SetShort(SETSHORT_MAX_SHARE_LIMIT, (int16_t)dBytes);
		SettingManager::m_Ptr->SetShort(SETSHORT_MAX_SHARE_UNITS, iter);

		SettingManager::m_Ptr->m_bUpdateLocked = false;
	}
	else
	{
		luaL_error(pLua, "bad argument count to 'SetMaxShare' (1 or 2 expected, got %d)", lua_gettop(pLua));
		lua_settop(pLua, 0);
		return 0;
	}

	SettingManager::m_Ptr->UpdateMaxShare();
	SettingManager::m_Ptr->UpdateShareLimitMessage();

	lua_settop(pLua, 0);
	return 0;
}
//------------------------------------------------------------------------------

static int SetHubSlotRatio(lua_State * pLua)
{
    GlobalDataQueue::m_Ptr->PrometheusLuaInc(__func__);
	if (lua_gettop(pLua) != 2)
	{
		luaL_error(pLua, "bad argument count to 'SetHubSlotRatio' (2 expected, got %d)", lua_gettop(pLua));
		lua_settop(pLua, 0);
		return 0;
	}

	if (lua_type(pLua, 1) != LUA_TNUMBER || lua_type(pLua, 2) != LUA_TNUMBER)
	{
		luaL_checktype(pLua, 1, LUA_TNUMBER);
		luaL_checktype(pLua, 2, LUA_TNUMBER);
		lua_settop(pLua, 0);
		return 0;
	}

	SettingManager::m_Ptr->m_bUpdateLocked = true;

#if LUA_VERSION_NUM < 503
	SettingManager::m_Ptr->SetShort(SETSHORT_HUB_SLOT_RATIO_HUBS, (int16_t)lua_tonumber(pLua, 1));
	SettingManager::m_Ptr->SetShort(SETSHORT_HUB_SLOT_RATIO_SLOTS, (int16_t)lua_tonumber(pLua, 2));
#else
	SettingManager::m_Ptr->SetShort(SETSHORT_HUB_SLOT_RATIO_HUBS, (int16_t)lua_tointeger(pLua, 1));
	SettingManager::m_Ptr->SetShort(SETSHORT_HUB_SLOT_RATIO_SLOTS, (int16_t)lua_tointeger(pLua, 2));
#endif

	SettingManager::m_Ptr->m_bUpdateLocked = false;

	SettingManager::m_Ptr->UpdateHubSlotRatioMessage();

	lua_settop(pLua, 0);
	return 0;
}
//------------------------------------------------------------------------------

static int GetOpChat(lua_State * pLua)
{
    GlobalDataQueue::m_Ptr->PrometheusLuaInc(__func__);
	if (lua_gettop(pLua) != 0)
	{
		luaL_error(pLua, "bad argument count to 'GetOpChat' (0 expected, got %d)", lua_gettop(pLua));
		lua_settop(pLua, 0);
		lua_pushnil(pLua);
		return 0;
	}

	lua_newtable(pLua);
	int i = lua_gettop(pLua);

	lua_pushliteral(pLua, "sNick");
	if (SettingManager::m_Ptr->m_sTexts[SETTXT_OP_CHAT_NICK] == NULL)
	{
		lua_pushnil(pLua);
	}
	else
	{
		lua_pushlstring(pLua, SettingManager::m_Ptr->m_sTexts[SETTXT_OP_CHAT_NICK],
		                (size_t)SettingManager::m_Ptr->m_ui16TextsLens[SETTXT_OP_CHAT_NICK]);
	}
	lua_rawset(pLua, i);

	lua_pushliteral(pLua, "sDescription");
	if (SettingManager::m_Ptr->m_sTexts[SETTXT_OP_CHAT_DESCRIPTION] == NULL)
	{
		lua_pushnil(pLua);
	}
	else
	{
		lua_pushlstring(pLua, SettingManager::m_Ptr->m_sTexts[SETTXT_OP_CHAT_DESCRIPTION],
		                (size_t)SettingManager::m_Ptr->m_ui16TextsLens[SETTXT_OP_CHAT_DESCRIPTION]);
	}
	lua_rawset(pLua, i);

	lua_pushliteral(pLua, "sEmail");
	if (SettingManager::m_Ptr->m_sTexts[SETTXT_OP_CHAT_EMAIL] == NULL)
	{
		lua_pushnil(pLua);
	}
	else
	{
		lua_pushlstring(pLua, SettingManager::m_Ptr->m_sTexts[SETTXT_OP_CHAT_EMAIL],
		                (size_t)SettingManager::m_Ptr->m_ui16TextsLens[SETTXT_OP_CHAT_EMAIL]);
	}
	lua_rawset(pLua, i);

	lua_pushliteral(pLua, "bEnabled");
	SettingManager::m_Ptr->m_bBools[SETBOOL_REG_OP_CHAT] == true ? lua_pushboolean(pLua, 1) : lua_pushnil(pLua);
	lua_rawset(pLua, i);

	return 1;
}
//------------------------------------------------------------------------------

static int SetOpChat(lua_State * pLua)
{
    GlobalDataQueue::m_Ptr->PrometheusLuaInc(__func__);
	if (lua_gettop(pLua) != 4)
	{
		luaL_error(pLua, "bad argument count to 'SetOpChat' (4 expected, got %d)", lua_gettop(pLua));
		lua_settop(pLua, 0);
		return 0;
	}

	if (lua_type(pLua, 1) != LUA_TBOOLEAN || lua_type(pLua, 2) != LUA_TSTRING || lua_type(pLua, 3) != LUA_TSTRING || lua_type(pLua, 4) != LUA_TSTRING)
	{
		luaL_checktype(pLua, 1, LUA_TBOOLEAN);
		luaL_checktype(pLua, 2, LUA_TSTRING);
		luaL_checktype(pLua, 3, LUA_TSTRING);
		luaL_checktype(pLua, 4, LUA_TSTRING);
		lua_settop(pLua, 0);
		return 0;
	}

	const char *NewBotName, *NewBotDescription, *NewBotEmail;
	size_t szNameLen, szDescrLen, szEmailLen;

	NewBotName = lua_tolstring(pLua, 2, &szNameLen);
	NewBotDescription = lua_tolstring(pLua, 3, &szDescrLen);
	NewBotEmail = lua_tolstring(pLua, 4, &szEmailLen);

	if (szNameLen == 0 || szNameLen > 64 || szDescrLen > 64 || szEmailLen > 64 ||
	        strpbrk(NewBotName, " $|") != NULL || strpbrk(NewBotDescription, "$|") != NULL ||
	        strpbrk(NewBotEmail, "$|") != NULL || HashManager::m_Ptr->FindUser(NewBotName, szNameLen) != NULL)
	{
		lua_settop(pLua, 0);
		return 0;
	}

	bool bBotHaveNewNick = (strcmp(SettingManager::m_Ptr->m_sTexts[SETTXT_OP_CHAT_NICK], NewBotName) != 0);
	bool bEnableBot = (lua_toboolean(pLua, 1) == 0 ? false : true);

	bool bRegStateChange = false, bDescriptionChange = false, bEmailChange = false;

	if (SettingManager::m_Ptr->m_bBools[SETBOOL_REG_OP_CHAT] != bEnableBot)
	{
		bRegStateChange = true;
	}

	if (SettingManager::m_Ptr->m_bBools[SETBOOL_REG_OP_CHAT] == true)
	{
		SettingManager::m_Ptr->DisableOpChat((bBotHaveNewNick == true || bEnableBot == false));
	}

	SettingManager::m_Ptr->m_bUpdateLocked = true;

	SettingManager::m_Ptr->SetBool(SETBOOL_REG_OP_CHAT, bEnableBot);

	if (bBotHaveNewNick == true)
	{
		SettingManager::m_Ptr->SetText(SETTXT_OP_CHAT_NICK, NewBotName);
	}

	if (SettingManager::m_Ptr->m_sTexts[SETTXT_OP_CHAT_DESCRIPTION] == NULL ||
	        strcmp(SettingManager::m_Ptr->m_sTexts[SETTXT_OP_CHAT_DESCRIPTION], NewBotDescription) != 0)
	{
		if (szDescrLen != (size_t)(SettingManager::m_Ptr->m_sTexts[SETTXT_OP_CHAT_DESCRIPTION] == NULL ? 0 : -1))
		{
			bDescriptionChange = true;
		}

		SettingManager::m_Ptr->SetText(SETTXT_OP_CHAT_DESCRIPTION, NewBotDescription);
	}

	if (SettingManager::m_Ptr->m_sTexts[SETTXT_OP_CHAT_EMAIL] == NULL ||
	        strcmp(SettingManager::m_Ptr->m_sTexts[SETTXT_OP_CHAT_EMAIL], NewBotEmail) != 0)
	{
		if (szEmailLen != (size_t)(SettingManager::m_Ptr->m_sTexts[SETTXT_OP_CHAT_EMAIL] == NULL ? 0 : -1))
		{
			bEmailChange = true;
		}

		SettingManager::m_Ptr->SetText(SETTXT_OP_CHAT_EMAIL, NewBotEmail);
	}

	SettingManager::m_Ptr->m_bUpdateLocked = false;

	SettingManager::m_Ptr->UpdateBotsSameNick();

	if (SettingManager::m_Ptr->m_bBools[SETBOOL_REG_OP_CHAT] == true &&
	        (bRegStateChange == true || bBotHaveNewNick == true || bDescriptionChange == true || bEmailChange == true))
	{
		SettingManager::m_Ptr->UpdateOpChat((bBotHaveNewNick == true || bRegStateChange == true));
	}

	lua_settop(pLua, 0);
	return 0;
}
//------------------------------------------------------------------------------

static int GetHubBot(lua_State * pLua)
{
    GlobalDataQueue::m_Ptr->PrometheusLuaInc(__func__);
	if (lua_gettop(pLua) != 0)
	{
		luaL_error(pLua, "bad argument count to 'GetHubBot' (0 expected, got %d)", lua_gettop(pLua));
		lua_settop(pLua, 0);
		lua_pushnil(pLua);
		return 0;
	}

	lua_newtable(pLua);
	int i = lua_gettop(pLua);

	lua_pushliteral(pLua, "sNick");
	if (SettingManager::m_Ptr->m_sTexts[SETTXT_BOT_NICK] == NULL)
	{
		lua_pushnil(pLua);
	}
	else
	{
		lua_pushlstring(pLua, SettingManager::m_Ptr->m_sTexts[SETTXT_BOT_NICK],
		                (size_t)SettingManager::m_Ptr->m_ui16TextsLens[SETTXT_BOT_NICK]);
	}
	lua_rawset(pLua, i);

	lua_pushliteral(pLua, "sDescription");
	if (SettingManager::m_Ptr->m_sTexts[SETTXT_BOT_DESCRIPTION] == NULL)
	{
		lua_pushnil(pLua);
	}
	else
	{
		lua_pushlstring(pLua, SettingManager::m_Ptr->m_sTexts[SETTXT_BOT_DESCRIPTION],
		                (size_t)SettingManager::m_Ptr->m_ui16TextsLens[SETTXT_BOT_DESCRIPTION]);
	}
	lua_rawset(pLua, i);

	lua_pushliteral(pLua, "sEmail");
	if (SettingManager::m_Ptr->m_sTexts[SETTXT_BOT_EMAIL] == NULL)
	{
		lua_pushnil(pLua);
	}
	else
	{
		lua_pushlstring(pLua, SettingManager::m_Ptr->m_sTexts[SETTXT_BOT_EMAIL],
		                (size_t)SettingManager::m_Ptr->m_ui16TextsLens[SETTXT_BOT_EMAIL]);
	}
	lua_rawset(pLua, i);

	lua_pushliteral(pLua, "bEnabled");
	SettingManager::m_Ptr->m_bBools[SETBOOL_REG_BOT] == true ? lua_pushboolean(pLua, 1) : lua_pushnil(pLua);
	lua_rawset(pLua, i);

	lua_pushliteral(pLua, "bUsedAsHubSecAlias");
	SettingManager::m_Ptr->m_bBools[SETBOOL_USE_BOT_NICK_AS_HUB_SEC] == true ? lua_pushboolean(pLua, 1) : lua_pushnil(pLua);
	lua_rawset(pLua, i);

	return 1;
}
//------------------------------------------------------------------------------

static int SetHubBot(lua_State * pLua)
{
    GlobalDataQueue::m_Ptr->PrometheusLuaInc(__func__);
	if (lua_gettop(pLua) != 5)
	{
		luaL_error(pLua, "bad argument count to 'SetHubBot' (5 expected, got %d)", lua_gettop(pLua));
		lua_settop(pLua, 0);
		return 0;
	}

	if (lua_type(pLua, 1) != LUA_TBOOLEAN || lua_type(pLua, 2) != LUA_TSTRING || lua_type(pLua, 3) != LUA_TSTRING ||
	        lua_type(pLua, 4) != LUA_TSTRING || lua_type(pLua, 5) != LUA_TBOOLEAN)
	{
		luaL_checktype(pLua, 1, LUA_TBOOLEAN);
		luaL_checktype(pLua, 2, LUA_TSTRING);
		luaL_checktype(pLua, 3, LUA_TSTRING);
		luaL_checktype(pLua, 4, LUA_TSTRING);
		luaL_checktype(pLua, 5, LUA_TBOOLEAN);
		lua_settop(pLua, 0);
		return 0;
	}

	const char *NewBotName, *NewBotDescription, *NewBotEmail;
	size_t szNameLen, szDescrLen, szEmailLen;

	NewBotName = lua_tolstring(pLua, 2, &szNameLen);
	NewBotDescription = lua_tolstring(pLua, 3, &szDescrLen);
	NewBotEmail = lua_tolstring(pLua, 4, &szEmailLen);

	if (szNameLen == 0 || szNameLen > 64 || szDescrLen > 64 || szEmailLen > 64 ||
	        strpbrk(NewBotName, " $|") != NULL || strpbrk(NewBotDescription, "$|") != NULL ||
	        strpbrk(NewBotEmail, "$|") != NULL || HashManager::m_Ptr->FindUser(NewBotName, szNameLen) != NULL)
	{
		lua_settop(pLua, 0);
		return 0;
	}

	bool bBotHaveNewNick = (strcmp(SettingManager::m_Ptr->m_sTexts[SETTXT_BOT_NICK], NewBotName) != 0);
	bool bEnableBot = (lua_toboolean(pLua, 1) == 0 ? false : true);

	bool bRegStateChange = false, bDescriptionChange = false, bEmailChange = false;

	if (SettingManager::m_Ptr->m_bBools[SETBOOL_REG_BOT] != bEnableBot)
	{
		bRegStateChange = true;
	}

	SettingManager::m_Ptr->m_bUpdateLocked = true;

	if (SettingManager::m_Ptr->m_sTexts[SETTXT_BOT_DESCRIPTION] == NULL ||
	        strcmp(SettingManager::m_Ptr->m_sTexts[SETTXT_BOT_DESCRIPTION], NewBotDescription) != 0)
	{
		if (szDescrLen != (size_t)(SettingManager::m_Ptr->m_sTexts[SETTXT_BOT_DESCRIPTION] == NULL ? 0 : -1))
		{
			bDescriptionChange = true;
		}

		SettingManager::m_Ptr->SetText(SETTXT_BOT_DESCRIPTION, NewBotDescription);
	}

	if (SettingManager::m_Ptr->m_sTexts[SETTXT_BOT_EMAIL] == NULL ||
	        strcmp(SettingManager::m_Ptr->m_sTexts[SETTXT_BOT_EMAIL], NewBotEmail) != 0)
	{
		if (szEmailLen != (size_t)(SettingManager::m_Ptr->m_sTexts[SETTXT_BOT_EMAIL] == NULL ? 0 : -1))
		{
			bEmailChange = true;
		}

		SettingManager::m_Ptr->SetText(SETTXT_BOT_EMAIL, NewBotEmail);
	}

	SettingManager::m_Ptr->SetBool(SETBOOL_USE_BOT_NICK_AS_HUB_SEC, (lua_toboolean(pLua, 5) == 0 ? false : true));

	if (SettingManager::m_Ptr->m_bBools[SETBOOL_REG_BOT] == true)
	{
		SettingManager::m_Ptr->m_bUpdateLocked = false;
		SettingManager::m_Ptr->DisableBot((bBotHaveNewNick == true || bEnableBot == false),
		                                  (bRegStateChange == true || bBotHaveNewNick == true || bDescriptionChange == true || bEmailChange == true) ? true : false);
		SettingManager::m_Ptr->m_bUpdateLocked = true;
	}

	SettingManager::m_Ptr->SetBool(SETBOOL_REG_BOT, bEnableBot);

	if (bBotHaveNewNick == true)
	{
		SettingManager::m_Ptr->SetText(SETTXT_BOT_NICK, NewBotName);
	}

	SettingManager::m_Ptr->m_bUpdateLocked = false;

	SettingManager::m_Ptr->UpdateHubSec();
	SettingManager::m_Ptr->UpdateMOTD();
	SettingManager::m_Ptr->UpdateHubNameWelcome();
	SettingManager::m_Ptr->UpdateRegOnlyMessage();
	SettingManager::m_Ptr->UpdateShareLimitMessage();
	SettingManager::m_Ptr->UpdateSlotsLimitMessage();
	SettingManager::m_Ptr->UpdateHubSlotRatioMessage();
	SettingManager::m_Ptr->UpdateMaxHubsLimitMessage();
	SettingManager::m_Ptr->UpdateNoTagMessage();
	SettingManager::m_Ptr->UpdateNickLimitMessage();
	SettingManager::m_Ptr->UpdateBotsSameNick();

	if (SettingManager::m_Ptr->m_bBools[SETBOOL_REG_BOT] == true &&
	        (bRegStateChange == true || bBotHaveNewNick == true || bDescriptionChange == true || bEmailChange == true))
	{
		SettingManager::m_Ptr->UpdateBot((bBotHaveNewNick == true || bRegStateChange == true));
	}

	return 0;
}
//------------------------------------------------------------------------------

static const luaL_Reg SetManRegs[] =
{
	{ "Save", Save },
	{ "GetMOTD", GetMOTD },
	{ "SetMOTD", SetMOTD },
	{ "GetBool", GetBool },
	{ "SetBool", SetBool },
	{ "GetNumber", GetNumber },
	{ "SetNumber", SetNumber },
	{ "GetString", GetString },
	{ "SetString", SetString },
	{ "GetMinShare", GetMinShare },
	{ "SetMinShare", SetMinShare },
	{ "GetMaxShare", GetMaxShare },
	{ "SetMaxShare", SetMaxShare },
	{ "SetHubSlotRatio", SetHubSlotRatio },
	{ "GetOpChat", GetOpChat },
	{ "SetOpChat", SetOpChat },
	{ "GetHubBot", GetHubBot },
	{ "SetHubBot", SetHubBot },
	{ NULL, NULL }
};
//---------------------------------------------------------------------------

#if LUA_VERSION_NUM > 501
int RegSetMan(lua_State * pLua)
{
	luaL_newlib(pLua, SetManRegs);
	return 1;
#else
void RegSetMan(lua_State * pLua)
{
	luaL_register(pLua, "SetMan", SetManRegs);
#endif
}
//---------------------------------------------------------------------------

V1042 This file is marked with copyleft license, which requires you to open the derived source code.