#pragma semicolon 1

#include <sourcemod>
#include <cstrike>
#include <multicolors>
#include <zombiereloaded>
#include <basecomm>
#include <sdktools>

bool g_bStuckRequestAuto;

int g_iStuckRequester;

float g_fStuckRequestTimer;

Handle StuckRequestTimer;

public Plugin myinfo =
{
	name = "Stuck Request",
	author = "Dogan",
	description = "Very simple Plugin to handle Humans being stuck in ZE",
	version = "1.0.0",
	url = ""
};

public void OnPluginStart()
{
	RegConsoleCmd("sm_stuck", Command_StuckRequest, "Send a request to admins for being stuck");
	RegConsoleCmd("sm_zstuck", Command_StuckRequest, "Send a request to admins for being stuck");
	RegAdminCmd("sm_acc", Command_AcceptRequest, ADMFLAG_GENERIC, "Accepts the current stuck-request");
	RegAdminCmd("sm_deny", Command_DenyRequest, ADMFLAG_GENERIC, "Denies the current stuck-request");

	HookEvent("player_death", OnPlayerDeath);

	ConVar cvar;
	HookConVarChange((cvar = CreateConVar("sm_stuckrequest_auto", "1", "1 = automatically accept stuck requests when timer runs out, 0 = decline by default", FCVAR_NONE, true, 0.0, true, 1.0)), g_cvStuckRequestAuto);
	g_bStuckRequestAuto = cvar.BoolValue;
	HookConVarChange((cvar = CreateConVar("sm_stuckrequest_timer", "6.0", "timer until a stuck request runs out")), g_cvStuckRequestTimer);
	g_fStuckRequestTimer = cvar.FloatValue;
	delete cvar;

	AutoExecConfig(true, "plugin.StuckRequest");

	g_iStuckRequester = 0;
}

public void g_cvStuckRequestAuto(ConVar convar, const char[] oldValue, const char[] newValue)
{
	g_bStuckRequestAuto = convar.BoolValue;
}

public void g_cvStuckRequestTimer(ConVar convar, const char[] oldValue, const char[] newValue)
{
	g_fStuckRequestTimer = convar.FloatValue;
}

public Action OnPlayerDeath(Event event, const char[] name, bool dontBroadcast)
{
	int client = GetClientOfUserId(GetEventInt(event, "userid"));

	char sWepName[64];
	GetEventString(event, "weapon", sWepName, sizeof(sWepName));

	if(g_iStuckRequester == client && !StrEqual(sWepName, "knife"))
	{
		CPrintToChat(client, "{lightgreen}[StuckRequest]{yellow} You died while the Request was pending! Request aborted.");

		for(int i = 1; i <= MaxClients; i++)
		{
			if(IsAdmin(i))
			{
				CPrintToChat(i, "{lightgreen}[StuckRequest]{yellow} %N died while the Request was pending! Request aborted.", g_iStuckRequester);
			}
		}

		g_iStuckRequester = 0;
		KillTimer(StuckRequestTimer);
		StuckRequestTimer = INVALID_HANDLE;
	}
}

public void OnClientDisconnect(int client)
{
	if(g_iStuckRequester == client)
	{
		for(int i = 1; i <= MaxClients; i++)
		{
			if(IsAdmin(i))
			{
				CPrintToChat(i, "{lightgreen}[StuckRequest]{yellow} %N left the Server while having a Request open. Request aborted.", g_iStuckRequester);
			}
		}

		g_iStuckRequester = 0;
		KillTimer(StuckRequestTimer);
		StuckRequestTimer = INVALID_HANDLE;
	}
}
public Action Command_StuckRequest(int client, int args)
{
	if(client == 0)
	{
		ReplyToCommand(client, "[SM] Cannot use this from Console.");
		return Plugin_Handled;
	}

	if(BaseComm_IsClientGagged(client))
	{
		ReplyToCommand(client, "{lightgreen}[StuckRequest]{yellow} Cannot use this while being gagged.");
		return Plugin_Handled;
	}

	if(g_iStuckRequester == client)
	{
		CReplyToCommand(client, "{lightgreen}[StuckRequest]{yellow} Your Request is pending!");
		return Plugin_Handled;
	}

	if(g_iStuckRequester != 0)
	{
		CReplyToCommand(client, "{lightgreen}[StuckRequest]{yellow} Another Request is pending! Try again in couple seconds.");
		return Plugin_Handled;
	}

	if(!IsPlayerAlive(client))
	{
		CReplyToCommand(client, "{lightgreen}[StuckRequest]{yellow} Cannot use this while being dead.");
		return Plugin_Handled;
	}

	if(ZR_IsClientZombie(client))
	{
		CReplyToCommand(client, "{lightgreen}[StuckRequest]{yellow} This feature is only available for Humans! Use !ztele as Zombie.");
		return Plugin_Handled;
	}

	if(IsAdmin(client))
	{
		CReplyToCommand(client, "{lightgreen}[StuckRequest]{yellow} Don't be silly! Teleport yourself.");
		return Plugin_Handled;
	}

	CReplyToCommand(client, "{lightgreen}[StuckRequest]{yellow} Sent your Request to Admins!");
	g_iStuckRequester = client;
	SendRequestToAdmin(g_iStuckRequester);
	StuckRequestTimer = CreateTimer(g_fStuckRequestTimer, OnStuckRequest);

	return Plugin_Handled;
}

public Action OnStuckRequest(Handle timer)
{
	if(g_bStuckRequestAuto)
	{
		if(ZR_IsClientZombie(g_iStuckRequester))
			ZR_HumanClient(g_iStuckRequester, false, false);

		int iRandomHuman = 0;
		int PotentialTPCount;
		int PotentialTPClient[64];

		for(int i = 1; i <= MaxClients; i++)
		{
			if(IsClientInGame(i) && !IsFakeClient(i) && IsPlayerAlive(i) && ZR_IsClientHuman(i) && i != g_iStuckRequester)
			{
				PotentialTPClient[PotentialTPCount] = i;
				PotentialTPCount++;
			}
		}

		if(PotentialTPCount < 1)//round ended meanwhile or no humans
		{
			CPrintToChat(g_iStuckRequester, "{lightgreen}[StuckRequest]{yellow} Round ended while the Request was pending! Request aborted.");

			g_iStuckRequester = 0;

			for(int i = 1; i <= MaxClients; i++)
			{
				if(IsAdmin(i))
				{
					CPrintToChat(i, "{lightgreen}[StuckRequest]{yellow} Round ended while the Request was pending! Request aborted.");
				}

			}

			return Plugin_Handled;
		}

		iRandomHuman = PotentialTPClient[GetRandomInt(0, PotentialTPCount - 1)];

		float vecTargetPos[3];
		GetClientAbsOrigin(iRandomHuman, vecTargetPos);
		TeleportEntity(g_iStuckRequester, vecTargetPos, NULL_VECTOR, NULL_VECTOR);

		CPrintToChat(g_iStuckRequester, "{lightgreen}[StuckRequest]{yellow} Request accepted and teleported to a random Human.");
		LogAction(0, -1, "[StuckRequest] Automatically accepted Stuck-Request of %N.", g_iStuckRequester);
		LogToFile("addons/sourcemod/logs/stuckresquests.log", "Automatically accepted Stuck-Request of %N.", g_iStuckRequester);

		for(int i = 1; i <= MaxClients; i++)
		{
		if(IsAdmin(i))
			{
				CPrintToChat(i, "{lightgreen}[StuckRequest]{yellow} Automatically accepted Stuck-Request of %N, because timer ran out.", g_iStuckRequester);
			}
		}
	}
	else
	{
		CPrintToChat(g_iStuckRequester, "{lightgreen}[StuckRequest]{yellow} Request left open. Probably Admins AFK. Sorry!");
		for(int i = 1; i <= MaxClients; i++)
		{
			if(IsAdmin(i))
			{
				CPrintToChat(i, "{lightgreen}[StuckRequest]{yellow} Automatically denied Stuck-Request of %N, because timer ran out.", g_iStuckRequester);
			}
		}
	}

	g_iStuckRequester = 0;

	return Plugin_Handled;
}

public Action SendRequestToAdmin(int client)
{
	for(int i = 1; i <= MaxClients; i++)
	{
		if(IsAdmin(i))
		{
			CPrintToChat(i, "{lightgreen}[StuckRequest]{yellow} %N sent a Request! Type {red}!acc{white} to accept or {red}!deny{white} to deny.", client);
		}
	}

	return Plugin_Handled;
}

public Action Command_AcceptRequest(int client, int args)
{
	if(g_iStuckRequester == 0)
	{
		CReplyToCommand(client, "{lightgreen}[StuckRequest]{yellow} There is no Request pending!");
		return Plugin_Handled;
	}

	if(ZR_IsClientZombie(g_iStuckRequester))
		ZR_HumanClient(g_iStuckRequester, false, false);

	int iRandomHuman = 0;
	int PotentialTPCount;
	int PotentialTPClient[64];

	for(int i = 1; i <= MaxClients; i++)
	{
		if(IsClientInGame(i) && !IsFakeClient(i) && IsPlayerAlive(i) && ZR_IsClientHuman(i) && i != g_iStuckRequester)
		{
			PotentialTPClient[PotentialTPCount] = i;
			PotentialTPCount++;
		}
	}

	if(PotentialTPCount < 1)//round ended meanwhile or no humans
	{
		CPrintToChat(g_iStuckRequester, "{lightgreen}[StuckRequest]{yellow} Round ended while the Request was pending! Request aborted.");

		g_iStuckRequester = 0;
		KillTimer(StuckRequestTimer);
		StuckRequestTimer = INVALID_HANDLE;

		for(int i = 1; i <= MaxClients; i++)
		{
			if(IsAdmin(i))
			{
				CPrintToChat(i, "{lightgreen}[StuckRequest]{yellow} Round ended while the Request was pending! Request aborted.");
			}
		}

		return Plugin_Handled;
	}

	iRandomHuman = PotentialTPClient[GetRandomInt(0, PotentialTPCount - 1)];

	float vecTargetPos[3];
	GetClientAbsOrigin(iRandomHuman, vecTargetPos);
	TeleportEntity(g_iStuckRequester, vecTargetPos, NULL_VECTOR, NULL_VECTOR);

	CPrintToChat(g_iStuckRequester, "{lightgreen}[StuckRequest]{yellow} Request accepted and teleported to a random Human.");
	LogAction(client, -1, "[StuckRequest] %N accepted Stuck-Request of %N.", client, g_iStuckRequester);

	for(int i = 1; i <= MaxClients; i++)
	{
		if(IsAdmin(i))
		{
			CPrintToChat(i, "{lightgreen}[StuckRequest]{yellow} %N accepted the Request of %N.", client, g_iStuckRequester);
		}
	}

	g_iStuckRequester = 0;
	KillTimer(StuckRequestTimer);
	StuckRequestTimer = INVALID_HANDLE;

	return Plugin_Handled;
}

public Action Command_DenyRequest(int client, int args)
{
	if(g_iStuckRequester == 0)
	{
		CReplyToCommand(client, "{lightgreen}[StuckRequest]{yellow} There is no Request pending!");
		return Plugin_Handled;
	}

	CPrintToChat(g_iStuckRequester, "{lightgreen}[StuckRequest]{yellow} Admins denied your Request.");

	for(int i = 1; i <= MaxClients; i++)
	{
		if(IsAdmin(i))
		{
			CPrintToChat(i, "{lightgreen}[StuckRequest]{yellow} %N denied the Request of %N.", client, g_iStuckRequester);
		}
	}

	g_iStuckRequester = 0;
	KillTimer(StuckRequestTimer);
	StuckRequestTimer = INVALID_HANDLE;

	return Plugin_Handled;
}

static stock bool IsAdmin(int client)
{
	if (client > 0 && client <= MaxClients && IsClientInGame(client) && CheckCommandAccess(client, "", ADMFLAG_GENERIC))
		return true;
	else
		return false;
}