--[[
	menu_plugins/OubHack/oubhack_lib.lua
	Oubliette | (STEAM_0:1:34029133)
	===DStream===
]]

/******************************************************************************
 .d88888b.  888     888 888888b.   888    888        d8888  .d8888b.  888    d8P  
d88P" "Y88b 888     888 888  "88b  888    888       d88888 d88P  Y88b 888   d8P   
888     888 888     888 888  .88P  888    888      d88P888 888    888 888  d8P    
888     888 888     888 8888888K.  8888888888     d88P 888 888        888d88K     
888     888 888     888 888  "Y88b 888    888    d88P  888 888        8888888b    
888     888 888     888 888    888 888    888   d88P   888 888    888 888  Y88b   
Y88b. .d88P Y88b. .d88P 888   d88P 888    888  d8888888888 Y88b  d88P 888   Y88b  
 "Y88888P"   "Y88888P"  8888888P"  888    888 d88P     888  "Y8888P"  888    Y88b 
 By Oubliete and UnknownAlias
*******************************************************************************/
-- Library
function player.FindByName(name)
	local found = nil;
	for _,ply in pairs(player.GetAll()) do
		if ply:Nick() == name then
			found = ply;
		end
	end
	if !found then 
		found = oubhack:FindNPCByName(name)
	end
	return found;
end

function oubhack:GetNPCS()
	local tbl = {}
	for k,v in pairs(ents.GetAll()) do
		if v:IsNPC() then
			tbl[#tbl+1] = v;
		end
	end
	return tbl;
end

function oubhack:FindNPCByName(name)
	for _,npc in pairs(self:GetNPCS()) do
		if npc:Nick() == name then
			return npc;
		end
	end
end

function player.GetAllDM()
	local tbl = {};
	for k,v in pairs(player.GetAll()) do
		if v!=LocalPlayer() then
			tbl[#tbl+1] = v;
		end
	end
	return tbl;
end

function oubhack:AddFriend(ply)
	if ply==LocalPlayer() then return false end;
	if not ply then return false end
	--if !ply:IsPlayer() or !ply:IsValid() then return false end;
	if not table.HasValue(self.friends,ply) then
		self.friends[#self.friends+1] = ply;
		return true;
	end
end

function oubhack:RemoveFriend(ply)
	if ply==LocalPlayer() then return false end;
	if not ply then return false end
	--if !ply:IsPlayer() or !ply:IsValid() then return false end;
	if table.HasValue(self.friends,ply) then
		for k,v in pairs(self.friends) do
			if v == ply then
				table.remove(self.friends,k)
			end
		end
		return true;
	end
end

function oubhack:GetPossibleTargets()
	local plys = player.GetAllDM()
	local npcs = self:GetNPCS()
	table.Add(plys,npcs)
	return self:SanatiseEntities(plys);
end

function oubhack:GetTargets()
	local tbl = {}
	for k,v in pairs(ents.GetAll()) do
		if v:IsPlayer() and self.ingore_admins and v:IsAdmin() then v.adm = true else v.adm = false end
		if v:IsPlayer() and self.ingore_superadmins and v:IsSuperAdmin() then v.adm = true else v.adm = false end
		if v!=LocalPlayer() and !v	.adm then
			if self.target_npcs and self.target_bots then
				if (v:IsPlayer() and v:Alive()) or v:IsNPC() then
					if !table.HasValue(self.friends,v) then
						tbl[#tbl+1] = v;
					end
				end
			elseif (!self.target_npcs and self.target_bots) then
				if (v:IsPlayer() and v:Alive()) then
					if !table.HasValue(self.friends,v) then
						tbl[#tbl+1] = v;
					end
				end
			elseif (!self.target_bots and self.target_npcs) then
				if (v:IsPlayer() and v:Alive() and !v:IsBot()) or (v:IsNPC()) then
					if !table.HasValue(self.friends,v) then
						tbl[#tbl+1] = v;
					end
				end
			else
				if (v:IsPlayer() and v:Alive()) then
					if !table.HasValue(self.friends,v) then
						tbl[#tbl+1] = v;
					end
				end
			end
		end
	end
	
	return self:SanatiseEntities(tbl);
	
end

function oubhack:GetFriends()
	return self.friends or {};
end

function _R.Entity:Nick()
	if self:IsPlayer() then
		return self:Name()
	else
		return tostring(self)
	end
end

function oubhack:IsFriend(ply)
	if not ply then return false end
	return table.HasValue(self.friends,ply)
end

function oubhack:IsSteamFriend(ply)
	if not ply then return false end;
	if not ply:IsPlayer() then return false end;
	return ply:GetFriendStatus() == "friend";
end
	
function oubhack:GetUserGroup(ply)
	if not ply then return "Invalid entity" end
	if not ply:IsPlayer() then return "NPC" end
	if ply:IsAdmin() then
		return "Admin";
	elseif ply:IsSuperAdmin() then
		return "Super-Admin";
	else
		return "Player";
	end
end

function string.BoolToYN(bool)
	if bool then
		return "Yes";
	else
		return "No";
	end
end
	
function string.ToBool(str)
	if str == "true" then
		return true;
	elseif str == "false" then
		return false;
	else
		return nil;
	end
end

function oubhack:SanatiseEntities(tbl)
	local stbl = tbl;

	for k,v in pairs(tbl) do
		if (!v or !v:IsValid() or !ValidEntity(v)) or (v:GetMoveType() == 0 or v:GetMoveType() == 5) then -- NPC's after dieing become null entities, that for some reason show as valid.
			table.remove(stbl,k)
		end
	end

	return stbl;
end

function oubhack:CreateGroup(name)
	if not name then return false end
	self:CheckGroups()
	for k,v in pairs(self.groups) do
		if v.Name == name then 
			return false
		end
	end
	self.groups[#self.groups+1] = {Name=name,Mbrs={},target=false}
	return true;
end

function oubhack:RemoveGroup(name)
	if not name then return false end
	self:CheckGroups()
	for k,v in pairs(self.groups) do
		for k,v in pairs(v.Mbrs) do v:SetGroup("None") end
		if v.Name == name then
			table.remove(self.groups,k)
		end
	end
end

function oubhack:GroupPlayer(ply,name)
	if !ply or !name then return false end
	self:CheckGroups()
	for k,v in pairs(self.groups) do
		for _,pl in pairs(v.Mbrs) do
			if pl == ply then
				table.remove(v.Mbrs,_)
			end
		end
	end
	for k,v in pairs(self.groups) do
		if v.Name == name and ply:IsValid() then
			v.Mbrs[#v.Mbrs+1] = ply;
		end
	end
end

function oubhack:GetGroup(ply)
	if not ply then return false end
	self:CheckGroups()
	for k,v in pairs(self.groups) do
		for _,pl in pairs(v.Mbrs) do
			if pl == ply then 
				return v;
			end
		end
	end
	return self.groups[1];
end

function oubhack:CheckGroups()
	for k,v in pairs(self.groups) do
		for _,ply in pairs(v.Mbrs) do
			if !ply:IsValid() or ply:GetMoveType() == 5 or ply:GetMoveType() == 0 then
				table.remove(v.Mbrs,_)
			end
		end
	end
end

local DermaControls = {}
function oubhack:RegisterVgui(name,mtable,base)
	if !name or !mtable then return false end;
	mtable.Base = base or "Panel";
	DermaControls[name] = mtable; 
	return mtable;
end

function oubhack:CreateVgui(classname,parent,name)

	if DermaControls[classname] then -- I'm using this for everything. It replaces vgui.Create, it has to do the same thing.
		local mtbl = DermaControls[classname];
		
		local panel = self:CreateVgui(mtbl.Base,parent,name);
		
		table.Merge( panel:GetTable(), mtbl );
		panel.ClassName = classname;
		panel.BaseClass = DermaControls[mtbl.Base];
		if (panel.Init) then
			local stat,error = pcall(panel.Init, panel)
			if not stat then ErrorNoHalt( "Who the fuck? Don't create dumbass panels please. : "..error.."\n" ) return nil end
		end
		panel:Prepare()
		return panel;
	end
	return vgui.Create(classname,parent,name)
end
