#pragma semicolon 1

#include <sourcemod>
#include <geoip>
#include <multicolors>
#include <clientprefs>
#include <RevEmuAPI>

#pragma newdecls required

char g_sDataFile[128];
char g_sCustomMessageFile[128];

Database g_hDatabase;

Handle g_hCustomMessageFile;
Handle g_hCustomMessageFile2;

bool g_bHideCsays[MAXPLAYERS + 1] = { false, ... };
Handle g_hCookieHideCsays = null;

ConVar g_cvHlstatsServerName;

#define MSGLENGTH 100

//----------------------------------------------------------------------------------------------------
// Purpose:
//----------------------------------------------------------------------------------------------------
public Plugin myinfo = {
	name        = "Connect Announce",
	author      = "Neon + Botox + Dogan",
	description = "Connect Announcer with special features for VIPS",
	version     = "3.0",
	url         = ""
}

//----------------------------------------------------------------------------------------------------
// Purpose:
//----------------------------------------------------------------------------------------------------
public void OnPluginStart()
{
	g_cvHlstatsServerName = CreateConVar("sm_connectannounce_hlstats_server_name", "css-ze", "Hlstats server name to check the rank for");
	AutoExecConfig(true);

	BuildPath(Path_SM, g_sCustomMessageFile, sizeof(g_sCustomMessageFile), "configs/connect_announce/custom-messages.cfg");
	BuildPath(Path_SM, g_sDataFile, sizeof(g_sDataFile), "configs/connect_announce/settings.cfg");

	Database.Connect(OnDatabaseConnect, "hlstatsx");

	RegAdminCmd("sm_joinmsg", Command_JoinMsg, ADMFLAG_CUSTOM1, "Sets a custom message which will be shown upon connecting to the server");
	RegAdminCmd("sm_resetjoinmsg", Command_ResetJoinMsg, ADMFLAG_CUSTOM1, "Resets your custom connect message");

	RegConsoleCmd("sm_hide_connect_csays", OnToggleHideCsays, "Toggle blocking connect csay messages");

	g_hCookieHideCsays = RegClientCookie("csays_blocked", "are csays blocked", CookieAccess_Protected);

	SetCookieMenuItem(MenuHandler_CookieMenu, 0, "Hide Connect Csays");
}

//----------------------------------------------------------------------------------------------------
// Purpose:
//----------------------------------------------------------------------------------------------------
public void OnDatabaseConnect(Database db, const char[] error, any data)
{
	if(db == INVALID_HANDLE || strlen(error) > 0)
	{
		LogError("Error connecting to database: %s", error);
		return;
	}

	g_hDatabase = db;
}

//----------------------------------------------------------------------------------------------------
// Purpose:
//----------------------------------------------------------------------------------------------------
public void ToggleHideCsays(int client)
{
	g_bHideCsays[client] = !g_bHideCsays[client];

	SetClientCookie(client, g_hCookieHideCsays, g_bHideCsays[client] ? "1" : "");
	CPrintToChat(client, "{cyan}[ConnectAnnounce] {white}%s", g_bHideCsays[client] ? "You hid Connect Csay Messages." : "You unhid Connect Csay Messages.");
}

//----------------------------------------------------------------------------------------------------
// Purpose:
//----------------------------------------------------------------------------------------------------
public void OnClientCookiesCached(int client)
{
	char sBuffer[2];

	GetClientCookie(client, g_hCookieHideCsays, sBuffer, sizeof(sBuffer));

	if(sBuffer[0] != '\0')
	{
		g_bHideCsays[client] = true;
	}
	else
	{
		g_bHideCsays[client] = false;
	}
}

//----------------------------------------------------------------------------------------------------
// Purpose:
//----------------------------------------------------------------------------------------------------
public void OnClientDisconnect(int client)
{
	g_bHideCsays[client] = false;
}

//----------------------------------------------------------------------------------------------------
// Purpose:
//----------------------------------------------------------------------------------------------------
public Action OnToggleHideCsays(int client, int args)
{
	ToggleHideCsays(client);
	return Plugin_Handled;
}

//----------------------------------------------------------------------------------------------------
// Purpose:
//----------------------------------------------------------------------------------------------------
public void ShowSettingsMenu(int client)
{
	Menu menu = new Menu(MenuHandler_MainMenu);

	menu.SetTitle("ConnectCsay Settings", client);

	char sBuffer[128];
	Format(sBuffer, sizeof(sBuffer), "Hiding Connect Csays: %s", g_bHideCsays[client] ? "Enabled" : "Disabled");

	menu.AddItem("0", sBuffer);

	menu.ExitBackButton = true;

	menu.Display(client, MENU_TIME_FOREVER);
}

//----------------------------------------------------------------------------------------------------
// Purpose:
//----------------------------------------------------------------------------------------------------
public void MenuHandler_CookieMenu(int client, CookieMenuAction action, any info, char[] buffer, int maxlen)
{
	switch(action)
	{
		case(CookieMenuAction_DisplayOption):
		{
			Format(buffer, maxlen, "ConnectAnnounce", client);
		}
		case(CookieMenuAction_SelectOption):
		{
			ShowSettingsMenu(client);
		}
	}
}

//----------------------------------------------------------------------------------------------------
// Purpose:
//----------------------------------------------------------------------------------------------------
public int MenuHandler_MainMenu(Menu menu, MenuAction action, int client, int selection)
{
	switch(action)
	{
		case(MenuAction_Select):
		{
			switch(selection)
			{
				case(0): ToggleHideCsays(client);
			}

			ShowSettingsMenu(client);
		}
		case(MenuAction_Cancel):
		{
			ShowCookieMenu(client);
		}
		case(MenuAction_End):
		{
			delete menu;
		}
	}
}

//----------------------------------------------------------------------------------------------------
// Purpose:
//----------------------------------------------------------------------------------------------------
public Action Command_JoinMsg(int client, int args)
{
	if (!client)
	{
		ReplyToCommand(client, "[ConnectAnnounce] Cannot use command from server console");
		return Plugin_Handled;
	}

	char sAuth[32];
	GetClientAuthId(client, AuthId_Steam2, sAuth, sizeof(sAuth));

	if (g_hCustomMessageFile != null)
			CloseHandle(g_hCustomMessageFile);

	g_hCustomMessageFile = CreateKeyValues("custom_messages");

	if (!FileToKeyValues(g_hCustomMessageFile, g_sCustomMessageFile))
	{
		SetFailState("[ConnectAnnounce] Config file missing!");
		return Plugin_Handled;
	}

	KvRewind(g_hCustomMessageFile);

	if (args < 1)
	{
		if (KvJumpToKey(g_hCustomMessageFile, sAuth))
		{
			char sCustomMessage[256];
			KvGetString(g_hCustomMessageFile, "message", sCustomMessage, sizeof(sCustomMessage), "");
			if (StrEqual(sCustomMessage, "reset"))
			{
				CPrintToChat(client, "[ConnectAnnounce] No Join Message set! Use sm_joinmsg <your message here> to set one.");
				return Plugin_Handled;
			}
			CPrintToChat(client, "[ConnectAnnounce] Your Join Message is: %s", sCustomMessage);
		}
		else
			CPrintToChat(client, "[ConnectAnnounce] No Join Message set! Use sm_joinmsg <your message here> to set one.");
	}
	else
	{
		char sArg[512];
		int iLength;
		iLength = GetCmdArgString(sArg, sizeof(sArg));

		if(iLength > MSGLENGTH)
		{
			ReplyToCommand(client, "[ConnectAnnounce] Maximum message length is %d characters!", MSGLENGTH);
			return Plugin_Handled;
		}

		StripQuotes(sArg);

		if (KvJumpToKey(g_hCustomMessageFile, sAuth, true))
			KvSetString(g_hCustomMessageFile, "message", sArg);
		else
		{
			SetFailState("[ConnectAnnounce] Could not find/create Key Value!");
			return Plugin_Handled;
		}

		KvRewind(g_hCustomMessageFile);
		KeyValuesToFile(g_hCustomMessageFile, g_sCustomMessageFile);
		CPrintToChat(client, "[ConnectAnnounce] Your Join Message is: %s", sArg);

	}
	KvRewind(g_hCustomMessageFile);
	return Plugin_Handled;
}

//----------------------------------------------------------------------------------------------------
// Purpose:
//----------------------------------------------------------------------------------------------------
public Action Command_ResetJoinMsg(int client, int args)
{
	if (!client)
	{
		ReplyToCommand(client, "[ConnectAnnounce] Cannot use command from server console");
		return Plugin_Handled;
	}

	char sAuth[32];
	GetClientAuthId(client, AuthId_Steam2, sAuth, sizeof(sAuth));

	if (g_hCustomMessageFile != null)
			CloseHandle(g_hCustomMessageFile);

	g_hCustomMessageFile = CreateKeyValues("custom_messages");

	if (!FileToKeyValues(g_hCustomMessageFile, g_sCustomMessageFile))
	{
		SetFailState("[ConnectAnnounce] Config file missing!");
		return Plugin_Handled;
	}

	KvRewind(g_hCustomMessageFile);

	if (KvJumpToKey(g_hCustomMessageFile, sAuth, true))
			KvSetString(g_hCustomMessageFile, "message", "reset");

	KvRewind(g_hCustomMessageFile);

	KeyValuesToFile(g_hCustomMessageFile, g_sCustomMessageFile);

	CPrintToChat(client, "[ConnectAnnounce] Your Join Message got reset.");
	return Plugin_Handled;

}
//----------------------------------------------------------------------------------------------------
// Purpose:
//----------------------------------------------------------------------------------------------------
public void TQueryCB(Handle owner, Handle rs, const char[] error, any data)
{
	int client = 0;

	if ((client = GetClientOfUserId(data)) == 0)
	{
		return;
	}

	int iRank = -1;
	if (SQL_GetRowCount(rs) > 0)
	{
		int iField;

		SQL_FetchRow(rs);
		SQL_FieldNameToNum(rs, "rank", iField);
		iRank = SQL_FetchInt(rs, iField);
		iRank += 1;
	}
	Handle hFile = OpenFile(g_sDataFile, "r");
	static char sRawMsg[301];

	if(hFile != INVALID_HANDLE)
	{
		ReadFileLine(hFile, sRawMsg, sizeof(sRawMsg));
		TrimString(sRawMsg);
		CloseHandle(hFile);
	}
	else
	{
		LogError("[SM] File not found! (configs/ConnectAnnounce/settings.txt)");
		return;
	}

	static char sIP[16];
	static char sAuth[32];
	static char sCountry[32];
	static char sName[128];

	GetClientAuthId(client, AuthId_Steam2, sAuth, sizeof(sAuth));
	GetClientName(client, sName, sizeof(sName));
	AdminId aid;

	if(StrContains(sRawMsg, "{PLAYERTYPE}"))
	{

		aid = GetUserAdmin(client);

		if(GetAdminFlag(aid, Admin_Generic))
		{
			ReplaceString(sRawMsg, sizeof(sRawMsg), "{PLAYERTYPE}", "Admin");
		}
		else if(GetAdminFlag(aid, Admin_Custom1))
		{
			ReplaceString(sRawMsg, sizeof(sRawMsg), "{PLAYERTYPE}", "VIP");
		}
		else if(GetAdminFlag(aid, Admin_Custom6))
		{
			ReplaceString(sRawMsg, sizeof(sRawMsg), "{PLAYERTYPE}", "Member");
		}
		else
		{
			ReplaceString(sRawMsg, sizeof(sRawMsg), "{PLAYERTYPE}", "Player");
		}
	}

	if(StrContains(sRawMsg, "{RANK}"))
	{
		if (iRank != -1)
		{
			char sBuffer[16];
			Format(sBuffer, sizeof(sBuffer), "[#%d] ", iRank);
			ReplaceString(sRawMsg, sizeof(sRawMsg), "{RANK}", sBuffer);
		}
	}

	if(StrContains(sRawMsg, "{NOSTEAM}"))
	{
		if(!RevEmu_IsPlayerSteam(client))
			ReplaceString(sRawMsg, sizeof(sRawMsg), "{NOSTEAM}", " <NoSteam>");
		else
			ReplaceString(sRawMsg, sizeof(sRawMsg), "{NOSTEAM}", "");
	}

	if(StrContains(sRawMsg, "{STEAMID}"))
	{
		ReplaceString(sRawMsg, sizeof(sRawMsg), "{STEAMID}", sAuth);
	}

	if(StrContains(sRawMsg, "{NAME}"))
	{
		ReplaceString(sRawMsg, sizeof(sRawMsg), "{NAME}", sName);
	}

	if(StrContains(sRawMsg, "{COUNTRY}"))
	{
		if(GetClientIP(client, sIP, sizeof(sIP)) && GeoipCountry(sIP, sCountry, sizeof(sCountry)))
		{
			char sBuffer[128];
			Format(sBuffer, sizeof(sBuffer), " from %s", sCountry);
			ReplaceString(sRawMsg, sizeof(sRawMsg), "{COUNTRY}", sBuffer);
		}
		else
			ReplaceString(sRawMsg, sizeof(sRawMsg), "{COUNTRY}", "");
	}

	////////////////////////////////////////////////////////////////////////////////////////////////////////////

	if (!CheckCommandAccess(client, "sm_joinmsg", ADMFLAG_CUSTOM1))
	{
		CPrintToChatAll(sRawMsg);
		return;
	}

	if (g_hCustomMessageFile2 != null)
			CloseHandle(g_hCustomMessageFile2);

	g_hCustomMessageFile2 = CreateKeyValues("custom_messages");

	if (!FileToKeyValues(g_hCustomMessageFile2, g_sCustomMessageFile))
	{
		SetFailState("[ConnectAnnounce] Config file missing!");
		return;
	}

	KvRewind(g_hCustomMessageFile2);

	char sBanned[16];
	char sFinalMessage[512];
	char sCustomMessage[256];

	if (KvJumpToKey(g_hCustomMessageFile2, sAuth))
	{
		KvGetString(g_hCustomMessageFile2, "banned", sBanned, sizeof(sBanned), "");
		KvGetString(g_hCustomMessageFile2, "message", sCustomMessage, sizeof(sCustomMessage), "");
		if(StrEqual(sCustomMessage, "reset") || StrEqual(sBanned, "true"))
		{
			CPrintToChatAll(sRawMsg);
			for(int i = 1; i <= MaxClients; i++)
			{
				if(!g_bHideCsays[i] && IsClientInGame(i))
				{
					PrintCenterText(i, "%s %s %s", "[VIP]", sName, "connected");
				}
			}
		}
		else
		{
			Format(sFinalMessage, sizeof(sFinalMessage), "%s %s", sRawMsg, sCustomMessage);
			CPrintToChatAll(sFinalMessage);
			for(int i = 1; i <= MaxClients; i++)
			{
				if(!g_bHideCsays[i] && IsClientInGame(i))
				{
					CRemoveTags(sCustomMessage, 256);
					PrintCenterText(i, "%s %s %s %s", "[VIP]", sName, "connected", sCustomMessage);
				}
			}
		}
	}
	else
	{
		CPrintToChatAll(sRawMsg);
		for(int i = 1; i <= MaxClients; i++)
		{
			if(!g_bHideCsays[i] && IsClientInGame(i))
			{
				PrintCenterText(i, "%s %s %s", "[VIP]", sName, "connected");
			}
		}
	}
}
//----------------------------------------------------------------------------------------------------
// Purpose:
//----------------------------------------------------------------------------------------------------
public void OnClientPostAdminCheck(int client)
{
	if(IsFakeClient(client))
		return;

	if(g_hDatabase == INVALID_HANDLE)
			return;

	static char sAuth[32];

	GetClientAuthId(client, AuthId_Steam2, sAuth, sizeof(sAuth));
	strcopy(sAuth, sizeof(sAuth), sAuth[8]);

	char sServer[16];
	g_cvHlstatsServerName.GetString(sServer, sizeof(sServer));

	char sQuery[512];
	Format(sQuery, sizeof(sQuery), "SELECT COUNT(*) AS rank FROM hlstats_Players WHERE hlstats_Players.game = '%s' AND hideranking = 0 AND skill > (SELECT skill from hlstats_Players JOIN hlstats_PlayerUniqueIds ON hlstats_Players.playerId = hlstats_PlayerUniqueIds.playerId WHERE uniqueId = '%s' AND hlstats_PlayerUniqueIds.game = '%s')", sServer, sAuth, sServer);
	g_hDatabase.Query(TQueryCB, sQuery, GetClientUserId(client));
}