--------------------- Polite Notice ---------------------
-- YaLB was created by Daniel Astbury (jnz)            --
-- The source is avaliable to anyone, however          --
-- please do not take it can claim it yours.           --
-- Please follow my example and release your own.      --
-----------------------Thank you-------------------------


Players = {}
Player = {Nick = "", Version = 0.0, JoinMsg = "", LastSeen = 0, Status = "", Serial = "", IP = "", Host = "", Muted = 0, ShowPM = false, Shunned = false, Points = nil}
    
function Player:new (o)
	o = o or {}
	setmetatable(o, self)	
	self.__index = self
	return o
end

function db_Seen_Callback(userdata, argc, data, column)
	local p = Players[tonumber(userdata)]
	for k,v in pairs(data) do
		if column[k] == "LastSeen" then
			p.LastSeen = v
		end
		
		if column[k] == "JoinMsg" then
			p.JoinMsg = v
		end
		
	end	
end

function db_Points_Callback(userdata, argc, data, column)
	local p = Players[tonumber(userdata)]
	p.Points = tonumber(data[1])
end


function Add_Player(PlayerId)
	local p = Player:new()
	p.Nick = Get_Player_Name_By_ID(PlayerId)
	p.IP = Get_IP_Address(PlayerId)
	p.Host = ""
	p.Serial = ""
	p.Muted = 0
	p.ShowPM = false
	p.Shunned = false
	Players[PlayerId] = p
	
	
	db:Query(tostring(PlayerId), "db_Seen_Callback", string.format("SELECT JoinMsg,LastSeen FROM Players WHERE Nick = '%s';", p.Nick))
	if p.LastSeen == 0 then
		db:Query("", "", string.format("INSERT INTO Players(Nick, LastSeen) VALUES('%s', '%d');", p.Nick, os.time(os.date("*t"))))
	elseif p.JoinMsg ~= "" then
		Console_Input(string.format("msg [%s]: %s", p.Nick, p.JoinMsg))
	end
	
	db:Query(tostring(PlayerId), "db_Points_Callback", string.format("SELECT Points FROM Ranks WHERE Nick = '%s';", p.Nick))
	if p.Points == nil then
		p.Points = 0
		db:Query("", "", string.format("INSERT INTO Ranks(Nick, Points) VALUES('%s', '%d');", p.Nick, 0))
	end
	
	local RankResult = nil
	function rank_db_callback(userdata, argc, data, columns)
		RankResult = data[1]
	end
	
	db:Query("", "rank_db_callback", string.format("SELECT COUNT(*) FROM Ranks WHERE Points >= (SELECT Points FROM Ranks WHERE Nick = '%s');", string.gsub(p.Nick, "'", "")))
	
	if RankResult ~= nil then
		local postfix = "th"
		local num = tonumber(RankResult) % 10
		if num == 1 then
			postfix = "st"
		elseif num == 2 then
			postfix = "nd"
		elseif num == 3 then
			postfix = "rd"
		end
		
		db:Query("", "rank_db_callback", string.format("SELECT Points FROM Ranks WHERE Nick = '%s';", string.gsub(p.Nick, "'", "")))
		if tonumber(RankResult) ~= 0 then
			Console_Inputf("msg %s is ranked %s%s with %s points.", p.Nick, num, postfix, RankResult)
		end
	end	
end

function Remove_Player(PlayerId)
	local p = Players[PlayerId]
	db:Query("", "", string.format("UPDATE Players SET LastSeen = '%d', JoinMsg = '%s' WHERE Nick = '%s';", os.time(os.date("*t")), p.JoinMsg, p.Nick))
	db:Query("", "", string.format("UPDATE Ranks SET Points = %d WHERE Nick = '%s';", p.Points, p.Nick));
	Players[PlayerId] = nil
end

function Player_Version(PlayerId, Version)
	local p = Players[PlayerId]
	if p ~= nil then
		p.Version = Version
	end
end

function Find_Player(Part)
	local ret = -1
	for i,p in pairs(Get_All_Players()) do
		local pName = Get_Player_Name_By_ID(p)
		if pName == Part then
			return p
		end
		
		if string.match(string.lower(pName), string.lower(Part)) ~= nil then
			if ret ~= -1 then
				return -2
			else
				ret = p
			end
		end
	end
	return ret
end

function Update_Player_Status(PlayerId, Status)
	Players[PlayerId].Status = Status
	if Status ~= "" then
		Console_Input(string.format("msg %s %s has been authorized.", Status_Name(Status), Players[PlayerId].Nick))
	end
end

function Player_Name_With_Status(PlayerId)
	local pname = Get_Player_Name_By_ID(PlayerId)
	local p = Players[PlayerId]
	if not p then
		return pname
	elseif not p.Status then
		return pname
	else
		return p.Status .. pname
	end
end	

function Get_Player_Status(PlayerId)
	local p = Players[PlayerId]
	if not p then
		return ""
	elseif not p.Status then
		return ""
	else
		return p.Status
	end
end

Is_Banned_var = -1
function sql_Get_Ban_ID_Callback(userdata, argc, data, columns)
	if tonumber(data[1]) > 0 then
		Is_Banned_var = data[1]
	end 
end

function Get_Ban_ID(PlayerId)
	local a,b,c,d = string.match(Get_IP_Address(PlayerId), "(%d+).(%d+).(%d+).(%d+)")
		if not a or not b or not c or not d then
		a = 0
		b = 0
		c = 0
		d = 0
	end
	
	db:Query("", "sql_Get_Ban_ID_Callback", string.format("SELECT ID FROM Bans WHERE Nick = '%s' or Serial = '%s' or (IPStart <= %s and IPEnd >= %s);", Players[PlayerId].Nick, Players[PlayerId].Serial, IPToLong(a,b,c,d), IPToLong(a,b,c,d)))

	local ret = Is_Banned_var
	Is_Banned_var = -1
	return tonumber(ret)
end

function Get_Ban_ID2(Nick, Serial, IP)
	local a,b,c,d = string.match(IP, "(%d+).(%d+).(%d+).(%d+)")
	if not a or not b or not c or not d then
		a = 0
		b = 0
		c = 0
		d = 0
	end
	
	db:Query("", "sql_Get_Ban_ID_Callback", string.format("SELECT ID FROM Bans WHERE Nick = '%s' or Serial = '%s' or (IPStart <= %s and IPEnd >= %s);", Nick, Serial, IPToLong(a,b,c,d), IPToLong(a,b,c,d)))

	local ret = Is_Banned_var
	Is_Banned_var = -1
	return tonumber(ret)
end


Get_Ban_Infomation_var = nil

function sql_Get_Ban_Infomation_Callback(userdata, argc, data, columns)
	Get_Ban_Infomation_var = data
end

function Get_Ban_Infomation(bID)
	db:Query("", "sql_Get_Ban_Infomation_Callback", string.format("SELECT Nick,Reason,WhoBy,Serial,IPStart,IPEnd FROM Bans WHERE ID = %d;", bID))
	
	local ret = Get_Ban_Infomation_var
	Get_Ban_Infomation_var = nil
	return ret
end

Bans_Think_Timer = tClock()

function Temp_Bans_sql_Callback(userdata, argc, data, columns)
	IRC_Sendc('p', "Ban ID #%s has been removed. (Time ended)", data[2])
	db:Query("", "", string.format("DELETE FROM Bans WHERE ID = %s;", data[2]))
	db:Query("", "", string.format("DELETE FROM TempBans WHERE ID = %s;", data[1]))
end

function Bans_Think()
	if tClock() - Bans_Think_Timer > 60000 then
		db:Query("", "Temp_Bans_sql_Callback", string.format("SELECT * FROM TempBans WHERE Until <= %d;", os.time(os.date("*t"))))
		Bans_Think_Timer = tClock()
	end
end

