/*
 * HexTags Plugin.
 * by: Hexah
 * https://github.com/Hexer10/HexTags
 * 
 * Copyright (C) 2017 Mattia (Hexah|Hexer10|Papero)
 *
 * This file is part of the HexTags SourceMod Plugin.
 *
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU General Public License, version 3.0, 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 <sourcemod>
#include <sdktools>
#include <chat-processor>
#include <geoip>
#include <hextags>
#include <sdkhooks>
#include <colorvariables>

#undef REQUIRE_EXTENSIONS
#undef REQUIRE_PLUGIN
#include <cstrike>
#define REQUIRE_EXTENSIONS
#define REQUIRE_PLUGIN

#define PLUGIN_AUTHOR         "Hexah, changed by jenz"
#define PLUGIN_VERSION        "1.208"


#pragma semicolon 1
#pragma newdecls required

Handle fTagsUpdated;

bool bLate;

//deffently needed for checking client pref
KeyValues g_hHextags;
KeyValues g_hIngame;

static char g_sKVPATH[PLATFORM_MAX_PATH]; 
static char g_sKVPATH1[PLATFORM_MAX_PATH]; 
bool g_bHextags[MAXPLAYERS+1];

char clan[1024];
char OriginalClan[512];
char sTags[MAXPLAYERS + 1][eTags][128];
char sNewName[MAXLENGTH_NAME];
char sSecs[16];

int iPoints[MAXPLAYERS];

KeyValues kv;


//vip chattags
char ChatTagchat[MAXPLAYERS];
int i_hasTag[MAXPLAYERS];
//vip chatcolors
char ChatTagColor[MAXPLAYERS];

//token chattags
bool b_tokenTag[MAXPLAYERS+1];
char c_storestats[MAXPLAYERS+1][MAX_NAME_LENGTH];
char c_Chattagtoken[MAXPLAYERS+1][MAX_NAME_LENGTH];

//Plugin infos
public Plugin myinfo = 
{
	name = "hextagsLevels", 
	author = PLUGIN_AUTHOR, 
	description = "Edit Tags & Colors! Modified by jenz", 
	version = PLUGIN_VERSION, 
	url = "https://forums.alliedmods.net/showthread.php?t=303671"
};

//Startup
public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max)
{
	fTagsUpdated = CreateGlobalForward("HexTags_OnTagsUpdated", ET_Ignore, Param_Cell);
	
	//LateLoad
	bLate = late;
	return APLRes_Success;
}

public void OnPluginStart()
{
	SQL_StartConnection();
	CreateConVar("sm_hextags_version", PLUGIN_VERSION, "HexTags plugin version", FCVAR_SPONLY | FCVAR_REPLICATED | FCVAR_NOTIFY);
	
	//Reg Cmds
	RegAdminCmd("sm_reloadtags", Cmd_ReloadTags, ADMFLAG_BAN, "Reload HexTags plugin config");
	RegAdminCmd("sm_hexmysql", cmd_HexmySQL, ADMFLAG_BAN, "test mysql query result");
	RegAdminCmd("sm_chattag", cmd_ChatTag, ADMFLAG_CUSTOM1, "Select chat text");
	RegAdminCmd("sm_chatcolour", cmd_ChatColor, ADMFLAG_CUSTOM1, "Select chat colour");
	RegAdminCmd("sm_chatcolor", cmd_ChatColor, ADMFLAG_CUSTOM1, "Select chat color");
	
	RegConsoleCmd("sm_getteam", Cmd_GetTeam, "Get current team name");
	RegConsoleCmd("sm_tokentag", Cmd_tokenTags, "Choose your tokentag");
	RegConsoleCmd("sm_tokentags", Cmd_tokenTags, "Choose your tokentag");
	RegConsoleCmd("sm_hextags", cmd_HexTags, "Restores clantag (reconnect maybe first)");
	
	//storage of prefference
	g_hHextags = new KeyValues("hexTags");
	BuildPath(Path_SM, g_sKVPATH, sizeof(g_sKVPATH), "data/playerprefs.hextags.txt");
	g_hHextags.ImportFromFile(g_sKVPATH);
	
	g_hIngame = new KeyValues("clanPrefs");
	BuildPath(Path_SM, g_sKVPATH1, sizeof(g_sKVPATH1), "data/playerprefs.ingame.txt");
	g_hIngame.ImportFromFile(g_sKVPATH1);
	

	LoadKv();
		
	//LateLoad
	if (bLate)
	{
		
		for (int i = 1; i <= MaxClients; i++)if (IsClientInGame(i))
		{
			if(IsClientInGame(i) && IsClientAuthorized(i))
			{
				// seems pretty good, only issue right now should be clan getting overwritten by new players
				OnClientPostAdminCheck(i);
				//check preferrence
				static char sAuth[32];
				GetClientAuthId(i, AuthId_Steam2, sAuth, sizeof(sAuth));
				OnClientAuthorized(i, sAuth);
				Frame_SetTag(GetClientUserId(i));
			}
		}
		
	}
}

public void OnPluginEnd()
{
	for(int client = 1; client <= MaxClients; client++)
	{
		if(IsClientInGame(client))
			OnClientDisconnect_Post(client);
	}
}



//Thanks to https://forums.alliedmods.net/showpost.php?p=2573907&postcount=6
public Action OnClientCommandKeyValues(int client, KeyValues TagKv)
{
	char sKey[64];
	if (!TagKv.GetSectionName(sKey, sizeof(sKey)))
		return Plugin_Continue;
		
		
	if (StrEqual(sKey, "ClanTagChanged"))
		{
			Frame_SetTag(GetClientUserId(client));
			RequestFrame(Frame_SetTag, GetClientUserId(client));
		}
	
	return Plugin_Continue;
}


public void Frame_SetTag(any iUserID)
{	
	int client = GetClientOfUserId(iUserID);
	LoadTags(client);
	
	static char SID[32];
	GetClientAuthId(client, AuthId_Steam2, SID, sizeof(SID));
	
	g_hHextags.Rewind();
	if(g_hHextags.JumpToKey(SID, true))
	{
		int disabled = g_hHextags.GetNum("disabled", 0);
		if(!disabled)
		{
			PrintToConsole(client, "disabled false");
			
		
			if (strlen(sTags[client][ScoreTag]) > 0 && IsCS())
			{
				CS_SetClientClanTag(client, sTags[client][ScoreTag]);
			}
		}
	}
	else
	{
		PrintToConsole(client, "[SM]g_hHextags is false");
	}
}


//Commands

public Action Cmd_ReloadTags(int client, int args)
{
	LoadKv();
	for (int i = 1; i <= MaxClients; i++)if (IsClientInGame(i))OnClientPostAdminCheck(i);
	
	ReplyToCommand(client, "[SM] Tags succesfully reloaded!");
	return Plugin_Handled;
}
public Action cmd_HexmySQL (int client, int args)
{
	ReplyToCommand(client, "[SM] Your iPoints are: %d", iPoints[client]);
	PrintToConsole(client, "[SM] sSEC: %s", sSecs);
	return Plugin_Handled;
}



public Action cmd_ChatColor (int client, int args)
{
	if (!IsValidClient(client))
	{
		return Plugin_Continue;
	}
	Menu menu = new Menu(ChatColorMenu_Handler);
	if (CheckCommandAccess(client, "actual vip", ADMFLAG_CUSTOM1, true))
	{
		menu.SetTitle("Chat Colors Menu");
		menu.AddItem("default", "default");
		menu.AddItem("teamcolor", "teamcolor");
		menu.AddItem("red", "red");
		menu.AddItem("lightred", "lightred");
		menu.AddItem("darkred", "darkred");
		menu.AddItem("bluegrey", "bluegrey");
		menu.AddItem("blue", "blue");
		menu.AddItem("darkblue", "darkblue");
		menu.AddItem("purple", "purple");
		menu.AddItem("orchid", "orchid");
		menu.AddItem("yellow", "yellow");
		menu.AddItem("gold", "gold");
		menu.AddItem("lightgreen", "lightgreen");
		menu.AddItem("green", "green");
		menu.AddItem("lime", "lime");
		menu.AddItem("grey", "grey");
		menu.AddItem("grey2", "grey2");
		
		menu.Display(client, 0);
		return Plugin_Handled;
	}
	if (b_tokenTag[client] == false)
	{
		PrintToChat(client, "Check !shop to gain access to !chatcolor");
		return Plugin_Handled;
	}
	if (StrContains(c_storestats[client], "l") >= 0)
	{
		menu.AddItem("teamcolor", "teamcolor");
		menu.AddItem("red", "red");
		menu.AddItem("lightred", "lightred");
	}
	if (StrContains(c_storestats[client], "m") >= 0)
	{
		menu.AddItem("darkred", "darkred");
		menu.AddItem("bluegrey", "bluegrey");
		menu.AddItem("blue", "blue");
	}
	if (StrContains(c_storestats[client], "n") >= 0)
	{
		menu.AddItem("darkblue", "darkblue");
		menu.AddItem("purple", "purple");
		menu.AddItem("orchid", "orchid");
	}
	if (StrContains(c_storestats[client], "o") >= 0)
	{
		menu.AddItem("yellow", "yellow");
	}
	if (StrContains(c_storestats[client], "p") >= 0)
	{
		menu.AddItem("gold", "gold");
	}
	if (StrContains(c_storestats[client], "q") >= 0)
	{
		menu.AddItem("lightgreen", "lightgreen");
	}
	if (StrContains(c_storestats[client], "r") >= 0)
	{
		menu.AddItem("green", "green");
	}
	if (StrContains(c_storestats[client], "s") >= 0)
	{
		menu.AddItem("lime", "lime");
	}
	if (StrContains(c_storestats[client], "t") >= 0)
	{
		menu.AddItem("grey", "grey");
	}
	if (StrContains(c_storestats[client], "u") >= 0)
	{
		menu.AddItem("grey2", "grey2");
	}
	menu.Display(client, 0);
	return Plugin_Handled;
}


public int ChatColorMenu_Handler(Menu menu, MenuAction action, int client, int choice)
{
	if (action == MenuAction_Select)
	{
		char info[32];
		menu.GetItem(choice, info, sizeof(info));
		
		static char SID[32];
		GetClientAuthId(client, AuthId_Steam2, SID, sizeof(SID));
	
		if (StrEqual(info, "default", true))
		{
			PrintToChat(client, "%N Selected Default Color.", client);
			strcopy(ChatTagColor[client], sizeof(ChatTagColor), "");
			Format(ChatTagColor[client], sizeof(ChatTagColor), "default");
			chatcolorMYSQL(client, info);
			return;
		}
		else if (StrEqual(info, "teamcolor", true))
		{
			PrintToChat(client, "%N Selected teamcolor.", client);
			strcopy(ChatTagColor[client], sizeof(ChatTagColor), "");
			Format(ChatTagColor[client], sizeof(ChatTagColor), "teamcolor");
			chatcolorMYSQL(client, info);
			return;
		}
		else if (StrEqual(info, "red", true))
		{
			PrintToChat(client, "%N Selected red Color.", client);
			strcopy(ChatTagColor[client], sizeof(ChatTagColor), "");
			Format(ChatTagColor[client], sizeof(ChatTagColor), "red");
			chatcolorMYSQL(client, info);
			
			return;
		}
		else if (StrEqual(info, "lightred", true))
		{
			PrintToChat(client, "%N Selected lightred Color.", client);
			strcopy(ChatTagColor[client], sizeof(ChatTagColor), "");
			Format(ChatTagColor[client], sizeof(ChatTagColor), "lightred");
			chatcolorMYSQL(client, info);
			
			return;
		}
		else if (StrEqual(info, "darkred", true))
		{
			PrintToChat(client, "%N Selected darkred Color.", client);
			strcopy(ChatTagColor[client], sizeof(ChatTagColor), "");
			Format(ChatTagColor[client], sizeof(ChatTagColor), "darkred");
			chatcolorMYSQL(client, info);
			
			return;
		}
		else if (StrEqual(info, "bluegrey", true))
		{
			PrintToChat(client, "%N Selected bluegrey Color.", client);
			strcopy(ChatTagColor[client], sizeof(ChatTagColor), "");
			Format(ChatTagColor[client], sizeof(ChatTagColor), "bluegrey");
			chatcolorMYSQL(client, info);
			
			return;
		}
		else if (StrEqual(info, "blue", true))
		{
			PrintToChat(client, "%N Selected blue Color.", client);
			strcopy(ChatTagColor[client], sizeof(ChatTagColor), "");
			Format(ChatTagColor[client], sizeof(ChatTagColor), "blue");
			chatcolorMYSQL(client, info);
			
			return;
		}
		else if (StrEqual(info, "darkblue", true))
		{
			PrintToChat(client, "%N Selected darkblue Color.", client);
			strcopy(ChatTagColor[client], sizeof(ChatTagColor), "");
			Format(ChatTagColor[client], sizeof(ChatTagColor), "darkblue");
			chatcolorMYSQL(client, info);
			
			return;
		}
		else if (StrEqual(info, "purple", true))
		{
			PrintToChat(client, "%N Selected purple Color.", client);
			strcopy(ChatTagColor[client], sizeof(ChatTagColor), "");
			Format(ChatTagColor[client], sizeof(ChatTagColor), "purple");
			chatcolorMYSQL(client, info);
			
			return;
		}
		else if (StrEqual(info, "orchid", true))
		{
			PrintToChat(client, "%N Selected orchid Color.", client);
			strcopy(ChatTagColor[client], sizeof(ChatTagColor), "");
			Format(ChatTagColor[client], sizeof(ChatTagColor), "orchid");
			chatcolorMYSQL(client, info);
			
			return;
		}
		else if (StrEqual(info, "yellow", true))
		{
			PrintToChat(client, "%N Selected yellow Color.", client);
			strcopy(ChatTagColor[client], sizeof(ChatTagColor), "");
			Format(ChatTagColor[client], sizeof(ChatTagColor), "yellow");
			chatcolorMYSQL(client, info);
			
			return;
		}
		else if (StrEqual(info, "gold", true))
		{
			PrintToChat(client, "%N Selected gold Color.", client);
			strcopy(ChatTagColor[client], sizeof(ChatTagColor), "");
			Format(ChatTagColor[client], sizeof(ChatTagColor), "gold");
			chatcolorMYSQL(client, info);
			return;
		}
		else if (StrEqual(info, "lightgreen", true))
		{
			PrintToChat(client, "%N Selected lightgreen Color.", client);
			strcopy(ChatTagColor[client], sizeof(ChatTagColor), "");
			Format(ChatTagColor[client], sizeof(ChatTagColor), "lightgreen");
			chatcolorMYSQL(client, info);
			
			return;
		}
		else if (StrEqual(info, "green", true))
		{
			PrintToChat(client, "%N Selected green Color.", client);
			strcopy(ChatTagColor[client], sizeof(ChatTagColor), "");
			Format(ChatTagColor[client], sizeof(ChatTagColor), "green");
			chatcolorMYSQL(client, info);
			return;
		}
		else if (StrEqual(info, "lime", true))
		{
			PrintToChat(client, "%N Selected lime Color.", client);
			strcopy(ChatTagColor[client], sizeof(ChatTagColor), "");
			Format(ChatTagColor[client], sizeof(ChatTagColor), "lime");
			chatcolorMYSQL(client, info);
			
			return;
		}
		else if (StrEqual(info, "grey", true))
		{
			PrintToChat(client, "%N Selected grey Color.", client);
			strcopy(ChatTagColor[client], sizeof(ChatTagColor), "");
			Format(ChatTagColor[client], sizeof(ChatTagColor), "grey");
			chatcolorMYSQL(client, info);
			
			return;
		}
		else if (StrEqual(info, "grey2", true))
		{
			PrintToChat(client, "%N Selected grey2 Color.", client);
			strcopy(ChatTagColor[client], sizeof(ChatTagColor), "");
			Format(ChatTagColor[client], sizeof(ChatTagColor), "grey2");
			chatcolorMYSQL(client, info);
			
			return;
		}
	}
}


public Action cmd_ChatTag (int client, int args)
{
	char inputArgs[250];
	GetCmdArgString(inputArgs, sizeof(inputArgs));
	
	if (StrContains(inputArgs, "'", false) >= 0)
	{
		PrintToChat(client, "[UNLOZE]' is invalid symbol");
		return Plugin_Handled;
	}
	if (StrContains(inputArgs, "reset", false) >= 0)
	{
		i_hasTag[client] = 0;
		chattagMYSQL(client, inputArgs);
		return Plugin_Handled;
	}
	i_hasTag[client] = 1;
	ReplyToCommand(client, "Updated Chattag: %s", inputArgs);
	
	Format(ChatTagchat[client], sizeof(ChatTagchat), inputArgs);
	chattagMYSQL(client, inputArgs);
	return Plugin_Handled;
}

public Action Cmd_tokenTags(int client, int args)
{
	if (b_tokenTag[client] == false)
	{
		PrintToChat(client, "Check !shop to gain access to !tokentag");
		return Plugin_Handled;
	}	
	Menu menu = new Menu(MenuHandler1);
	menu.SetTitle("Unloze Token Tags");
	if (StrContains(c_storestats[client], "l") >= 0)
	{
		menu.AddItem("Rookie", "Rookie");
	}
	if (StrContains(c_storestats[client], "m") >= 0)
	{
		menu.AddItem("MEMBER", "MEMBER");
	}
	if (StrContains(c_storestats[client], "n") >= 0)
	{
		menu.AddItem("SERBIAN", "SERBIAN");
	}
	if (StrContains(c_storestats[client], "o") >= 0)
	{
		menu.AddItem("Overweight Vegetarian", "Overweight Vegetarian");
	}
	if (StrContains(c_storestats[client], "p") >= 0)
	{
		menu.AddItem("русский", "русский");
	}
	if (StrContains(c_storestats[client], "q") >= 0)
	{
		menu.AddItem("NIGGER elites", "NIGGER elites");
	}
	if (StrContains(c_storestats[client], "r") >= 0)
	{
		menu.AddItem("BAGUETTE", "BAGUETTE");
	}
	if (StrContains(c_storestats[client], "s") >= 0)
	{
		menu.AddItem("DANE", "DANE");
	}
	if (StrContains(c_storestats[client], "t") >= 0)
	{
		menu.AddItem("WEEB", "WEEB");
	}
	if (StrContains(c_storestats[client], "u") >= 0)
	{
		menu.AddItem("Nosteam Chad", "Nosteam Chad");
	}
	
	menu.AddItem("Reset", "Reset");
	menu.ExitButton = true;
	menu.Display(client, 0);
	return Plugin_Handled;
}


public int MenuHandler1(Menu menu, MenuAction action, int client, int choice)
{
	if (action == MenuAction_Select)
	{
		char info[32];
		menu.GetItem(choice, info, sizeof(info));
		if (StrEqual(info, "Rookie", true))
		{
			Format(c_Chattagtoken[client], sizeof(c_Chattagtoken), "Rookie");
		}
		else if (StrEqual(info, "MEMBER", true))
		{
			Format(c_Chattagtoken[client], sizeof(c_Chattagtoken), "MEMBER");
		}
		else if (StrEqual(info, "SERBIAN", true))
		{
			Format(c_Chattagtoken[client], sizeof(c_Chattagtoken), "SERBIAN");
		}
		else if (StrEqual(info, "Overweight Vegetarian", true))
		{
			Format(c_Chattagtoken[client], sizeof(c_Chattagtoken), "Overweight Vegetarian");
		}
		else if (StrEqual(info, "Reset", true))
		{
			Format(c_Chattagtoken[client], sizeof(c_Chattagtoken), "Reset");
		}
		PrintToChat(client, "Selected %s as Chattag", info);
		chattagMYSQLTokens(client, info);
	}
}


public Action Cmd_GetTeam(int client, int args)
{
	char sTeam[32];
	GetTeamName(GetClientTeam(client), sTeam, sizeof(sTeam));
	ReplyToCommand(client, "[SM] Current team name: %s", sTeam);
	return Plugin_Handled;
}

public Action cmd_HexTags(int client, int args)
{
	static char SID[32];
	GetClientAuthId(client, AuthId_Steam2, SID, sizeof(SID));
	
	if (strlen(OriginalClan) >= 0)
	{
		g_hHextags.Rewind();
		if(g_hHextags.JumpToKey(SID, true))
		{
			int disabled = g_hHextags.GetNum("disabled", 0);
			if(!disabled)
			{
				//ReplyToCommand(client, "[HexTags] Saved entry for STEAMID({green}%s{default}) {green}successfully{default}.", SID);
				g_hHextags.SetNum("disabled", 1);
				g_hHextags.Rewind();
				g_hHextags.ExportToFile(g_sKVPATH);
				
				g_bHextags[client] = true;
				ReplyToCommand(client, "[Hextags] Hextags disabled - entry saved.");
				
				g_hIngame.Rewind();
				if(g_hIngame.JumpToKey(SID, true))
				{
					g_hIngame.GetString("clan", OriginalClan, sizeof(OriginalClan));	
				}
				
				CS_SetClientClanTag(client, OriginalClan);
				return Plugin_Handled;	
			}
			else
			{
				//CPrintToChat(client, "[StopSound] Entry for STEAMID({green}%s{default}) {green}successfully deleted{default}.", SID);
				g_hHextags.DeleteThis();
				g_hHextags.Rewind();
				g_hHextags.ExportToFile(g_sKVPATH);

				g_bHextags[client] = false;
				ReplyToCommand(client, "[Hextags] Hextags enabled - entry deleted.");
				
				CS_SetClientClanTag(client, sTags[client][ScoreTag]);
				return Plugin_Handled;
			}
		}
		g_hHextags.Rewind();
	}
	
	
	g_bHextags[client] = !g_bHextags[client];
	ReplyToCommand(client, "[Hextags FAILED?] Hextags %s.", g_bHextags[client] ? "disabled" : "enabled");
	return Plugin_Handled;
}


//Events

public void OnClientAuthorized(int client, const char[] auth)
{
	if (IsFakeClient(client) == false)
	{
		//prevents OnClientAuthorized errors in sourcemod logs
		iPoints[client] = CheckMYSQL(client);
		CheckFlagsMYSQL(client);
		TokentagMYSQL(client);
		g_hHextags.Rewind();
		if(KvJumpToKey(g_hHextags, auth, false))
		{
			int disabled = g_hHextags.GetNum("disabled", 0);
			if (disabled)
				g_bHextags[client] = true;
		}
		
		g_hHextags.Rewind();
	}
}

public void OnClientDisconnect_Post(int client)
{
	iPoints[client] = 0;
	g_bHextags[client] = false;
	Format(c_storestats[client], sizeof(c_storestats), "");
	g_hIngame.Rewind();
	g_hIngame.DeleteThis();
	g_hIngame.ExportToFile(g_sKVPATH1);
	
	Format(ChatTagColor[client], sizeof(ChatTagColor), "default");
	Format(c_Chattagtoken[client], sizeof(c_Chattagtoken), "");
}


public void OnClientPostAdminCheck(int client)
{
	if (IsFakeClient(client) == true)
	{
		iPoints[client] = CheckMYSQL(client);
	}
	ReplaceString(sTags[client][ScoreTag], sizeof(sTags[][]), "{country}", "Dream bubbles and the furthest ring"); //sCountry
	i_hasTag[client] = 0;
	b_tokenTag[client] = false;
	if (StrContains(c_storestats[client], "l") >= 0 || StrContains(c_storestats[client], "m") >= 0 || StrContains(c_storestats[client], "n") >= 0)
	{
		b_tokenTag[client] = true;	
	}
	else if (StrContains(c_storestats[client], "o") >= 0 || StrContains(c_storestats[client], "p") >= 0 || StrContains(c_storestats[client], "q") >= 0)
	{
		b_tokenTag[client] = true;	
	}
	else if (StrContains(c_storestats[client], "r") >= 0 || StrContains(c_storestats[client], "s") >= 0 || StrContains(c_storestats[client], "t") >= 0)
	{
		b_tokenTag[client] = true;	
	}
	else if (StrContains(c_storestats[client], "u") >= 0)
	{
		b_tokenTag[client] = true;
	}
	sendMYSQL(client);
}

public Action CP_OnChatMessage(int& author, ArrayList recipients, char[] flagstring, char[] name, char[] message, bool& processcolors, bool& removecolors)
{	
	char sNewMessage[MAXLENGTH_MESSAGE];
	
	for (int i = 0; i <= MaxClients; i++)
	{
		if (IsValidClient(i))
		{
			if (i_hasTag[i] == 1 && (("%N", i) == ("%i", author)))
			{
				static char sAuth[32];
				GetClientAuthId(i, AuthId_Steam2, sAuth, sizeof(sAuth));
				strcopy(ChatTagchat[i], sizeof(ChatTagchat), "");
				strcopy(ChatTagColor[i], sizeof(ChatTagColor), "");
				
				sendMYSQL(i);
				
				Format(sNewName, MAXLENGTH_NAME, "{%s}[%s] %s%s{default}", ChatTagColor[i], ChatTagchat[i], sTags[author][NameColor], name);
				Format(sNewMessage, MAXLENGTH_MESSAGE, "%s%s", sTags[author][ChatColor], message);
				strcopy(name, MAXLENGTH_NAME, sNewName);
				strcopy(message, MAXLENGTH_MESSAGE, sNewMessage);
				processcolors = true;
				removecolors = false;
				
				return Plugin_Changed;
			}
			else if (IsValidClient(i) && i_hasTag[i] == 0 && i == author && b_tokenTag[i] == true && (StrContains(c_Chattagtoken[i], "reset", false) < 0))
			{
				Format(sNewName, MAXLENGTH_NAME, "{%s}[%s] %s%s{default}", ChatTagColor[i], c_Chattagtoken[i], sTags[author][NameColor], name);
				Format(sNewMessage, MAXLENGTH_MESSAGE, "%s%s", sTags[author][ChatColor], message);
				strcopy(name, MAXLENGTH_NAME, sNewName);
				strcopy(message, MAXLENGTH_MESSAGE, sNewMessage);
				processcolors = true;
				removecolors = false;
				
				return Plugin_Changed;
			}
			else if (IsValidClient(i) && i_hasTag[i] == 0 && i == author)
			{
				Format(sNewName, MAXLENGTH_NAME, "{default}[lvl: %s] %s%s{default}", sTags[author][Level], sTags[author][NameColor], name);
				Format(sNewMessage, MAXLENGTH_MESSAGE, "%s%s", sTags[author][ChatColor], message);
				strcopy(name, MAXLENGTH_NAME, sNewName);
				strcopy(message, MAXLENGTH_MESSAGE, sNewMessage);
				processcolors = true;
				removecolors = false;
				
				return Plugin_Changed;
			}
		}
	}
	return Plugin_Changed;
}


//Functions
void LoadKv()
{
	char sConfig[PLATFORM_MAX_PATH];
	BuildPath(Path_SM, sConfig, sizeof(sConfig), "configs/hextags.cfg"); //Get cfg file
	
	if (OpenFile(sConfig, "rt") == null)
		SetFailState("Couldn't find: \"%s\"", sConfig); //Check if cfg exist
	
	if (kv != null)
		delete kv;
		
	kv = new KeyValues("HexTags"); //Create the kv
	
	
	if (!kv.ImportFromFile(sConfig))
		SetFailState("Couldn't import: \"%s\"", sConfig); //Check if file was imported properly
	
	if (!kv.GotoFirstSubKey())
		LogMessage("No entries found in: \"%s\"", sConfig); //Notify that there aren't any entry
}





void LoadTags(int client)
{	
	//Clear the tags when re-checking
	ResetTags(client);
	
	kv.Rewind();
	
	//// GOOD PLACE FOR CS_GetClientClanTag
	CS_GetClientClanTag(client, clan, sizeof(clan));
	g_hIngame.Rewind();
	static char SID[32];
	GetClientAuthId(client, AuthId_Steam2, SID, sizeof(SID));
	if(g_hIngame.JumpToKey(SID, true))
		{
			g_hIngame.SetString("clan", clan);
		}
		
	g_hIngame.ExportToFile(g_sKVPATH1);
	//Check steamid checking
	char steamid[32];
	
	if (!GetClientAuthId(client, AuthId_Steam2, steamid, sizeof(steamid)))
		return;
	
	if (kv.JumpToKey(steamid))
	{
		Call_StartForward(fTagsUpdated);
		Call_PushCell(client);
		Call_Finish();
		GetTags(client);
		return;
	}
	
	steamid[6] = '0'; //Replace the STEAM_1 to STEAM_0
	
	if (kv.JumpToKey(steamid)) //Check again with STEAM_0
	{
		
		GetTags(client);
		Call_StartForward(fTagsUpdated);
		Call_PushCell(client);
		Call_Finish();
		return;
	}
	
	//Start AdminGroups checking
	AdminId admin = GetUserAdmin(client);
	if (admin != INVALID_ADMIN_ID)
	{
		char sGroup[32];
		admin.GetGroup(0, sGroup, sizeof(sGroup));
		Format(sGroup, sizeof(sGroup), "@%s", sGroup);
		
		if (kv.JumpToKey(sGroup))
		{
			GetTags(client);
			Call_StartForward(fTagsUpdated);
			Call_PushCell(client);
			Call_Finish();
			return;
		}
	}
	
	//Start flags checking
	char sFlags[21] = "abcdefghijklmnopqrstz";
	
	for (int i = sizeof(sFlags) - 1; 0 <= i; i--)
	{
		char sFlag[1];
		sFlag[0] = sFlags[i];
		
		if (ReadFlagString(sFlag) & GetUserFlagBits(client))
		{
			if (kv.JumpToKey(sFlag))
			{
				GetTags(client);
				Call_StartForward(fTagsUpdated);
				Call_PushCell(client);
				Call_Finish();
				return;
			}
		}
	}
	
	//start level checking
	bool blvl = true;
	if (blvl)
	{
		int iOldTime;
		bool bReturn;
		
		if (!kv.GotoFirstSubKey())
			return;
		do
		{
			
			kv.GetSectionName(sSecs, sizeof(sSecs));

			if(sSecs[0] != '#') //Check if it's a "level-format"
				continue;
			Format(sSecs, sizeof(sSecs), "%s", sSecs[1]); //Cut the '#' at the start
			
			if(iOldTime >= StringToInt(sSecs)) //Select only the higher time.
				continue;
			
			if (StringToInt(sSecs) <= iPoints[client] / 1000)
			{
				GetTags(client);
				iOldTime = StringToInt(sSecs); //Save the time
				bReturn = true; 
			}
		}
		while (kv.GotoNextKey());
		
		kv.Rewind();
		if (bReturn)
		{
			Call_StartForward(fTagsUpdated);
			Call_PushCell(client);
			Call_Finish();
			return;
		}
	}
	
	//Start team checking
	char sTeam[32];
	int team = GetClientTeam(client);
	GetTeamName(team, sTeam, sizeof(sTeam));
	
	if (kv.JumpToKey(sTeam))
	{
		GetTags(client);
		return;
	}
	
	//Check for 'All' entry
	if (kv.JumpToKey("Default"))
		GetTags(client);
	
	//Call the forward
	Call_StartForward(fTagsUpdated);
	Call_PushCell(client);
	Call_Finish();
}

//Stocks
void GetTags(int client)
{
	kv.GetString("ScoreTag", sTags[client][ScoreTag], sizeof(sTags[][]), "");
	kv.GetString("ChatColor", sTags[client][ChatColor], sizeof(sTags[][]), "");
	kv.GetString("NameColor", sTags[client][NameColor], sizeof(sTags[][]), "{teamcolor}");
	kv.GetString("Level", sTags[client][Level], sizeof(sTags[][]), "");
}

void ResetTags(int client)
{
	strcopy(sTags[client][ScoreTag], sizeof(sTags[][]), "");
	strcopy(sTags[client][ChatColor], sizeof(sTags[][]), "");
	strcopy(sTags[client][NameColor], sizeof(sTags[][]), "");
	strcopy(sTags[client][Level], sizeof(sTags[][]), "");
}

bool IsCS()
{
	EngineVersion engine = GetEngineVersion();
	
	return (engine == Engine_CSGO || engine == Engine_CSS);
}

//API

public int Native_SetClientTag(Handle plugin, int numParams)
{
	int client = GetNativeCell(1);
	
	if (client < 1 || client > MaxClients)
	{
		return ThrowNativeError(SP_ERROR_NATIVE, "Invalid client index (%d)", client);
	}
	if (!IsClientConnected(client))
	{
		return ThrowNativeError(SP_ERROR_NATIVE, "Client %d is not connected", client);
	}
	
	char sTag[32];
	eTags Tag = view_as<eTags>(GetNativeCell(2));
	GetNativeString(3, sTag, sizeof(sTag));
	
	strcopy(sTags[client][Tag], sizeof(sTags[][]), sTag);
	return 0;
}

public int Native_ResetClientTags(Handle plugin, int numParams)
{
	int client = GetNativeCell(1);
	
	if (client < 1 || client > MaxClients)
	{
		return ThrowNativeError(SP_ERROR_NATIVE, "Invalid client index (%d)", client);
	}
	if (!IsClientConnected(client))
	{
		return ThrowNativeError(SP_ERROR_NATIVE, "Client %d is not connected", client);
	}
	
	LoadTags(client);
	return 0;
}

stock bool IsValidClient(int client, bool alive = false, bool bots = false)
{
	if (client > 0 && client <= MaxClients && IsClientInGame(client) && (alive == false || IsPlayerAlive(client)) && (bots == false && !IsFakeClient(client)))
	{
		return true;
	}
	return false;
}

stock void CheckCloseHandle(Handle handle)
{
	if (handle != INVALID_HANDLE)
	{
		CloseHandle(handle);
		handle = INVALID_HANDLE;
	}
}


/*neon idea */
public int CheckMYSQL(int client)
{
	if (client < 1 || client > MaxClients)
	{
		return ThrowNativeError(SP_ERROR_NATIVE, "Invalid client index (%d)", client);
	}
	
	
	char error[255];
	Database db;
	if (SQL_CheckConfig("stats"))
	{
		db = SQL_Connect("stats", true, error, sizeof(error));
	}
	if (db == null)
	{
		PrintToChat(client, "{green}[Unloze] {white}Error! Could not connect to MYSQL-DB!");
		delete db;
		return -1;
	}
	char sSID[64];
	GetClientAuthId(client, AuthId_Steam2, sSID, sizeof(sSID));
	strcopy(sSID, sizeof(sSID), sSID[8]); //matching up with hlstats_PlayerUniqueIds
	char sQuery[255];
	if (IsFakeClient(client) == false)
	{
		Format(sQuery, sizeof(sQuery), "SELECT skill from hlstats_Players JOIN hlstats_PlayerUniqueIds ON hlstats_Players.playerId = hlstats_PlayerUniqueIds.playerId WHERE uniqueId = '%s' AND hlstats_PlayerUniqueIds.game = 'csgo-ze'", sSID);
	}
	else
	{
		Format(sQuery, sizeof(sQuery), "SELECT skill FROM hlstats_Players WHERE playerId = '7715' ");
	}
	
	DBResultSet rs;
	
	if ((rs = SQL_Query(db, sQuery)) == null)
	{
		//PrintToConsole(client, "[Unloze] Failed sQuery: %s", sQuery);
		delete db;
		delete rs;
		return -1;
	}
	//PrintToConsole(client, "[Unloze] Success sQuery: %s", sQuery);
	
	
	int iCollected;
	
	if (!(rs.RowCount > 0))
	{
		iCollected = 0;
	}
	else
	{
		int iField;
		rs.FetchRow();
		rs.FieldNameToNum("collected", iField);
		iCollected = rs.FetchInt(iField);
		if (IsFakeClient(client) == true)
		{
			char tag[64];
			Format(tag, sizeof(tag), "[LVL: %i]", (iCollected / 1000));
			CS_SetClientClanTag(client, tag);
		}
	}
	delete rs;
	delete db;
	return iCollected;
} 


public void sendMYSQL(int client)
{
	char error[255];
	Database db;
	if (SQL_CheckConfig("unloze_chatcsgo"))
	{
		db = SQL_Connect("unloze_chatcsgo", true, error, sizeof(error));
	}
	if (db == null)
	{
		CPrintToChatAll("{green}[Unloze] {white}Error! Could not connect to MYSQL-DB!");
		delete db;
		return;
	}
	
	char sQuery[255];
	char sSID[64];
	GetClientAuthId(client, AuthId_Steam2, sSID, sizeof(sSID));
	Format(sQuery, sizeof(sQuery), "SELECT chattag, chatcolor FROM `unloze_csgochat` WHERE steam_id = '%s'", sSID);
	DBResultSet rs;
	
	if ((rs = SQL_Query(db, sQuery)) == null)
	{
		
		delete db;
		delete rs;
		return;
	}
	
	Format(ChatTagColor[client], sizeof(ChatTagColor), "default");
	if (!(rs.RowCount > 0))
	{
		Format(ChatTagchat[client], sizeof(ChatTagchat), "Place holder");
	}
	else if (rs.FetchRow()) 
	{	
		rs.FetchString(0, ChatTagchat[client], MAX_NAME_LENGTH);
		rs.FetchString(1, ChatTagColor[client], MAX_NAME_LENGTH);
		if (CheckCommandAccess(client, "actual vip", ADMFLAG_CUSTOM1, true))
		{
   			i_hasTag[client] = 1;
		} 
		else
		{
			i_hasTag[client] = 0;
		}
		if (StrContains(ChatTagchat[client], "reset", false) >= 0)
		{
			i_hasTag[client] = 0;
		}
	}
	
	delete rs;
	delete db;
	return;
}

public void chatcolorMYSQL(int client, const char[] inputarg)
{
	char error[255];
	Database db;
	if (SQL_CheckConfig("unloze_chatcsgo"))
	{
		db = SQL_Connect("unloze_chatcsgo", true, error, sizeof(error));
	}
	if (db == null)
	{
		CPrintToChatAll("{green}[Unloze] {white}Error! Could not connect to MYSQL-DB!");
		delete db;
		return;
	}
	
	char sQuery[255];
	char sSID[64];
	GetClientAuthId(client, AuthId_Steam2, sSID, sizeof(sSID));
	Format(sQuery, sizeof(sQuery), "INSERT INTO `unloze_csgochat` (`steam_id`, `chatcolor`) VALUES ('%s','%s') ON DUPLICATE KEY UPDATE `chatcolor` = '%s'", sSID, inputarg, inputarg);
	SQL_TQuery(db, DummyCallbackSimple, sQuery);
	delete db;
}

public void chattagMYSQL(int client, const char[] inputarg)
{
	char error[255];
	Database db;
	if (SQL_CheckConfig("unloze_chatcsgo"))
	{
		db = SQL_Connect("unloze_chatcsgo", true, error, sizeof(error));
	}
	if (db == null)
	{
		CPrintToChatAll("{green}[Unloze] {white}Error! Could not connect to MYSQL-DB!");
		delete db;
		return;
	}
	
	char sQuery[255];
	char sSID[64];
	GetClientAuthId(client, AuthId_Steam2, sSID, sizeof(sSID));
	Format(sQuery, sizeof(sQuery), "INSERT INTO `unloze_csgochat` (`steam_id`, `chattag`) VALUES ('%s','%s') ON DUPLICATE KEY UPDATE `chattag` = '%s'", sSID, inputarg, inputarg);
	SQL_TQuery(db, DummyCallbackSimple, sQuery);
	delete db;
}

public void chattagMYSQLTokens(int client, const char[] info)
{
	char error[255];
	Database db;
	if (SQL_CheckConfig("unloze_chatcsgo"))
	{
		db = SQL_Connect("unloze_chatcsgo", true, error, sizeof(error));
	}
	if (db == null)
	{
		CPrintToChatAll("{green}[Unloze] {white}Error! Could not connect to MYSQL-DB!");
		delete db;
		return;
	}
	
	char sQuery[255];
	char sSID[64];
	GetClientAuthId(client, AuthId_Steam2, sSID, sizeof(sSID));
	Format(sQuery, sizeof(sQuery), "INSERT INTO `unloze_csgochattokens` (`steam_id`, `chattag`) VALUES ('%s','%s') ON DUPLICATE KEY UPDATE `chattag` = '%s'", sSID, info, info);
	SQL_TQuery(db, DummyCallbackSimple, sQuery);
	delete db;
}

public void SQL_StartConnection()
{
	char error[255];
	Database db;
	if (SQL_CheckConfig("unloze_csgochat")) 
	{
		db = SQL_Connect("unloze_csgochat", true, error, sizeof(error));
	}
	if (db == null)
	{
		CPrintToChatAll("{green}[Unloze] {white}Error! Could not connect to MYSQL-DB!");
		delete db;
		return;
	}
	//create tables
	char sQuery[255];
	Format(sQuery, sizeof(sQuery), "CREATE TABLE IF NOT EXISTS `unloze_csgochat` (`steam_id` VARCHAR(254) NOT NULL, `chattag` VARCHAR(254) NOT NULL, `chatcolor` VARCHAR(254) NOT NULL, PRIMARY KEY (`steam_id`))");
	SQL_TQuery(db, DummyCallbackSimple, sQuery);
	
	Format(sQuery, sizeof(sQuery), "CREATE TABLE IF NOT EXISTS `unloze_csgochattokens` (`steam_id` VARCHAR(254) NOT NULL, `chattag` VARCHAR(254) NOT NULL, PRIMARY KEY (`steam_id`))");
	SQL_TQuery(db, DummyCallbackSimple, sQuery);
	
	delete db;
}

public void CheckFlagsMYSQL(int client)
{
	char error[255];
	Database db; 
	//the points not related to hlstats are stored together with tracer prefferences but have
	//their own table
	if (SQL_CheckConfig("unloze_tracerpref"))
	{
		db = SQL_Connect("unloze_tracerpref", true, error, sizeof(error));
	}
	if (db == null)
	{
		PrintToChat(client, "{green}[Unloze] {white}Error! Could not connect to MYSQL-DB!");
		delete db;
		return;
	}
	char sSID[64];
	GetClientAuthId(client, AuthId_Steam2, sSID, sizeof(sSID));
	char sQuery[512];
	Format(sQuery, sizeof(sQuery), "SELECT storestats FROM `unloze_zonepoints` WHERE `steam_id` = '%s'", sSID);
	
	DBResultSet rs;
	
	if ((rs = SQL_Query(db, sQuery)) == null)
	{	
		delete db;
		delete rs;
		return;
	}
	
	if (rs.FetchRow())
	{
		SQL_FetchString(rs, 0, c_storestats[client], MAX_NAME_LENGTH);
	}
	delete rs;
	delete db;
} 


public void TokentagMYSQL(int client)
{
	char error[255];
	Database db; 
	if (SQL_CheckConfig("unloze_chatcsgo"))
	{
		db = SQL_Connect("unloze_chatcsgo", true, error, sizeof(error));
	}
	if (db == null)
	{
		CPrintToChatAll("{green}[Unloze] {white}Error! Could not connect to MYSQL-DB!");
		delete db;
		return;
	}
	
	char sSID[64];
	GetClientAuthId(client, AuthId_Steam2, sSID, sizeof(sSID));
	char sQuery[512];
	Format(sQuery, sizeof(sQuery), "SELECT chattag FROM `unloze_csgochattokens` WHERE `steam_id` = '%s'", sSID);
	
	DBResultSet rs;
	
	if ((rs = SQL_Query(db, sQuery)) == null)
	{	
		delete db;
		delete rs;
		return;
	}
	
	if (rs.FetchRow())
	{
		SQL_FetchString(rs, 0, c_Chattagtoken[client], MAX_NAME_LENGTH);
	}
	delete rs;
	delete db;
} 

public void DummyCallbackSimple(Handle hOwner, Handle hChild, const char[] err, DataPack pack1)
{
	if (hOwner == null || hChild == null)
	{
		LogError("Query error. (%s)", err);
	}
}