minetest.register_privilege("electoraljudge",  {
	description=modEUrn.translate("Allows you to configure the Electronic Urn."), 
	give_to_singleplayer=false,
})

modEUrn.debug = function(text, playername)
	if text ~= nil
		and type(text) == "string"
		and text ~= ""
	then
		if minetest.settings:get_bool("eurn.debug") then
			if playername ~= nil
				and type(playername) == "string"
				and playername ~= ""
			then
				local player = minetest.get_player_by_name(playername)
				if player ~=nil and player:is_player() then
					minetest.chat_send_player(
						playername, text
					)
					minetest.log('action',"["..modEUrn.modname:upper()..":DEBUG:"..playername.."] "..text)
				else
					minetest.log('error',
						"["..modEUrn.modname:upper()..":DEBUG] "
						..modEUrn.translate(
							"Unable to address debug for player '%s'."
						):format(dump(playername))
					)
					minetest.log('action',"["..modEUrn.modname:upper()..":DEBUG] "..text)
				end
			else
				minetest.chat_send_all(text)
				minetest.log('action',"["..modEUrn.modname:upper()..":DEBUG] "..text)
			end
		end
	end
end

modEUrn.unsortTableByValue = function(tbl)
	if type(tbl)~="table" then
		tbl = {}
	end

	--modEUrn.debug("modEUrn.unsortTableByValue(): tbl = "..dump(tbl))
	table.sort(tbl, function(a, b) 
		local aaa = "a(%s) > b(%s)"
		aaa = aaa:format(dump(a), dump(b))
		modEUrn.debug(aaa)
		return a >= b 
	end)
	--modEUrn.debug("modEUrn.unsortTableByValue(): tbl = "..dump(tbl))
	
	return tbl
end

modEUrn.sortTableLenght = function(tbl)
	local count = 0
	--modEUrn.debug("t = "..dump(t))
   for _ in pairs(tbl) do 
   	count = count + 1 
   end
   return count
end

modEUrn.handler = {
	elected = { 
		president = {
			name = "", --name of the elected candidate.
			when = 0, --when the candidate was elected.
			--voters = { }, --names of voters who voted for this elected candidate.
		},
	},
	candidates = { 
		president = { }, --modEUrn.handler.candidates.president[<candidatename>] = <when> | If the candidate has not updated his candidacy for more than 6 months, he loses his candidacy application.
	},
	--]]
	voters = { }, --modEUrn.handler.voters[playername]
	--month_counted = 0
}

modEUrn.MinPlayedHours = tonumber(minetest.settings:get("eurn.voter.min_played_hours") or 90) -- value in hours
modEUrn.save_compressed = minetest.settings:get_bool("eurn.save_compressed") ~= false

modEUrn.doSave = function()
	local file = io.open(modEUrn.urlTabela, "w")
	if file then
		local handler = minetest.serialize(modEUrn.handler)
		if modEUrn.save_compressed then
			handler = minetest.encode_base64(handler)
		end
		file:write(handler)
		file:close()
		minetest.log('action',"[E-URN] "..modEUrn.translate("Database saved in file '%s'!"):format(modEUrn.urlTabela))
	else
		minetest.log('error',"[E-URN:ERRO] "..modEUrn.translate("The file '%s' is not in table format!"):format(modEUrn.urlTabela))
	end
end

modEUrn.doLoad = function()
	local file = io.open(modEUrn.urlTabela, "r")
	if file then
		local handler = file:read("*all")
		if modEUrn.save_compressed then
			handler = minetest.decode_base64(handler)
		end
		handler = minetest.deserialize(handler) --transforma string to table
		file:close()
		if not handler or type(handler) ~= "table" then
			minetest.log('error',"[E-URN:ERRO] "..modEUrn.translate("The file '%s' is not in table format!"):format(modEUrn.urlTabela))
			return { }
		else
			modEUrn.handler = handler
			minetest.log('action',"[E-URN] "..modEUrn.translate("Database '%s' loaded!"):format(modEUrn.urlTabela))
		end
	end
end

modEUrn.on_leaveplayer = function(player)
	local playername = player:get_player_name()
	local now = os.time() --Em milisegundos
	if modEUrn.handler.voters[playername]~=nil and type(modEUrn.handler.voters[playername]) == "table" then
		if modEUrn.handler.voters[playername].times.login~=nil and type(modEUrn.handler.voters[playername].times.login) == "number" and modEUrn.handler.voters[playername].times.login > 0 then
			if modEUrn.handler.voters[playername].times.played~=nil and type(modEUrn.handler.voters[playername].times.played) == "number" and modEUrn.handler.voters[playername].times.played > 0 then
				modEUrn.handler.voters[playername].times.played = modEUrn.handler.voters[playername].times.played + (now - modEUrn.handler.voters[playername].times.login)
			else
				modEUrn.handler.voters[playername].times.played = (now - modEUrn.handler.voters[playername].times.login)
			end
			modEUrn.handler.voters[playername].times.login = 0
			modEUrn.handler.voters[playername].times.logout = now
		end
	else
		minetest.log('error',"[E-URN:ERROR:ONLEAVEPLAYER] "..modEUrn.translate("Impossible to register logout for player '%s' !"):format(dump(player)))
	end
end

modEUrn.getPresidentName = function()
	if type(modEUrn.handler.elected.president.name)~="nil"
		and modEUrn.handler.elected.president.name ~= ""
	then
		return modEUrn.handler.elected.president.name
	end
	return ""
end

modEUrn.doCheckDataBase = function(candidatename)
   --modEUrn.handler.elected
   if type(modEUrn.handler.elected)=="nil" then
   	modEUrn.handler.elected = { }
   end
   if type(modEUrn.handler.elected.president)=="nil" then
   	modEUrn.handler.elected.president = { }
   end
   if type(modEUrn.handler.elected.president.name)=="nil" then
      modEUrn.handler.elected.president.name = ""
   end
   if type(modEUrn.handler.elected.president.when)=="nil" then
      modEUrn.handler.elected.president.when = 0
   end
   
   --modEUrn.handler.candidates
   if type(modEUrn.handler.candidates)=="nil" then
		modEUrn.handler.candidates = { }
   end
   if type(modEUrn.handler.candidates.president)=="nil" then
		modEUrn.handler.candidates.president = { }
   end
   
   if type(candidatename)=="string" and candidatename~="" then
      if type(modEUrn.handler.candidates.president[candidatename])=="nil" then
      	modEUrn.handler.candidates.president[candidatename] = { }
      end
      if type(modEUrn.handler.candidates.president[candidatename].political_campaign)=="nil" then
      	modEUrn.handler.candidates.president[candidatename].political_campaign = "There are no campaign data about this political candidate."
      end
      if type(modEUrn.handler.candidates.president[candidatename].voters)=="nil" then
      	modEUrn.handler.candidates.president[candidatename].voters = { }
      end
   end
   
end

modEUrn.doPresident = function(playername, candidatename)
	if minetest.player_exists(candidatename) then
   	modEUrn.doCheckDataBase(candidatename)
      modEUrn.handler.elected.president.name = candidatename
      modEUrn.handler.elected.president.when = os.time() --Em milisegundos
      modEUrn.doVote(playername, candidatename)
		return true
	else
		minetest.chat_send_player(
      	playername, 
      	--os.date("%Y-%m-%d %Hh:%Mm:%Ss", now) ..
      	core.colorize("#FF0000", "[E-URN]").." "
      	..modEUrn.translate("The name '%s' is not the player name registered on the server!"):format(candidatename)
      )
	end
	return false
end

modEUrn.doPresidentCandidate = function(playername, candidatename, political_campaign)
	if minetest.player_exists(candidatename) then
   	--local now = os.time() --Em milisegundos
   	if type(political_campaign)~="string" 
   		or political_campaign == ""
   	then
   		political_campaign = "There are no campaign data about this political candidate."
   	end
      
		modEUrn.doCheckDataBase(candidatename)
      modEUrn.handler.candidates.president[candidatename].political_campaign = political_campaign
		return true
	else
		minetest.chat_send_player(
      	playername, 
      	--os.date("%Y-%m-%d %Hh:%Mm:%Ss", now) ..
      	core.colorize("#FF0000", "[E-URN]").." "
      	..modEUrn.translate("The name '%s' is not the player name registered on the server!"):format(candidatename)
      )
	end
	return false
end

modEUrn.getPresCandCampaign = function(candidatename)
	local political_campaign = "There are no campaign data about this political candidate."
	--modEUrn.debug("candidatename="..dump(candidatename))
	if type(modEUrn.handler.candidates.president[candidatename])=="table"
		and type(modEUrn.handler.candidates.president[candidatename].political_campaign)=="string"
		and modEUrn.handler.candidates.president[candidatename].political_campaign ~= ""
	then
		political_campaign = modEUrn.handler.candidates.president[candidatename].political_campaign
	end
	return political_campaign
end

modEUrn.getPresidentCandidates = function()
	local cands = { }
	for iCandPresName, iCandPresValue in pairs(modEUrn.handler.candidates.president) do
		table.insert(cands, iCandPresName)
		--cands:insert(iCandPresName)
	end
	return cands
end

modEUrn.showPresCandCampaign = function(playername, candidatename)
   if type(candidatename)=="string" and candidatename ~= "" then --Se o nome do candidato foi dito
      if minetest.player_exists(candidatename) then --Se existe algum jogador o nome que foi dito
      	if type(modEUrn.handler.candidates.president[candidatename])=="table" then --Se foi algum candidato registrado.
      		local player = minetest.get_player_by_name(playername)
		   	if player:is_player()  then --verifica se o jogador está online ou por terminal
		   		modEUrn.FormSpecs.showFormInfoCampaign(playername, candidatename)
		   	else
		   		minetest.chat_send_player(
				   	playername, 
				   	core.colorize("#00FF00", "[E-URN]").." "
				   	..core.colorize("#888888", 
				   		modEUrn.translate("Candidate Name")..": "
				   	)
				   	..core.colorize("#00FF00", candidatename)
				   )
				   local Campaign = modEUrn.getPresCandCampaign(candidatename)
					if type(Campaign)=="string" and Campaign~="" then
					   minetest.chat_send_player(
					   	playername, 
					   	core.colorize("#00FF00", "[E-URN]").." "
					   	..core.colorize("#888888", 
					   		modEUrn.translate("Candidate Campaign")..": "
					   	)
					   	..Campaign
					   )
					end
				end
      	else
      		minetest.chat_send_player(
		      	playername, 
		      	core.colorize("#FF0000", "[E-URN]").." "
		      	..modEUrn.translate("Player %s is not registered as a candidate for president!"):format(candidatename)
		      )
      	end
   	else
			minetest.chat_send_player(
	      	playername, 
	      	--os.date("%Y-%m-%d %Hh:%Mm:%Ss", now) ..
	      	core.colorize("#FF0000", "[E-URN]").." "
	      	..modEUrn.translate("The name '%s' is not the player name registered on the server!"):format(candidatename)
	      )
      end
	else
		minetest.chat_send_player(
      	playername, 
      	--os.date("%Y-%m-%d %Hh:%Mm:%Ss", now) ..
      	core.colorize("#FF0000", "[E-URN]").." "
      	..modEUrn.translate("Please enter the name of the candidate you wish to display the campaign!").."\n"
      	..core.colorize("#888888", "Syntaxe: ")
      	..core.colorize("#00FFFF", 
      		"/campaign <"..modEUrn.translate("candidate_name")..">"
      	)
      )
	end
end

modEUrn.doUnvote = function(playername)
   modEUrn.doCheckDataBase(candidatename)
   for iCandPresName, _ in pairs(modEUrn.handler.candidates.president) do
		--modEUrn.debug("iCandPresName = "..iCandPresName)
		if type(modEUrn.handler.candidates.president[iCandPresName].voters[playername])~="nil" then
			--modEUrn.debug("modEUrn.handler.candidates.president["..iCandPresName.."].voters = "..dump(modEUrn.handler.candidates.president[iCandPresName].voters))  
			modEUrn.handler.candidates.president[iCandPresName].voters[playername] = nil
			return true, modEUrn.translate("You unvoted for the presidential candidate!")
		end
   end
   return false, modEUrn.translate("You can't have registered vote!")
end

--[[  ]]
modEUrn.doVote = function(playername, candidatename)
   if type(modEUrn.handler.voters[playername])=="table" then
		local voterTimePlayed = modEUrn.handler.voters[playername].times.played --in secounds
		if voterTimePlayed >= modEUrn.MinPlayedHours * (60*60) then
			if type(candidatename)=="string" and candidatename ~= "" then
				if minetest.player_exists(candidatename) then
					if type(modEUrn.handler.candidates.president[candidatename])=="table" then
						modEUrn.doUnvote(playername)
						modEUrn.handler.candidates.president[candidatename].voters[playername] = os.time() --Agora em milisegundos
					   return true, modEUrn.translate("You voted for the candidate: ")..core.colorize("#00FF00", candidatename)
					else
					   return false, modEUrn.translate("Player '%s' is not registered as a candidate for president!"):format(candidatename)
					end
				else
				   return false, modEUrn.translate("The name '%s' is not the player name registered on the server!"):format(candidatename)
				end
			else
			   return false, modEUrn.translate("Please enter the name of the presidential candidate you wish to vote!").."\n"..core.colorize("#888888", "Syntaxe: ")..core.colorize("#00FFFF", "/vote <"..modEUrn.translate("candidate_name")..">")
			end
		else
		   return false, modEUrn.translate("You have not yet played the minimum number of hours to become a presidential voter. (Minimum %02d hours)"):format(modEUrn.MinPlayedHours)
		end
	else
	   return false, modEUrn.translate("Your name is not registered as a voter.")
   end
end
--]]

modEUrn.doCheckPresident = function()
	--Verifica registra quem será o presidente pela maioria de voto do candidato.
	if modEUrn.sortTableLenght(modEUrn.handler.candidates.president) >= 1 then
		local maxVotes = 0
		local PresMaxVoted = ""
		for iCandPresName, _ in pairs(modEUrn.handler.candidates.president) do
			local numVotes = modEUrn.sortTableLenght(modEUrn.handler.candidates.president[iCandPresName].voters)
			if numVotes >= 1 and maxVotes < numVotes  then
				maxVotes = numVotes
				PresMaxVoted = iCandPresName
			end
		end
		if maxVotes>=1 and PresMaxVoted~="" then
		   modEUrn.doCheckDataBase()
			modEUrn.handler.elected.president.name = PresMaxVoted
			modEUrn.handler.elected.president.when = os.time() --Agora em milisegundos
			
			return true, modEUrn.translate("Player %s has been named the president of this server!"):format(dump(PresMaxVoted))
			--[[
				Falta: 
					* enviar email para todos os jogadores anunciando quem ganhou a eleição do mês.
					* Faze o som de vitória
			--]]
		else
		   return false, modEUrn.translate("There are no votes registered!")
		end 
	else
	   return false, modEUrn.translate("There are no candidates registered!")
	end
end

minetest.register_on_leaveplayer(function(player)
	modEUrn.on_leaveplayer(player)
	modEUrn.doSave()
end)

--[[
minetest.register_on_newplayer(function(player)

end)
--]]

--[[
minetest.register_on_prejoinplayer(function(name, ip)

end)
--]]

minetest.register_on_joinplayer(function(player)
	local playername = player:get_player_name()
	local now = os.time() --Em milisegundos
	if playername~=nil and type(playername)=="string" and playername~="" then
		if modEUrn.handler.voters[playername]==nil then
			modEUrn.handler.voters[playername] = {
				times ={
					register = now,
					played = 0,
					login = now,
					logout = 0,
				},
			}
		end
		modEUrn.handler.voters[playername].times.login = now
		modEUrn.handler.voters[playername].times.logout = 0
	else
		minetest.log('error',"[E-URN:ERROR:ONJOINPLAYER] "..modEUrn.translate("Impossible to register login for player '%s' !"):format(dump(player)))
	end
end)

minetest.register_on_shutdown(function()
	local players = minetest.get_connected_players()
	if #players >= 1 then
		for _, player in ipairs(players) do
			modEUrn.on_leaveplayer(player)
			local playername = player:get_player_name()
			--minetest.disconnect_player(name, [reason])
			minetest.disconnect_player(playername)
		end	
	end
	modEUrn.doSave()
	--minetest.log('action',"[E-URN] "..modEUrn.translate("Saving the database from all players in the file '%s'!"):format(modEUrn.urlTabela))
end)

--[[  ]]
minetest.after(3.5, function()
	minetest.register_globalstep(function(dtime)
		--local presname = modEUrn.handler.elected.president.name
		local presname = modEUrn.getPresidentName()
		if type(presname)=="string" and presname~="" then
			local mesAtual = os.date("%m", os.time())
			local mesChecked = os.date("%m", tonumber(modEUrn.handler.elected.president.when))
			if mesChecked ~= mesAtual then
				local result, cause = modEUrn.doCheckPresident()
   	   	if result == true then
   	   	   minetest.chat_send_all(
   					core.colorize("#00FF00", "[E-URN]").." "..cause
   				)
   	   	else
   	   	   minetest.chat_send_player(
   					playername, 
   					core.colorize("#FF0000", "[E-URN]").." "..cause
   				)
   	   	end
			end
		end
	end)
end)
--]]