Documentation for this module may be created at Modulenn:Oberour/doc

local p = {}
local lang = "br"
local NS = mw.title.getCurrentTitle().namespace
local CatNS = mw.site.namespaces.Category.name
local langObj = mw.language.new(lang)

function p.main(frame)
	
	local entity = nil
	if frame.args.wd ~= nil and frame.args.wd ~= "" then entity = frame.args.wd end
	
	-- data from Wikidata
	local item = mw.wikibase.getEntity(entity)
	local html = mw.html.create()
	
	if item == nil then
		local e = "Ar bajenn-mañ n’eo ket liammet ouzh elfenn ebet"
		if entity ~= nil then
			e = "N'eus ket an elfenn "..entity.." war Wikidata."
		end
		html:wikitext("'''Fazi!''' " .. e)
		if NS == 104 then
			html:wikitext('[['..CatNS..':Pajennoù « Oberour » hep elfenn Wikidata]]')
		end
		return html
	end
	
	if NS == 104 then
		html:wikitext('[['..CatNS..':Oberourien]]')
	end

	local fullnameWD = item:getLabel(lang)
	local fullnameWD_fr = item:getLabel("fr")
	if fullnameWD == nil then fullnameWD = "?" end
	if fullnameWD_fr == nil then 
		fullnameWD_fr = "" 
	else 
		fullnameWD_fr = frame:expandTemplate{ title = 'lang', args = { 'fr', fullnameWD_fr } }
		fullnameWD_fr = "''"..fullnameWD_fr.."'' e galleg, " 
	end
	
	-- Image
	local imgWD = item:getBestStatements('P18')
	if imgWD[1] ~= nil and imgWD[1].mainsnak.datavalue ~= nil then
		img = imgWD[1].mainsnak.datavalue.value
		html:wikitext( '[[File:'..img..'|thumb|right|200px|'..fullnameWD..']]' )
	end
	
	html:wikitext("'''"..fullnameWD.."'''")
	
	local akaWD = item:getBestStatements('P742')
	local i = 1
	for i, _ in ipairs(akaWD) do
		if akaWD[i].mainsnak.datavalue ~= nil then
			html:wikitext(" pe '''"..akaWD[i].mainsnak.datavalue.value.."'''")
			if i == 10 then break end
		end
	end
	
	local arrtmp = {} -- tableau temporaire
	
	-- On récupère les dates de naissance
	local birthWD = item:getAllStatements('P569')
	for i, _ in ipairs(birthWD) do
		if birthWD[i].mainsnak.datavalue ~= nil then
			local date = p.formatDate(birthWD[i])
			local cat = true
			if date == nil then date = "?" end
			
			if birthWD[i].rank == "preferred" then
				table.insert(arrtmp, 1, date)
			elseif birthWD[i].rank == "normal" then
				table.insert(arrtmp, date)
			else
				cat = false
			end
			
			if NS == 104 and cat and date~=nil and birthWD[i].mainsnak.datavalue.value.precision >= 7 then
				local year
				if birthWD[i].mainsnak.datavalue.value.precision > 9 then
					year = langObj:formatDate('Y', birthWD[i].mainsnak.datavalue.value.time)
				else
					year = p.formatDate(birthWD[i])
				end 
				html:wikitext('[['..CatNS..':Ganedigezhioù '..year..']]')
			end
		end
	end
	birthWD = table.concat(arrtmp, ", ")
	arrtmp = {} -- on vide le tableau temporaire
	
	-- On récupère les dates de décès
	local deathWD = item:getAllStatements('P570')
	for i, _ in ipairs(deathWD) do
		if deathWD[i].mainsnak.datavalue ~= nil then
			local date = p.formatDate(deathWD[i])
			local cat = true
			if date == nil then date = "?" end
			
			if deathWD[i].rank == "preferred" then
				table.insert(arrtmp, 1, date)
			elseif deathWD[i].rank == "normal" then
				table.insert(arrtmp, date)
			else
				cat = false
			end
			
			if NS == 104 and cat and date~=nil and deathWD[i].mainsnak.datavalue.value.precision >= 7 then
				local year
				if deathWD[i].mainsnak.datavalue.value.precision > 9 then
					year = langObj:formatDate('Y', deathWD[i].mainsnak.datavalue.value.time)
				else
					year = p.formatDate(deathWD[i])
				end 
				html:wikitext('[['..CatNS..':Marvioù '..year..']]')
			end
		end
	end
	deathWD = table.concat(arrtmp, ", ")
	
	html:wikitext(" ("..fullnameWD_fr..birthWD.." — "..deathWD..")")

	-- clé de tri
	local sortkey
	if frame.args["alc'hwez diforc'hañ"] ~= nil and frame.args["alc'hwez diforc'hañ"] ~="" then
		sortkey = frame.args["alc'hwez diforc'hañ"]
	else
		sortkey = p.getSortKey(fullnameWD)
	end
	html:wikitext(frame:preprocess('{{DEFAULTSORT:' .. sortkey .. '}}'))

	return html
end

-- formate une date selon la précision donnée
-- @d table d'une propriété wikidata de type time
-- @return nil|string date formatée
function p.formatDate(d)
	if type(d) ~= 'table' then return nil end
	if d.mainsnak ~= nil then d=d.mainsnak end
	if d.datatype ~= 'time' then return nil end
	
	local time = d.datavalue.value.time
	
	-- date négative
	local BC = false
	if string.sub(d.datavalue.value.time, 1, 1) == "-" then
		BC = true
		-- formatDate ne traite que des dates positives
		time = '+' .. string.sub(d.datavalue.value.time, 2)
	end
	
	-- précision siecle (en nombre romain)
	-- 1899 → CEIL(18,99) → 0019 → XIX → XIXvet kantved
	-- 0899 → CEIL(8,99) → 0009 → IX → IXvet kantved
	-- 0089 → CEIL(0,89) → 0001 → I → Ivet kantved
	-- voir https://www.mediawiki.org/wiki/Help:Extension:ParserFunctions/fr##time
	if d.datavalue.value.precision == 7 then
		if BC then BC = ' kt JK' else BC = "" end
		local y = langObj:formatDate('Y', time)
		y = p.lpad(tostring(math.ceil(tonumber(y)/100)), 4, '0')
		return langObj:formatDate('xrY"vet kantved"', y) .. BC
		
	-- précision décennie
	-- 1899 → FLOOR(189.9) → 1890
	elseif d.datavalue.value.precision == 8 then
		if BC then BC = 'vers -' else BC = "" end
		local y = langObj:formatDate('Y', time)
		return BC .. tostring( math.floor(tonumber(y)/10) .. '0' )
		
	-- précision année
	-- les dates étant stockées sous la forme 2019-00-00T00:00:00Z
	-- le mois 00 est recalculée comme le mois 12 de l'année précédente
	-- il faut donc rajouté 1 an
	elseif d.datavalue.value.precision == 9 then
		if BC then BC = '-' else BC = "" end
		local y = tonumber(langObj:formatDate('Y', time)) -- pour éviter des années comme 0629
		return BC .. tostring(y+1)
		
	-- précision mois
	-- les dates étant stockées sous la forme 2019-03-00T00:00:00Z
	-- le jour 00 est recalculée comme le mois 02 de l'année en cours
	-- et si le mois est 01 come le mois 12 de l'année précédente
	-- il faut donc rajouté 1 jour
	elseif d.datavalue.value.precision == 10 then
		return langObj:formatDate('F Y', time .. '+1 day')
		
	-- précision jour
	elseif d.datavalue.value.precision == 11 then
		return langObj:formatDate('j "a viz" F Y', time)
		
	else
		return nil
	end
end

-- Détermine la clé de tri à partir d'une chaîne correspondant au nom complet (prénom + nom de famille)
-- On considère naïvement que le dernier mot correspond au nom de famille, et donc la clé de tri
-- Se baser sur la propriété P734 ne semble pas approprié pour le breton
-- voir https://br.wikisource.org/w/index.php?title=Kaozeadenn_Implijer:VIGNERON&oldid=153087#Patrom:Oberour
-- @str string chaîne à traiter
-- @return string dernier mot de la chaîne
function p.getSortKey (str)
    local parts = mw.text.split(str, ' ', true)
    return parts[#parts] .. ',' .. table.concat(parts, " ", 1, (#parts-1))
end

-- Complète une chaîne par la gauche jusqu'à une taille donnée
-- @str string chaîne à compléter
-- @len int longueur totale de la chaîne
-- @char string caractère à ajouter
-- @return string chaîne complétée
-- TODO Serait plus à sa place dans un futur module string
function p.lpad (str, len, char)
    if char == nil then char = ' ' end
    return string.rep(char, len - #str) .. str
end

return p